Description
cTrader cBot with RSI entry, place pending stop orders, average TP or Trailing Stop, modify volume, Time expired, …and many other functions.
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
https://t.me/+TW8UYDE-R242NzZl
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.Indicators;
using cAlgo.API.Indicators;
using System;
using System.Linq;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class RSI_Tiengthu_Bot : Robot
{
[Parameter("RSI Period", DefaultValue = 14)]
public int RsiPeriod { get; set; }
[Parameter("RSI Source")]
public DataSeries RsiSource { get; set; }
[Parameter("Before", DefaultValue = true)]
public bool Before { get; set; }
[Parameter("Buy", DefaultValue = true)]
public bool BuyEnabled { get; set; }
[Parameter("Sell", DefaultValue = true)]
public bool SellEnabled { get; set; }
[Parameter("Buy Stop", DefaultValue = true)]
public bool BuyStop { get; set; }
[Parameter("Sell Stop", DefaultValue = true)]
public bool SellStop { get; set; }
[Parameter("Buy Limit", DefaultValue = false)]
public bool BuyLimit { get; set; }
[Parameter("Sell Limit", DefaultValue = false)]
public bool SellLimit { get; set; }
[Parameter("First Volume (Lots)", DefaultValue = 0.02, MinValue = 0.01)]
public double FirstVolume { get; set; }
[Parameter("Take Profit (Pips)", DefaultValue = 50)]
public int TakeProfit { get; set; }
[Parameter("Label", DefaultValue = "RSI_TiengThu")]
public string Label { get; set; }
[Parameter("Enable T- Stop", DefaultValue = false)]
public bool EnableTrailingStop { get; set; }
[Parameter("T-Stop Trigger (Pips)", DefaultValue = 30)]
public int TrailingStopTrigger { get; set; }
[Parameter("T-Stop Distance (Pips)", DefaultValue = 5)]
public int TrailingStopDistance { get; set; }
[Parameter("Distance Order", DefaultValue = 10)]
public int Distance { get; set; }
[Parameter("Distance between", DefaultValue = 15)]
public int DistanceBetween { get; set; }
[Parameter("Double Volume", DefaultValue = true)]
public bool DoubleVolume { get; set; }
[Parameter("Max Lots", DefaultValue = 0.8)]
public double MaxLots { get; set; }
[Parameter("Distance Double", DefaultValue = 100)]
public int DistanceDouble { get; set; }
private DateTime _expirationTime;
private RelativeStrengthIndex _rsi;
private double _previousRsiValue;
protected override void OnStart()
{
_expirationTime = new DateTime (2124,10,1,0,0,0);
_rsi = Indicators.RelativeStrengthIndex(RsiSource, RsiPeriod);
_previousRsiValue = _rsi.Result.Last(1);
}
protected override void OnBar()
{
var currentRsiValue = _rsi.Result.Last(1);
var BuypositionsWithLabel = Positions
.Where(p => p.Label == Label && p.SymbolName == SymbolName && p.TradeType == TradeType.Buy)
.ToList();
if (!Before && BuypositionsWithLabel.Count == 0)
{
CheckAndExecuteBuyOrders(_previousRsiValue, currentRsiValue);
}
if (Before && BuypositionsWithLabel.Count == 0)
{
CheckAndExecuteBuyOrdersStop(_previousRsiValue, currentRsiValue);
}
var SellpositionsWithLabel = Positions
.Where(p => p.Label == Label && p.SymbolName == SymbolName && p.TradeType == TradeType.Sell)
.ToList();
if (!Before && SellpositionsWithLabel.Count == 0)
{
CheckAndExecuteSellOrders(_previousRsiValue, currentRsiValue);
}
if (Before && SellpositionsWithLabel.Count == 0)
{
CheckAndExecuteSellOrdersStop(_previousRsiValue, currentRsiValue);
}
_previousRsiValue = currentRsiValue;
}
protected override void OnTick()
{
if (Server.Time >= _expirationTime)
{
Stop();
}
UpdatePositionsWithLabel(Label);
if (EnableTrailingStop)
{
foreach (var position in Positions)
{
if (position.SymbolName == SymbolName)
{
if (position.Pips >= TrailingStopTrigger)
{
SetTrailingStop(position);
}
}
}
}
ManageSellOrder();
ManageBuyOrder();
if (DoubleVolume)
{
ModifySellVolume(Label);
ModifyBuyVolume(Label);
}
}
protected override void OnStop()
{
Print(" Bot has stop because Time expired ");
}
private void CheckAndExecuteBuyOrders(double previousRsiValue, double currentRsiValue)
{
if ( BuyEnabled && previousRsiValue < 30 && currentRsiValue >= 30)
{
ExecuteMarketOrder(TradeType.Buy, SymbolName, Symbol.NormalizeVolumeInUnits(Symbol.QuantityToVolumeInUnits(FirstVolume)), Label);
}
}
private void CheckAndExecuteSellOrders(double previousRsiValue, double currentRsiValue)
{
if ( SellEnabled && previousRsiValue > 70 && currentRsiValue < 70)
{
ExecuteMarketOrder(TradeType.Sell, SymbolName, Symbol.NormalizeVolumeInUnits(Symbol.QuantityToVolumeInUnits(FirstVolume)), Label);
}
}
private void CheckAndExecuteBuyOrdersStop(double previousRsiValue, double currentRsiValue)
{
if ( BuyEnabled && previousRsiValue > 30 && currentRsiValue <= 30)
{
ExecuteMarketOrder(TradeType.Buy, SymbolName, Symbol.NormalizeVolumeInUnits(Symbol.QuantityToVolumeInUnits(FirstVolume)), Label);
}
}
private void CheckAndExecuteSellOrdersStop(double previousRsiValue, double currentRsiValue)
{
if ( SellEnabled && previousRsiValue < 70 && currentRsiValue >= 70)
{
ExecuteMarketOrder(TradeType.Sell, SymbolName, Symbol.NormalizeVolumeInUnits(Symbol.QuantityToVolumeInUnits(FirstVolume)), Label);
}
}
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);
}
}
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 UpdatePositionsWithLabel(string label)
{
var BuypositionsWithLabel = Positions
.Where(p => p.Label == label && p.SymbolName == SymbolName && p.TradeType == TradeType.Buy )
.ToList();
var SellpositionsWithLabel = Positions
.Where(p => p.Label == label && p.SymbolName == SymbolName && p.TradeType == TradeType.Sell )
.ToList();
if (BuypositionsWithLabel.Count == 0)
{
Print ("No Buy to updateposition ");
}
else
{
double totalBuyVolume = BuypositionsWithLabel.Sum(p => p.VolumeInUnits);
double totalBuyEntryPrice = BuypositionsWithLabel.Sum(p => p.EntryPrice * p.VolumeInUnits);
double averageBuyEntryPrice = totalBuyEntryPrice / totalBuyVolume;
double newTakeBuyProfitPrice = averageBuyEntryPrice + TakeProfit * Symbol.PipSize;
foreach (var position in BuypositionsWithLabel)
{
if (position.TakeProfit != newTakeBuyProfitPrice)
{
ModifyPosition(position, position.StopLoss, newTakeBuyProfitPrice);
}
}
}
if (SellpositionsWithLabel.Count == 0)
{
Print ("No Sell to updateposition ");
}
else
{
double totalSellVolume = SellpositionsWithLabel.Sum(p => p.VolumeInUnits);
double totalSellEntryPrice = SellpositionsWithLabel.Sum(p => p.EntryPrice * p.VolumeInUnits);
double averageSellEntryPrice = totalSellEntryPrice / totalSellVolume;
double newTakeSellProfitPrice = averageSellEntryPrice - TakeProfit * Symbol.PipSize;
foreach (var position in SellpositionsWithLabel)
{
if (position.TakeProfit != newTakeSellProfitPrice)
{
ModifyPosition(position, position.StopLoss, newTakeSellProfitPrice);
}
}
}
}
private void ManageBuyOrder()
{
var lowestBuyPosition = Positions
.Where(p => p.SymbolName == SymbolName && p.Label == Label && p.TradeType == TradeType.Buy)
.OrderBy(p => p.EntryPrice) // sắp xếp theo thứ tự tăng dần
.FirstOrDefault();
if (lowestBuyPosition == null)
{
CancelPendingOrders(TradeType.Buy);
return;
}
else
{
if( lowestBuyPosition.EntryPrice <= Symbol.Bid )
{
CancelPendingOrders(TradeType.Buy);
}
else
{
if (BuyLimit)
{
PlaceBuyLimitOrder() ;
}
if (BuyStop)
{
PlaceBuyStopOrder();
}
}
}
}
private void PlaceBuyLimitOrder()
{
var existingOrder = PendingOrders
.Where(o => o.SymbolName == SymbolName && o.Label == Label && o.TradeType == TradeType.Buy && o.TargetPrice < Symbol.Bid)
.OrderByDescending(o => o.TargetPrice) // sắp xếp theo thứ tự giảm dần
.FirstOrDefault();
var limitPrice = Symbol.Bid - Symbol.PipSize * Distance;
if (existingOrder == null)
{
PlaceLimitOrder(TradeType.Buy, SymbolName, Symbol.QuantityToVolumeInUnits(FirstVolume), limitPrice, Label);
}
else if (Symbol.Bid - existingOrder.TargetPrice >= Symbol.PipSize * (Distance + DistanceBetween))
{
PlaceLimitOrder(TradeType.Buy, SymbolName, Symbol.QuantityToVolumeInUnits(FirstVolume), limitPrice, Label);
}
}
private void PlaceBuyStopOrder()
{
var existingOrder = PendingOrders
.Where(o => o.SymbolName == SymbolName && o.Label == Label && o.TradeType == TradeType.Buy && o.TargetPrice > Symbol.Ask)
.OrderBy(o => o.TargetPrice) // sắp xếp theo thứ tự tăng dần
.FirstOrDefault();
var StopPrice = Symbol.Ask + Symbol.PipSize * Distance;
if (existingOrder == null)
{
PlaceStopOrder(TradeType.Buy, SymbolName, Symbol.QuantityToVolumeInUnits(FirstVolume), StopPrice, Label);
}
else if (existingOrder.TargetPrice - Symbol.Ask >= Symbol.PipSize * (Distance + DistanceBetween))
{
PlaceStopOrder(TradeType.Buy, SymbolName, Symbol.QuantityToVolumeInUnits(FirstVolume), StopPrice, Label);
}
}
private void ManageSellOrder()
{
var hightestSellPosition = Positions
.Where(p => p.SymbolName == SymbolName && p.Label == Label && p.TradeType == TradeType.Sell)
.OrderByDescending(p => p.EntryPrice) // sắp xếp theo thứ tự giảm dần
.FirstOrDefault();
if (hightestSellPosition == null)
{
CancelPendingOrders(TradeType.Sell);
return;
}
else
{
if( hightestSellPosition.EntryPrice >= Symbol.Ask )
{
CancelPendingOrders(TradeType.Sell);
}
else
{
if (SellLimit)
{
PlaceSellLimitOrder() ;
}
if (SellStop)
{
PlaceSellStopOrder();
}
}
}
}
private void PlaceSellLimitOrder()
{
var existingOrder = PendingOrders
.Where(o => o.SymbolName == SymbolName && o.Label == Label && o.TradeType == TradeType.Sell && o.TargetPrice > Symbol.Ask)
.OrderBy(o => o.TargetPrice) // sắp xếp theo thứ tự tăng dần
.FirstOrDefault();
var limitPrice = Symbol.Ask + Symbol.PipSize * Distance;
if (existingOrder == null)
{
PlaceLimitOrder(TradeType.Sell, SymbolName, Symbol.QuantityToVolumeInUnits(FirstVolume), limitPrice, Label);
}
else if (existingOrder.TargetPrice - Symbol.Ask >= Symbol.PipSize * (Distance + DistanceBetween))
{
PlaceLimitOrder(TradeType.Sell, SymbolName, Symbol.QuantityToVolumeInUnits(FirstVolume), limitPrice, Label);
}
}
private void PlaceSellStopOrder()
{
var existingOrder = PendingOrders
.Where(o => o.SymbolName == SymbolName && o.Label == Label && o.TradeType == TradeType.Sell && o.TargetPrice < Symbol.Bid)
.OrderByDescending(o => o.TargetPrice) // sắp xếp theo thứ tự giảm dần
.FirstOrDefault();
var StopPrice = Symbol.Bid - Symbol.PipSize * Distance;
if (existingOrder == null)
{
PlaceStopOrder(TradeType.Sell, SymbolName, Symbol.QuantityToVolumeInUnits(FirstVolume), StopPrice, Label);
}
else if (Symbol.Bid - existingOrder.TargetPrice >= Symbol.PipSize * (Distance + DistanceBetween))
{
PlaceStopOrder(TradeType.Sell, SymbolName, Symbol.QuantityToVolumeInUnits(FirstVolume), StopPrice, Label);
}
}
private void ModifySellVolume(string Label)
{
var sellPositions = Positions
.Where(p => p.SymbolName == SymbolName && p.Label == Label && p.TradeType == TradeType.Sell)
.OrderBy(p => p.EntryPrice) // Sắp xếp theo thứ tự tăng dần
.ToList();
foreach (var position in sellPositions)
{
double currentVolume = position.VolumeInUnits;
double nextVolume = currentVolume + Symbol.QuantityToVolumeInUnits(FirstVolume);
double MaxlotsInUnit = Symbol.QuantityToVolumeInUnits(MaxLots);
if ((Symbol.Bid - position.EntryPrice) > DistanceDouble * Symbol.PipSize && MaxlotsInUnit >= nextVolume)
{
ModifyPosition(position, nextVolume );
}
}
}
private void ModifyBuyVolume(string Label)
{
var buyPositions = Positions
.Where(p => p.SymbolName == SymbolName && p.Label == Label && p.TradeType == TradeType.Buy)
.OrderByDescending(p => p.EntryPrice) // Sắp xếp theo thứ tự giảm dần
.ToList();
foreach (var position in buyPositions)
{
double currentVolume = position.VolumeInUnits;
double nextVolume = currentVolume + Symbol.QuantityToVolumeInUnits(FirstVolume);
double MaxlotsInUnit = Symbol.QuantityToVolumeInUnits(MaxLots);
if ((position.EntryPrice - Symbol.Ask) > DistanceDouble * Symbol.PipSize && MaxlotsInUnit >= nextVolume)
{
ModifyPosition(position, nextVolume);
}
}
}
private void CancelPendingOrders(TradeType tradeType)
{
foreach (var order in PendingOrders.Where(o => o.SymbolName == SymbolName && o.Label == Label && o.TradeType == tradeType))
{
CancelPendingOrder(order);
}
}
private void OnPositionClosed(PositionClosedEventArgs args)
{
var closedPosition = args.Position;
if (!IsPositionOpen(closedPosition.TradeType))
{
CancelPendingOrders(closedPosition.TradeType);
}
}
private bool IsPositionOpen(TradeType tradeType)
{
return Positions.Any(p => p.SymbolName == SymbolName && p.Label == Label && p.TradeType == tradeType);
}
}
}
ForexViet
Joined on 05.05.2023
- Distribution: Free
- Language: C#
- Trading platform: cTrader Automate
- File name: 26.8-RSI_TiengThu_withSourceCode.algo
- Rating: 3.33
- Installs: 512
- Modified: 26/08/2024 03:05
Warning! Running cBots downloaded from this section may lead to financial losses. Use them at your own risk.
Note that publishing copyrighted material is strictly prohibited. If you believe there is copyrighted material in this section, please use the Copyright Infringement Notification form to submit a claim.
Comments
Log in to add a comment.
This is my story:
About 5 years ago I met a foreign friend, he was a programmer and I tested cbot on my account. I came up with many ideas and he fixed it, then I had to pay about 2500 USD for the cbot that we built together in that 1 year. I received the cbot without source code. I use that cbot quite well. Few months ago, I discovered that cTrader has significant improvements, especially Bot cloud, so I don't need to use VPS anymore. I contacted him again asking him to update the cbot but he refused, he said it was his effort and couldn't be given away for free. This makes me not want to depend on anyone anymore. I tried to study programming and this is the result. I can create a same cbot and improve many things