Cbot incorrectly opens/closes positions.
Cbot incorrectly opens/closes positions.
14 Jun 2023, 20:41
Hello. Need help correcting the code. I would like the cBot to close / open the position after the EMA cut, but only after the close of the candle during which the cut occurred, and not immediately. I use renko candles. Cbot also has an error and when closing / opening a position, it closes all positions that are currently open, which I manually opened. It only has to close/open its own positions. Please help.
using System;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using System.IO;
using System.Linq;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
public class TradingStrategiesBot : Robot
{
[Parameter("Fast Moving Average Period",Group = "Moving Average", DefaultValue = 10, MinValue = 1)]
public int FastMAPeriod { get; set; }
[Parameter("Lot Size", DefaultValue = 0.01, MinValue = 0.01, Step = 0.01)]
public double LotSize { get; set; }
[Parameter("Slow Moving Average Period",Group = "Moving Average", DefaultValue = 30, MinValue = 1)]
public int SlowMAPeriod { get; set; }
[Parameter("ATR Stoploss", DefaultValue = 100, MinValue = 1)]
public int StopLoss { get; set; }
[Parameter("ATR TakeProfit", DefaultValue = 200, MinValue = 1)]
public int TakeProfit { get; set; }
[Parameter("Enable Trailing Stop Loss")]
public bool EnableTrailingStopLoss { get; set; }
[Parameter("Enable Take Profit")]
public bool EnableTakeProfit { get; set; }
[Parameter("Enable Stop Loss")]
public bool EnableStopLoss { get; set; }
[Parameter("Strategy Type")]
public StrategyType Strategy { get; set; }
[Parameter("Moving Average Type",Group = "Moving Average")]
public MovingAverageType matype { get; set; }
[Parameter("Fast MA Source", Group = "Moving Average")]
public DataSeries fSource { get; set; }
[Parameter("Slow MA Source", Group = "Moving Average")]
public DataSeries sSource { get; set; }
[Parameter("Start Time (HH:MM)", DefaultValue = "00:00")]
public string StartTime { get; set; }
[Parameter("Stop Time (HH:MM)", DefaultValue = "23:59")]
public string StopTime { get; set; }
[Parameter("Close All Positions At (HH:MM)", DefaultValue = "")]
public string ClosePositionsAt { get; set; }
private MovingAverage _fastMA;
private MovingAverage _slowMA;
private AverageTrueRange atr;
private TimeSpan _startTime;
private TimeSpan _stopTime;
private TimeSpan? _closePositionsAtTime;
protected override void OnStart()
{
_fastMA = Indicators.MovingAverage(fSource, FastMAPeriod, matype);
_slowMA = Indicators.MovingAverage(sSource, SlowMAPeriod, matype);
Chart.DrawStaticText("Copyright", "Owned by Singularity", VerticalAlignment.Top, HorizontalAlignment.Left, "Gray");
atr = Indicators.AverageTrueRange(14, MovingAverageType.Exponential);
if (!TimeSpan.TryParse(StartTime, out _startTime))
{
Print("Invalid Start Time format. Use HH:MM format.");
Stop();
}
if (!TimeSpan.TryParse(StopTime, out _stopTime))
{
Print("Invalid Stop Time format. Use HH:MM format.");
Stop();
}
if (!string.IsNullOrEmpty(ClosePositionsAt))
{
TimeSpan closePositionsAtTime;
if (TimeSpan.TryParse(ClosePositionsAt, out closePositionsAtTime))
{
_closePositionsAtTime = closePositionsAtTime;
}
else
{
Print("Invalid Close All Positions At format. Use HH:MM format.");
Stop();
}
}
}
protected override void OnBar()
{
var currentTime = Server.Time.TimeOfDay;
if (currentTime >= _startTime && currentTime <= _stopTime)
{
if (_fastMA.Result.HasCrossedAbove(_slowMA.Result, 1))
{
ExecuteStrategy(TradeType.Buy);
}
else if (_fastMA.Result.HasCrossedBelow(_slowMA.Result, 1))
{
ExecuteStrategy(TradeType.Sell);
}
}
if (_closePositionsAtTime.HasValue && currentTime >= _closePositionsAtTime.Value)
{
CloseAllPositions();
}
}
protected override void OnStop()
{
WriteNetProfitToCSV();
}
private void ExecuteStrategy(TradeType tradeType)
{
CloseAllPositions();
double volume = Symbol.QuantityToVolumeInUnits(LotSize);
double atrPips = Math.Ceiling(atr.Result.Last(1) / Symbol.PipSize);
if (tradeType == TradeType.Buy)
{
if (Strategy == StrategyType.Strategy1 || (Strategy == StrategyType.Strategy2 && Symbol.Ask > _fastMA.Result.LastValue && Symbol.Ask > _slowMA.Result.LastValue) || (Strategy == StrategyType.Strategy3 && _fastMA.Result.IsRising() && _slowMA.Result.IsRising()))
{
PlaceOrder(tradeType, Symbol, volume, "Long", atrPips);
}
}
else
{
if (Strategy == StrategyType.Strategy1 || (Strategy == StrategyType.Strategy2
&& Symbol.Bid < _fastMA.Result.LastValue && Symbol.Bid < _slowMA.Result.LastValue) || (Strategy == StrategyType.Strategy3
&& _fastMA.Result.IsFalling() && _slowMA.Result.IsFalling()))
{
PlaceOrder(tradeType, Symbol, volume, "Short", atrPips);
}
}
}
private void PlaceOrder(TradeType tradeType, Symbol symbol, double volume, string label, double atrPips)
{
Print(atrPips);
var stopLossPips = EnableStopLoss ? StopLoss*atrPips : 0;
var takeProfitPips = EnableTakeProfit ? TakeProfit* atrPips : 0;
var tradeResult = ExecuteMarketOrder(tradeType, symbol.Name, volume, label, stopLossPips, takeProfitPips);
if (tradeResult.IsSuccessful && EnableTrailingStopLoss)
{
tradeResult.Position.ModifyTrailingStop(true);
}
}
private void CloseAllPositions()
{
foreach (var position in Positions)
{
ClosePosition(position);
}
}
public void WriteNetProfitToCSV()
{
// Calculate Net Profit
double netProfit = History.Sum(trade => trade.NetProfit);
// Define the CSV file path
string csvFilePath = "C:\\N\\Net_Profits.csv";
// Check if the CSV file exists
if (!File.Exists(csvFilePath))
{
// If the file doesn't exist, create it and write the header
using (StreamWriter sw = File.CreateText(csvFilePath))
{
sw.WriteLine("Net Profit");
}
}
// Write the Net Profit to the CSV file
using (StreamWriter sw = File.AppendText(csvFilePath))
{
sw.WriteLine(netProfit.ToString());
}
Print("Net Profit written to CSV file.");
}
public enum StrategyType
{
Strategy1 = 1,
Strategy2 = 2,
Strategy3 = 3
}
}
}
firemyst
17 Jun 2023, 06:04
Your bot is closing all positions because you tell it to:
If you only want to close positions that your bot has specifically opened, then it's a two step process:
1) when you open a position, you need to assign a label to it (eg, "acBotPosition"), which is a string.
2) when looping through all the open positions, only close those positions whose label matches "acBotPosition":
As for the cut scenario, I wouldn't use the "HasCrossedAbove" method.
Instead, I would use logic similar to the following:
@firemyst