Description
cTrader cBot with multiple pending orders and Trailing Stop functionality.
This cbot is not the final version but it describes the principle of my cbot. I have 2 cbots running in live account, RSI_bot and XAU_bot. If you are interested, you can see my account:
https://ct.spotware.com/investor/HFWsCkwNjBM
More information or using my other cBots, email to superalgo247@gmail.com
or
using cAlgo.API;
using System;
using cAlgo.API.Internals;
using cAlgo.Indicators;
using System.Linq;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class PendingOrderTiengthu : Robot
{
[Parameter("Buy Stop", DefaultValue = true)]
public bool BuyStopEnabled { get; set; }
[Parameter("Sell Stop", DefaultValue = true)]
public bool SellStopEnabled { get; set; }
[Parameter("Buy Limit", DefaultValue = true)]
public bool BuyLimitEnabled { get; set; }
[Parameter("Sell Limit", DefaultValue = true)]
public bool SellLimitEnabled { get; set; }
[Parameter("Volume (Lots)", DefaultValue = 0.01)]
public double FirstVolume { get; set; }
[Parameter("Number of Orders", DefaultValue = 2, MinValue = 1)]
public int NumberOfOrders { get; set; }
[Parameter("Distance (Pips)", DefaultValue = 50, MinValue = 1)]
public double Distance { get; set; }
[Parameter("Distance Between Orders (Pips)", DefaultValue = 100, MinValue = 1)]
public double DistanceBetween { get; set; }
[Parameter("Label", DefaultValue = "Pending_TiengThu")]
public string Label { get; set; }
[Parameter("SL (Pips)", DefaultValue = 0, MinValue = 0)]
public double StopInPips { get; set; }
[Parameter("TP (Pips)", DefaultValue = 50, MinValue = 0)]
public double TakeProfit { get; set; }
[Parameter("Enable Trailing Stop", DefaultValue = true)]
public bool EnableTrailingStop { get; set; }
[Parameter("Trailing Stop Trigger (Pips)", DefaultValue = 50)]
public int TrailingStopTrigger { get; set; }
[Parameter("Trailing Stop Distance (Pips)", DefaultValue = 5)]
public int TrailingStopDistance { get; set; }
protected override void OnStart()
{
var volumeInUnits = Symbol.QuantityToVolumeInUnits(FirstVolume);
Distance *= Symbol.PipSize;
DistanceBetween *= Symbol.PipSize;
var stopLoss = StopInPips == 0 ? null : (double?)StopInPips;
var takeProfit = TakeProfit == 0 ? null : (double?)TakeProfit;
for (int i = 0; i < NumberOfOrders; i++)
{
double orderDistance = Distance + i * DistanceBetween;
double orderPrice;
if (BuyStopEnabled)
{
orderPrice = Symbol.Ask + orderDistance;
PlaceStopOrder(TradeType.Buy, orderPrice, volumeInUnits, stopLoss, takeProfit);
}
if (SellStopEnabled)
{
orderPrice = Symbol.Bid - orderDistance;
PlaceStopOrder(TradeType.Sell, orderPrice, volumeInUnits, stopLoss, takeProfit);
}
if (BuyLimitEnabled)
{
orderPrice = Symbol.Ask - orderDistance;
PlaceLimitOrder(TradeType.Buy, orderPrice, volumeInUnits, stopLoss, takeProfit);
}
if (SellLimitEnabled)
{
orderPrice = Symbol.Bid + orderDistance;
PlaceLimitOrder(TradeType.Sell, orderPrice, volumeInUnits, stopLoss, takeProfit);
}
}
}
protected override void OnBar()
{
}
protected override void OnTick()
{
UpdatePositionsWithLabel(Label);
if (EnableTrailingStop)
{
foreach (var position in Positions)
{
if (position.SymbolName == SymbolName)
{
if (position.Pips > TrailingStopTrigger)
{
SetTrailingStop(position);
}
}
}
}
}
private void SetTrailingStop(Position position)
{
double newStopLossPrice;
if (position.TradeType == TradeType.Buy)
{
newStopLossPrice = Symbol.Bid - TrailingStopDistance * Symbol.PipSize;
if (position.StopLoss == null || newStopLossPrice > position.StopLoss)
{
ModifyPosition(position, newStopLossPrice, position.TakeProfit);
}
}
else if (position.TradeType == TradeType.Sell)
{
newStopLossPrice = Symbol.Ask + TrailingStopDistance * Symbol.PipSize;
if (position.StopLoss == null || newStopLossPrice < position.StopLoss)
{
ModifyPosition(position, newStopLossPrice, position.TakeProfit);
}
}
}
private void PlaceStopOrder(TradeType tradeType, double stopPrice, double volumeInUnits, double? stopLoss, double? takeProfit)
{
TradeResult result = PlaceStopOrder(tradeType, SymbolName, volumeInUnits, stopPrice, Label, stopLoss, takeProfit, null);
if (!result.IsSuccessful) Print("Error: ", result.Error);
}
private void PlaceLimitOrder(TradeType tradeType, double limitPrice, double volumeInUnits, double? stopLoss, double? takeProfit)
{
TradeResult result = PlaceLimitOrder(tradeType, SymbolName, volumeInUnits, limitPrice, Label, stopLoss, takeProfit, null);
if (!result.IsSuccessful) Print("Error: ", result.Error);
}
private void UpdatePositionsWithLabel(string label)
{
var positionsWithLabel = Positions
.Where(p => p.Label == label && p.SymbolName == SymbolName)
.ToList();
if (positionsWithLabel.Count == 0)
return;
double totalVolume = positionsWithLabel.Sum(p => p.VolumeInUnits);
double totalEntryPrice = positionsWithLabel.Sum(p => p.EntryPrice * p.VolumeInUnits);
double averageEntryPrice = totalEntryPrice / totalVolume;
double newTakeProfitPrice;
foreach (var position in positionsWithLabel)
{
if (position.TradeType == TradeType.Buy)
{
newTakeProfitPrice = averageEntryPrice + TakeProfit * Symbol.PipSize;
}
else
{
newTakeProfitPrice = averageEntryPrice - TakeProfit * Symbol.PipSize;
}
if (position.TakeProfit != newTakeProfitPrice)
{
ModifyPosition(position, position.StopLoss, newTakeProfitPrice);
}
}
}
}
}
ForexViet
Joined on 05.05.2023
- Distribution: Free
- Language: C#
- Trading platform: cTrader Automate
- File name: 23.8_Pending_TiengThu_withSourceCode.algo
- Rating: 5
- Installs: 279
- Modified: 22/08/2024 23:25
Comments
Are there any special settings that need to be applied? It's a good robot for areas of strong price movement, where the price moves in all directions.
is there a new, improved version?
This cbot is semi-automatic, which means if you have built your own indicator system, you can use it to place pending orders, manage open orders and close them. In the code, I programmed the cbot to manage only profitable open positions, and for losing positions, if you want, you can set SL for each pending Order.
@emaile2008 - on looking at the source code, this is definitely due to all the activity taking place on the OnStart() event, rather than being OnBar(). You could refactor everything out to OnBar() and add further conditions so as to play when required.
after number of orders parameter finish all orders, it will not place any new orders unless you stop cbot and run it again
i think if there is option to reset orders like every day or every 4 hours it will be great
Hi, agbemefa.apelete
I am the author of this cbot, now there are new versions of cbot. If you are interested, please contact me via the link https://t.me/+TW8UYDE-R242NzZl .
You can also see my trading results when using cbot cloud : https://ct.spotware.com/investor/HFWsCkwNjBM