Topics
Replies
ryan.a.blake
14 Jan 2024, 22:34
RE: RE: RE: Open positions per Bar - OnTick
PanagiotisCharalampous said:
ryan.a.blake said:
PanagiotisCharalampous said:
Hi Ryan,
You can use a flag to achieve this e.g. bool CanTrade. Set it to false when a trade is taken and then set it back to true when a new bar is opened.
Best regards,
Panagiotis
Thanks Panagiotis,
I have attempted the code below, but believe I am missing something as it places multiple trades per bar, but trader per bar after bar is opened. I attempted to limit positions with Positions.Count, but that stops it being placed per bar.
Have I missed something?
Thanks for your help.
private bool _canTrade;
private int barCountSinceLastPosition;
protected override void OnStart()
{
_ema1 = Indicators.GetIndicator<SampleEMA>(Source1, Period1);
_ema2 = Indicators.GetIndicator<SampleEMA>(Source2, Period2);
_ema3 = Indicators.GetIndicator<SampleEMA>(Source3, Period3);
_rsi = Indicators.RelativeStrengthIndex(Source3, Period3);
Bars.BarOpened += Bar_Opened;
}
void Bar_Opened(BarOpenedEventArgs args)
{
_canTrade = false;
}
protected override void OnTick()
{
if (IncludeBreakEven == true)
GoToBreakEven();
var Ema1 = _ema1.Result.Last(0);
var Ema2 = _ema2.Result.Last(0);
var Ema1i = _ema1.Result.Last(2);
var Ema2i = _ema2.Result.Last(2);
var Ema3 = _ema3.Result.LastValue;
var rising = _ema1.Result.IsRising();
var falling = _ema2.Result.IsFalling();
var rising2 = _ema2.Result.IsRising();
var falling2 = _ema1.Result.IsFalling();
if (Ema1 > Ema2 && falling && falling2 && Symbol.Bid == Bars.OpenPrices.Last(0) - (pips * Symbol.PipSize))
{
if (Positions.Count(x => x.TradeType == TradeType.Sell && x.Label == InstanceName) == 0)
{
double volume = Symbol.QuantityToVolumeInUnits(lotsize);
ExecuteMarketOrder(TradeType.Sell, SymbolName, volume, InstanceName, SL, TP);
}
{
_canTrade = true;
}
if(_canTrade)
{
if (Ema1 > Ema2 && falling && falling2 && Symbol.Bid == Bars.OpenPrices.Last(0) - (pips * Symbol.PipSize))
{
double volume = Symbol.QuantityToVolumeInUnits(lotsize);
ExecuteMarketOrder(TradeType.Sell, SymbolName, volume, InstanceName, SL, TP);
}
}
}
{
CloseSell();
}
}Hi Ryan,
_canTrade needs to be set to false in OnTick() and to true in OnBar()
Best regards,
Panagiotis
Thanks Panagiotis,
Could you share an example code for this?
I have added OnBar() but multiple trades are still opening. Have I placed everything correctly?
private SampleEMA _ema1 { get; set; }
private SampleEMA _ema2 { get; set; }
private SampleEMA _ema3 { get; set; }
private RelativeStrengthIndex _rsi { get; set; }
private bool _canBuy;
private bool _canSell;
protected override void OnStart()
{
_ema1 = Indicators.GetIndicator<SampleEMA>(Source1, Period1);
_ema2 = Indicators.GetIndicator<SampleEMA>(Source2, Period2);
_ema3 = Indicators.GetIndicator<SampleEMA>(Source3, Period3);
_rsi = Indicators.RelativeStrengthIndex(Source3, Period3);
}
protected override void OnBar()
{
_canSell = true;
}
protected override void OnTick()
{
Print("OnTick");
if (IncludeBreakEven == true)
GoToBreakEven();
var Ema1 = _ema1.Result.Last(0);
var Ema2 = _ema2.Result.Last(0);
var rising = _ema1.Result.IsRising();
var falling = _ema2.Result.IsFalling();
var rising2 = _ema2.Result.IsRising();
var falling2 = _ema1.Result.IsFalling();
if (Ema1 < Ema2 && rising && rising2 && Symbol.Bid == Bars.OpenPrices.Last(0) + (pips * Symbol.PipSize))
{
_canBuy = false;
}
{
CloseBuy();
}
if (Ema1 > Ema2 && falling && falling2 && Symbol.Bid == Bars.OpenPrices.Last(0) - (pips * Symbol.PipSize))
{
double volume = Symbol.QuantityToVolumeInUnits(lotsize);
ExecuteMarketOrder(TradeType.Sell, SymbolName, volume, InstanceName, SL, TP);
}
if(_canSell == true)
{
if (Positions.Count(x => x.TradeType == TradeType.Sell && x.Label == InstanceName) >= 2)
{
_canSell = false;
}
}
{
CloseSell();
}
}
private void CloseSell()
{
var Ema1 = _ema1.Result.Last(0);
var Ema2 = _ema2.Result.Last(0);
foreach (var position in Positions)
if (Ema1 < Ema2 && position.TradeType == TradeType.Sell)
{
ClosePosition(position);
}
}
private void CloseBuy()
{
var Ema1 = _ema1.Result.Last(0);
var Ema2 = _ema2.Result.Last(0);
foreach (var position in Positions)
if (Ema1 > Ema2 && position.TradeType == TradeType.Buy)
{
ClosePosition(position);
}
}
@ryan.a.blake
ryan.a.blake
11 Jan 2024, 16:55
RE: Open positions per Bar - OnTick
PanagiotisCharalampous said:
Hi Ryan,
You can use a flag to achieve this e.g. bool CanTrade. Set it to false when a trade is taken and then set it back to true when a new bar is opened.
Best regards,
Panagiotis
Thanks Panagiotis,
I have attempted the code below, but believe I am missing something as it places multiple trades per bar, but trader per bar after bar is opened. I attempted to limit positions with Positions.Count, but that stops it being placed per bar.
Have I missed something?
Thanks for your help.
private bool _canTrade;
private int barCountSinceLastPosition;
protected override void OnStart()
{
_ema1 = Indicators.GetIndicator<SampleEMA>(Source1, Period1);
_ema2 = Indicators.GetIndicator<SampleEMA>(Source2, Period2);
_ema3 = Indicators.GetIndicator<SampleEMA>(Source3, Period3);
_rsi = Indicators.RelativeStrengthIndex(Source3, Period3);
Bars.BarOpened += Bar_Opened;
}
void Bar_Opened(BarOpenedEventArgs args)
{
_canTrade = false;
}
protected override void OnTick()
{
if (IncludeBreakEven == true)
GoToBreakEven();
var Ema1 = _ema1.Result.Last(0);
var Ema2 = _ema2.Result.Last(0);
var Ema1i = _ema1.Result.Last(2);
var Ema2i = _ema2.Result.Last(2);
var Ema3 = _ema3.Result.LastValue;
var rising = _ema1.Result.IsRising();
var falling = _ema2.Result.IsFalling();
var rising2 = _ema2.Result.IsRising();
var falling2 = _ema1.Result.IsFalling();
if (Ema1 > Ema2 && falling && falling2 && Symbol.Bid == Bars.OpenPrices.Last(0) - (pips * Symbol.PipSize))
{
if (Positions.Count(x => x.TradeType == TradeType.Sell && x.Label == InstanceName) == 0)
{
double volume = Symbol.QuantityToVolumeInUnits(lotsize);
ExecuteMarketOrder(TradeType.Sell, SymbolName, volume, InstanceName, SL, TP);
}
{
_canTrade = true;
}
if(_canTrade)
{
if (Ema1 > Ema2 && falling && falling2 && Symbol.Bid == Bars.OpenPrices.Last(0) - (pips * Symbol.PipSize))
{
double volume = Symbol.QuantityToVolumeInUnits(lotsize);
ExecuteMarketOrder(TradeType.Sell, SymbolName, volume, InstanceName, SL, TP);
}
}
}
{
CloseSell();
}
}
@ryan.a.blake
ryan.a.blake
22 Jul 2020, 17:26
RE:
PanagiotisCharalampous said:
Hi ryan.a.blake,
Try
if (Positions.Count(x => x.TradeType == TradeType.Sell && x.Label == InstanceName) == 0)
Best Regards,
Panagiotis
Works Perfectly!! Thank you very much.
@ryan.a.blake
ryan.a.blake
15 May 2019, 10:14
RE:
I see, I believe I have now fixed the problem. Thankyou for your assistance.
@ryan.a.blake
ryan.a.blake
15 May 2019, 00:15
Apologies, looking back i had pasted the wrong code.
using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class EnvelopeCbot : Robot
{
private DateTime _stopTime;
private DateTime _startTime;
[Parameter("Start Hour", DefaultValue = 6.0)]
public double StartTime { get; set; }
[Parameter("Stop Hour", DefaultValue = 17.3)]
public double StopTime { get; set; }
[Parameter("Instance Name", DefaultValue = "001")]
public string InstanceName { get; set; }
[Parameter("Lot Size", DefaultValue = 0.01)]
public double lotsize { get; set; }
[Parameter("Loss", DefaultValue = 50)]
public double loss { get; set; }
[Parameter("TakeProfitPips", DefaultValue = 10)]
public int TP { get; set; }
[Parameter("StopLossPips", DefaultValue = 10, MinValue = 0)]
public int SL { get; set; }
[Parameter("Trigger When Gaining", DefaultValue = 1)]
public double Trigger { get; set; }
[Parameter("Trailing Stop Loss Distance", DefaultValue = 1)]
public double Trailing { get; set; }
[Parameter("Band Distance", DefaultValue = 0.07)]
public double band { get; set; }
[Parameter("Envelope Period", DefaultValue = 20)]
public int period { get; set; }
[Parameter("MAType")]
public int matype { get; set; }
private Envelopes _env { get; set; }
protected override void OnStart()
{
_env = Indicators.GetIndicator<Envelopes>(period, band, matype);
}
protected override void OnTick()
{
var currentHours = Server.Time.TimeOfDay.TotalHours;
bool tradeTime = StartTime < StopTime ? currentHours > StartTime && currentHours < StopTime : currentHours < StopTime || currentHours > StartTime;
if (!tradeTime)
return;
if ((MarketSeries.Close.LastValue > _env.ChannelUp.Last(1)))
if (Positions.Count(x => x.TradeType == TradeType.Buy) == 0)
{
double volume = Symbol.QuantityToVolumeInUnits(lotsize);
ExecuteMarketOrder(TradeType.Buy, Symbol, volume, InstanceName, SL, TP, null);
ClosePosition(TradeType.Sell);
}
if ((MarketSeries.Close.LastValue < _env.ChannelLow.Last(1)))
if (Positions.Count(x => x.TradeType == TradeType.Sell) == 0)
{
{
double volume = Symbol.QuantityToVolumeInUnits(lotsize);
ExecuteMarketOrder(TradeType.Sell, Symbol, volume, InstanceName, SL, TP, null);
ClosePosition(TradeType.Buy);
}
}
}
private void ExecuteMarketOrder(TradeType buy, Symbol symbol, double volume, string instanceName, string v, int sL, int tP, object p)
{
throw new NotImplementedException();
}
private void ClosePosition(TradeType type)
{
var p = Positions.Find(InstanceName, Symbol, type);
if (p != null)
{
ClosePosition(p);
}
if (Account.Balance <= loss)
Stop();
}
private void TRAILING()
{
if (Trailing > 0 && Trigger > 0)
{
Position[] positions = Positions.FindAll(InstanceName, Symbol);
foreach (Position position in positions)
{
if (position.TradeType == TradeType.Sell)
{
double distance = position.EntryPrice - Symbol.Ask;
if (distance >= Trigger * Symbol.PipSize)
{
double newStopLossPrice = Symbol.Ask + Trailing * Symbol.PipSize;
if (position.StopLoss == null || newStopLossPrice < position.StopLoss)
{
ModifyPosition(position, newStopLossPrice, position.TakeProfit);
}
}
}
else
{
double distance = Symbol.Bid - position.EntryPrice;
if (distance >= Trigger * Symbol.PipSize)
{
double newStopLossPrice = Symbol.Bid - Trailing * Symbol.PipSize;
if (position.StopLoss == null || newStopLossPrice > position.StopLoss)
{
ModifyPosition(position, newStopLossPrice, position.TakeProfit);
}
}
}
}
}
}
}
}
@ryan.a.blake
ryan.a.blake
14 May 2019, 10:17
Hi,
Previously the Cbot would set a stoploss and when price moved into profit and reached a specified pip amount (Trigger) the stoploss would move to the trailing distance specified in the parameters. However recently this has not been the case. A stoploss is placed but when price moves into profit and reaches the trigger amount of pips, the stoploss then does not trail behind as expected. Is this due to a recent upgrade to the platform, and i now need to alter some of the code to suit?
Kind regards.
@ryan.a.blake
ryan.a.blake
13 May 2019, 22:51
My code is below.
using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class MACbot : Robot
{
private DateTime _stopTime;
private DateTime _startTime;
[Parameter("Start Hour", DefaultValue = 6.0)]
public double StartTime { get; set; }
[Parameter("Stop Hour", DefaultValue = 17.3)]
public double StopTime { get; set; }
[Parameter("Instance Name", DefaultValue = "001")]
public string InstanceName { get; set; }
[Parameter("Lot Size", DefaultValue = 0.01)]
public double lotsize { get; set; }
[Parameter("Source #1")]
public DataSeries Source1 { get; set; }
[Parameter("Source #2")]
public DataSeries Source2 { get; set; }
[Parameter("Period #1", DefaultValue = 1, MinValue = 1, MaxValue = 100)]
public int Period1 { get; set; }
[Parameter("Period #2", DefaultValue = 2, MinValue = 1, MaxValue = 100)]
public int Period2 { get; set; }
[Parameter("Loss", DefaultValue = 50)]
public double loss { get; set; }
[Parameter("TakeProfitPips", DefaultValue = 10)]
public int TP { get; set; }
[Parameter("StopLossPips", DefaultValue = 10, MinValue = 0)]
public int SL { get; set; }
[Parameter("Trigger ", DefaultValue = 20)]
public int Trigger { get; set; }
[Parameter("Trailing", DefaultValue = 10)]
public int Trailing { get; set; }
private SimpleMovingAverage _sma1 { get; set; }
private SimpleMovingAverage _sma2 { get; set; }
protected override void OnStart()
{
// Start Time is the same day at 22:00:00 Server Time
_startTime = Server.Time.Date.AddHours(StartTime);
// Stop Time is the next day at 06:00:00
_stopTime = Server.Time.Date.AddHours(StopTime);
Print("Start Time {0},", _startTime);
Print("Stop Time {0},", _stopTime);
_sma1 = Indicators.SimpleMovingAverage(Source1, Period1);
_sma2 = Indicators.SimpleMovingAverage(Source2, Period2);
}
protected override void OnTick()
{
if (Trade.IsExecuting)
return;
var currentHours = Server.Time.TimeOfDay.TotalHours;
bool tradeTime = StartTime < StopTime ? currentHours > StartTime && currentHours < StopTime : currentHours < StopTime || currentHours > StartTime;
if (!tradeTime)
return;
if (_sma1.Result.Last(2) > _sma2.Result.Last(2) && (_sma2.Result.Last(1) < _sma1.Result.Last(1)))
if (Positions.Count(x => x.TradeType == TradeType.Buy) == 0)
{
double volume = Symbol.QuantityToVolumeInUnits(lotsize);
ExecuteMarketOrder(TradeType.Buy, Symbol, volume, InstanceName, SL, TP);
ClosePosition(TradeType.Sell);
}
if (_sma1.Result.Last(2) < _sma2.Result.Last(2) && (_sma2.Result.Last(1) > _sma1.Result.Last(1)))
if (Positions.Count(x => x.TradeType == TradeType.Sell) == 0)
{
{
double volume = Symbol.QuantityToVolumeInUnits(lotsize);
ExecuteMarketOrder(TradeType.Sell, Symbol, volume, InstanceName, SL, TP);
ClosePosition(TradeType.Buy);
}
}
}
private void ClosePosition(TradeType type)
{
var p = Positions.Find(InstanceName, Symbol, type);
if (p != null)
{
ClosePosition(p);
}
if (Account.Balance <= loss)
Stop();
TRAILING();
}
private void TRAILING()
{
if (Trailing > 0 && Trigger > 0)
{
Position[] positions = Positions.FindAll(InstanceName, Symbol);
foreach (Position position in positions)
{
if (position.TradeType == TradeType.Sell)
{
double distance = position.EntryPrice - Symbol.Ask;
if (distance >= Trigger * Symbol.PipSize)
{
double newStopLossPrice = Symbol.Ask + Trailing * Symbol.PipSize;
if (position.StopLoss == null || newStopLossPrice < position.StopLoss)
{
ModifyPosition(position, newStopLossPrice, position.TakeProfit);
}
}
}
else
{
double distance = Symbol.Bid - position.EntryPrice;
if (distance >= Trigger * Symbol.PipSize)
{
double newStopLossPrice = Symbol.Bid - Trailing * Symbol.PipSize;
if (position.StopLoss == null || newStopLossPrice > position.StopLoss)
{
ModifyPosition(position, newStopLossPrice, position.TakeProfit);
}
}
}
}
}
}
}
}
@ryan.a.blake
ryan.a.blake
08 May 2019, 15:44
Hi,
Below is something i have quickly put together based on a bollinger band algo i have found in the forum. They are similar indicator so i assume the prinicples would be the same. Would this be correct, or does it require additional coding. In terms of the parameters such as band distance and period, im aware these will need to be included which i will do in due course, but in terms of the algo placing trades based on the implementation of the indicator, have i represented that correctly.
using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class NewcBot : Robot
{
[Parameter(DefaultValue = 0.0)]
public double Parameter { get; set; }
Envelopes _env;
protected override void OnStart()
{
_env = Indicators.GetIndicator<Envelopes>(MarketSeries.Close, 20, 0.07);
}
protected override void OnTick()
{
if ((Marketseries.close > _env.Upperband.LastValue))
{
// Trade...
}
}
protected override void OnStop()
{
// Put your deinitialization logic here
}
}
}
@ryan.a.blake
ryan.a.blake
08 May 2019, 15:18
I have been having trouble coding the Envelopes indicator to automate a strategy. it is currently placed in the custom indicator section, which i can easily use the following method - env.indicator.Getindicator<Envelopes>(Period 1, Banddistance) which works, however i seem to run into problems when writing the ontick method marketseries.close > env....... How could i code this to open a trade when close is above the upper band and the lower band?
Would appreciate any suuggestions.
Kind regards.
@ryan.a.blake
ryan.a.blake
05 Mar 2019, 21:26
Oops. Forgot to add my settings used for the MA shift. They are as follows = MA shift 1 (Red): MA =3, Shift =1 & MA shift 2 (Blue): MA= 4, Shift = -1.
No TP but Trailing Stoploss was triggered at 5 pips and trailed every 10pips.
@ryan.a.blake
ryan.a.blake
05 Mar 2019, 21:15
( Updated at: 21 Dec 2023, 09:21 )
Hi Panagiotis,
Me again. I was unable to produce results from monday's session as it was having technical issues and not placing any trades due to the error in the code I created when trialing something that may fix it, which obviously didn't.
After todays testing of the Cbot live on renko there still seems to be an error with it. Please see code for strategy below;
using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class MAShiftCbot : Robot
{
[Parameter("Instance Name", DefaultValue = "001")]
public string InstanceName { get; set; }
[Parameter("Lot Size", DefaultValue = 0.01)]
public double lotsize { get; set; }
[Parameter("Source #SMA1")]
public DataSeries Source1 { get; set; }
[Parameter("Source #SMA2")]
public DataSeries Source2 { get; set; }
[Parameter("Period #SMA1", DefaultValue = 1, MinValue = 1, MaxValue = 100)]
public int Period1 { get; set; }
[Parameter("Shift #SMA1", DefaultValue = 5, MinValue = -100, MaxValue = 500)]
public int Shift1 { get; set; }
[Parameter("Period #SMA2", DefaultValue = 5, MinValue = 1, MaxValue = 100)]
public int Period2 { get; set; }
[Parameter("Shift #SMA2", DefaultValue = 5, MinValue = -100, MaxValue = 500)]
public int Shift2 { get; set; }
[Parameter("Loss", DefaultValue = 50)]
public double loss { get; set; }
[Parameter("TakeProfitPips", DefaultValue = 10)]
public int TP { get; set; }
[Parameter("StopLossPips", DefaultValue = 10, MinValue = 0)]
public int SL { get; set; }
[Parameter("trigger ", DefaultValue = 20)]
public int Trigger { get; set; }
[Parameter("Trailing", DefaultValue = 10)]
public int Trailing { get; set; }
private SMAShift _sma1 { get; set; }
private SMAShift _sma2 { get; set; }
protected override void OnStart()
{
_sma1 = Indicators.GetIndicator<SMAShift>(Source1, Period1, Shift1);
_sma2 = Indicators.GetIndicator<SMAShift>(Source2, Period2, Shift2);
}
protected override void OnTick()
{
TRAILING();
}
protected override void OnBar()
{
if (_sma1.Result.Last(0) > _sma2.Result.Last(0))
if (Positions.Count(x => x.TradeType == TradeType.Buy) == 0)
{
double volume = Symbol.QuantityToVolumeInUnits(lotsize);
ExecuteMarketOrder(TradeType.Buy, this.Symbol, volume, InstanceName, SL, TP, null, null);
ClosePosition(TradeType.Sell);
}
if (_sma1.Result.Last(0) < _sma2.Result.Last(0))
if (Positions.Count(x => x.TradeType == TradeType.Sell) == 0)
{
{
double volume = Symbol.QuantityToVolumeInUnits(lotsize);
ExecuteMarketOrder(TradeType.Sell, this.Symbol, volume, InstanceName, SL, TP, null, null);
ClosePosition(TradeType.Buy);
}
}
}
private void ClosePosition(TradeType type)
{
var p = Positions.Find(InstanceName, this.Symbol, type);
if (p != null)
{
ClosePosition(p);
}
if (Account.Balance <= loss)
Stop();
}
private void TRAILING()
{
if (Trailing > 0 && Trigger > 0)
{
Position[] positions = Positions.FindAll(InstanceName, Symbol);
foreach (Position position in positions)
{
if (position.TradeType == TradeType.Sell)
{
double distance = position.EntryPrice - Symbol.Ask;
if (distance >= Trigger * Symbol.PipSize)
{
double newStopLossPrice = Symbol.Ask + Trailing * Symbol.PipSize;
if (position.StopLoss == null || newStopLossPrice < position.StopLoss)
{
ModifyPosition(position, newStopLossPrice, position.TakeProfit);
}
}
}
else
{
double distance = Symbol.Bid - position.EntryPrice;
if (distance >= Trigger * Symbol.PipSize)
{
double newStopLossPrice = Symbol.Bid - Trailing * Symbol.PipSize;
if (position.StopLoss == null || newStopLossPrice > position.StopLoss)
{
ModifyPosition(position, newStopLossPrice, position.TakeProfit);
}
}
}
}
}
}
}
}
The code for the indicator is as posted earlier in the thread above. Please also see below image showing todays renko chart with MA shift indicators used for the strategy;
And finally please also see results from trades taken today for your analysis;
I trust this should be ok to hopefully find out what could be the underlying cause for the cbot not trading as expected. Im hoping this could possibly be the cbot requiring additional coding and not MA shift not being compatible with renko or being used in a cbot.
Il look forward to your reply.
Kind regards
Ryan
@ryan.a.blake
ryan.a.blake
02 Mar 2019, 19:26
I unfortunately am unable to produce the backtesting results from where it went wrong. I have however tested this through backtesting and it does appear to work. Looking through some of the code I have placed the condition coding (if....) under OnBar instead of Ontick, which has moderated the trade results. Im wondering if that could have been the cause previously. Anyway, im planning on testing this again live on renko when monday comes round and will post any problems I come across (if any).
Kind regards.
@ryan.a.blake
ryan.a.blake
01 Mar 2019, 13:11
( Updated at: 21 Dec 2023, 09:21 )
Hi Panagiotis,
Thank you for getting back to be.
Unfortunaltey i am not at my computer today and unable to post my actual backtesting results showing you where the Cbot went wrong. However if its ok with you I have posted screenshots from Trading view showing you examples of where the cbot went wrong.
The below image shows what the Cbot actually does, which creates non intended trades due to the moving averages not taking into account the shift part of my strategy which has been calculated into the moving averages indicator.
The below image shows what the Cbot needs to do, which is to incorporate shift into the moving averages creating a gap between the two MA's creating cleaner entries for the cbot. However when the cbot is running this is not what happens.
So the main problem with the cbot is that shift does not want to work or register when the cbot is running. Hopefully you should have all information now, however let m eknow if you need more.
Kind regards.
@ryan.a.blake
ryan.a.blake
28 Feb 2019, 21:15
So, as I attempted to explain in my very first post. The Cbot is based on a crossover of MA = Period 3 (shift=0) & MA = Period 2 (shift= -1) with shift coded into the indicator (you will notice I have placed -1 into the code at the bottom of the indicator = Result{index - 1} = sum / Periods;) Im aware that this should have been 'shift' in that place instead, to link with what I have put in the parameters. Anyway as I run this cbot on renko charts everything appears to work smoothly until it places trades in the wrong direction when a cross happens, after further analysis of where trades were placed and the direction they are going whether it be buy or sell. I noticed that the trades taken were as if shift -1 was not working and as if it was two normal MA's, which as a result took incorrect trades causing loss.
I hope this shoud now make sense.
Let me know if you require anything else.
Kind regards.
@ryan.a.blake
ryan.a.blake
28 Feb 2019, 21:01
RE:
Panagiotis Charalampous said:
Hi Ryan,
Unfortunately the information you provide is too little. We need you to share with us your indicator and cBot and tell us how to reproduce the issue so that we can advise you.
Best Regards,
Panagiotis
Wow, apologies. I did not realise how bad I had written my previous post. No wonder why you did not understand. Anyway - Please see below copy of my code for the cbot.
using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class MAShiftCbot : Robot
{
[Parameter("Instance Name", DefaultValue = "001")]
public string InstanceName { get; set; }
[Parameter("Lot Size", DefaultValue = 0.01)]
public double lotsize { get; set; }
[Parameter("Source #SMA1")]
public DataSeries Source1 { get; set; }
[Parameter("Source #SMA2")]
public DataSeries Source2 { get; set; }
[Parameter("Period #SMA1", DefaultValue = 1, MinValue = 1, MaxValue = 100)]
public int Period1 { get; set; }
[Parameter("Shift #SMA1", DefaultValue = 5, MinValue = -100, MaxValue = 500)]
public int Shift1 { get; set; }
[Parameter("Period #SMA2", DefaultValue = 5, MinValue = 1, MaxValue = 100)]
public int Period2 { get; set; }
[Parameter("Shift #SMA2", DefaultValue = 5, MinValue = -100, MaxValue = 500)]
public int Shift2 { get; set; }
[Parameter("Loss", DefaultValue = 50)]
public double loss { get; set; }
[Parameter("TakeProfitPips", DefaultValue = 10)]
public int TP { get; set; }
[Parameter("StopLossPips", DefaultValue = 10, MinValue = 0)]
public int SL { get; set; }
[Parameter("trigger ", DefaultValue = 20)]
public int Trigger { get; set; }
[Parameter("Trailing", DefaultValue = 10)]
public int Trailing { get; set; }
private SMAShift _sma1 { get; set; }
private SMAShift _sma2 { get; set; }
protected override void OnStart()
{
_sma1 = Indicators.GetIndicator<SMAShift>(Source1, Period1, Shift1);
_sma2 = Indicators.GetIndicator<SMAShift>(Source2, Period2, Shift2);
}
protected override void OnTick()
{
TRAILING();
if (_sma1.Result.Last(0) > _sma2.Result.Last(0))
if (Positions.Count(x => x.TradeType == TradeType.Buy) == 0)
{
double volume = Symbol.QuantityToVolumeInUnits(lotsize);
ExecuteMarketOrder(TradeType.Buy, this.Symbol, volume, InstanceName, SL, TP, null, null);
ClosePosition(TradeType.Sell);
}
if (_sma1.Result.Last(0) < _sma2.Result.Last(0))
if (Positions.Count(x => x.TradeType == TradeType.Sell) == 0)
{
{
double volume = Symbol.QuantityToVolumeInUnits(lotsize);
ExecuteMarketOrder(TradeType.Sell, this.Symbol, volume, InstanceName, SL, TP, null, null);
ClosePosition(TradeType.Buy);
}
}
}
private void ClosePosition(TradeType type)
{
var p = Positions.Find(InstanceName, this.Symbol, type);
if (p != null)
{
ClosePosition(p);
}
if (Account.Balance <= loss)
Stop();
}
private void TRAILING()
{
if (Trailing > 0 && Trigger > 0)
{
Position[] positions = Positions.FindAll(InstanceName, Symbol);
foreach (Position position in positions)
{
if (position.TradeType == TradeType.Sell)
{
double distance = position.EntryPrice - Symbol.Ask;
if (distance >= Trigger * Symbol.PipSize)
{
double newStopLossPrice = Symbol.Ask + Trailing * Symbol.PipSize;
if (position.StopLoss == null || newStopLossPrice < position.StopLoss)
{
ModifyPosition(position, newStopLossPrice, position.TakeProfit);
}
}
}
else
{
double distance = Symbol.Bid - position.EntryPrice;
if (distance >= Trigger * Symbol.PipSize)
{
double newStopLossPrice = Symbol.Bid - Trailing * Symbol.PipSize;
if (position.StopLoss == null || newStopLossPrice > position.StopLoss)
{
ModifyPosition(position, newStopLossPrice, position.TakeProfit);
}
}
}
}
}
}
}
}
Please see code below for the indicator =
// -------------------------------------------------------------------------------------------------
//
// Simple Moving Average Shift
// This code is a cAlgo API example.
//
// -------------------------------------------------------------------------------------------------
using System;
using cAlgo.API;
using cAlgo.API.Indicators;
namespace cAlgo.Indicators
{
[Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
public class SMAShift : Indicator
{
[Parameter("Source")]
public DataSeries Source { get; set; }
[Parameter(DefaultValue = 14)]
public int Periods { get; set; }
[Parameter(DefaultValue = -2, MinValue = -100, MaxValue = 500)]
public int Shift { get; set; }
[Output("Main", Color = Colors.Blue)]
public IndicatorDataSeries Result { get; set; }
public override void Calculate(int index)
{
double sum = 0.0;
for (int i = index - Periods + 1; i <= index; i++)
{
sum += Source[i];
}
Result[index - 1] = sum / Periods;
}
}
}
@ryan.a.blake
ryan.a.blake
05 Feb 2019, 22:57
RE:
Hi Panagiotis,
Im not sure what you mean, im actually just starting out coding and slowly beginning to understand how to create a Cbot but unsure of how to solve the errors.
The above Cbot needs to open positions when Kama1 crosses above Kama2 for a buy and vise versa, aloowing 1 trade per cross. However the above Cbot appears to be placing more than 1 trade at once when the indicator has not even crossed yet. This could be due to how i have coded the cross and not specify at which point the cbot needs to place trades.
Could you please advise.
Kind regards.
@ryan.a.blake
ryan.a.blake
04 Feb 2019, 21:22
RE:
Hi Panagiotis,
Thankyou for your help above. I have now completed the Cbot, however when backtesting I keep getting the following in the log - Crashed in OnTick with NullReferenceException: Object reference not set to an instance of an object. I have tried to solve this with - if (p =! null) but still comes up with the error. I have copied my code below, what could be the issue.
Also im trying to alter the code to only allow one trade per cross and by a certain distance. Any advice?
Many Thanks.
using cAlgo.API;
using cAlgo.Indicators;
using System.Linq;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class KAMACbot : Robot
{
#region Parameters
[Parameter("Instance Name", DefaultValue = "2307")]
public string InstanceName { get; set; }
[Parameter("Lot Size", DefaultValue = 0.01)]
public double lotsize { get; set; }
[Parameter("TakeProfitPips", DefaultValue = 10)]
public int TP { get; set; }
[Parameter("Profit", DefaultValue = 10)]
public int profit { get; set; }
[Parameter("StopLossPips", DefaultValue = 10, MinValue = 0)]
public int SL { get; set; }
[Parameter("Source #1")]
public DataSeries Source1 { get; set; }
[Parameter("Source #2")]
public DataSeries Source2 { get; set; }
[Parameter("Fast #1", DefaultValue = 1, MinValue = 1, MaxValue = 100)]
public int Fast1 { get; set; }
[Parameter("Slow #1", DefaultValue = 5, MinValue = 1, MaxValue = 100)]
public int Slow1 { get; set; }
[Parameter("Period #1", DefaultValue = 5, MinValue = 1, MaxValue = 100)]
public int Period1 { get; set; }
[Parameter("Fast #2", DefaultValue = 2, MinValue = 1, MaxValue = 100)]
public int Fast2 { get; set; }
[Parameter("Slow #2", DefaultValue = 10, MinValue = 1, MaxValue = 100)]
public int Slow2 { get; set; }
[Parameter("Period #2", DefaultValue = 40, MinValue = 1, MaxValue = 100)]
public int Period2 { get; set; }
[Parameter("Calculate OnBar", DefaultValue = false)]
public bool CalculateOnBar { get; set; }
#endregion
#region Indicator declarations
private KAMA _Kama1 { get; set; }
private KAMA _Kama2 { get; set; }
#endregion
#region cTrader events
protected override void OnStart()
{
// construct the indicators
_Kama1 = Indicators.GetIndicator<KAMA>(Source1, Fast1, Slow1, Period1);
_Kama2 = Indicators.GetIndicator<KAMA>(Source2, Fast2, Slow2, Period2);
}
protected override void OnTick()
{
if (CalculateOnBar)
{
return;
}
ManagePositions();
}
protected override void OnBar()
{
if (!CalculateOnBar)
{
return;
}
ManagePositions();
}
protected override void OnStop()
{
// unused
}
#endregion
#region Position management
private void ManagePositions()
{
if (_Kama1.kama.LastValue > _Kama2.kama.LastValue)
{
if (!IsPositionOpenByType(TradeType.Buy))
{
OpenPosition(TradeType.Buy);
}
ClosePosition();
}
if (_Kama1.kama.LastValue < _Kama2.kama.LastValue)
{
if (!IsPositionOpenByType(TradeType.Sell))
{
OpenPosition(TradeType.Sell);
}
ClosePosition();
}
}
private void OpenPosition(TradeType type)
{
double volume = Symbol.QuantityToVolumeInUnits(lotsize);
// open a new position
ExecuteMarketOrder(type, this.Symbol, volume, InstanceName, SL, TP, null, null);
}
private void ClosePosition()
{
var OpenPosition = Positions.Find(InstanceName, this.Symbol);
if (OpenPosition.Pips >= profit)
{
ClosePosition(OpenPosition);
}
}
#endregion
#region Position Information
private bool IsPositionOpenByType(TradeType type)
{
var p = Positions.FindAll(InstanceName, Symbol, type);
if (p != null)
if (p.Count() == 0)
{
return true;
}
return false;
}
#endregion
}
}
@ryan.a.blake
ryan.a.blake
29 Jan 2019, 15:10
RE:
ryan.a.blake said:
I have recently created a Cbot based on the simple moving average Cbot and have just amended a few of the text to incorporate the KAMA indicator but does not work.
Could somebody help with a mistake it may have?
using cAlgo.API;
using cAlgo.Indicators;
using System.Linq;namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class KAMACbot : Robot
{
#region Parameters[Parameter("Instance Name", DefaultValue = "23078549")]
public string InstanceName { get; set; }[Parameter("Lot Size", DefaultValue = 0.01)]
public double lotsize { get; set; }[Parameter("Source #1")]
public DataSeries Source1 { get; set; }[Parameter("Source #2")]
public DataSeries Source2 { get; set; }[Parameter("Fast #1", DefaultValue = 1, MinValue = 1, MaxValue = 100)]
public int Fast1 { get; set; }[Parameter("Slow #1", DefaultValue = 5, MinValue = 1, MaxValue = 100)]
public int Slow1 { get; set; }[Parameter("Period #1", DefaultValue = 5, MinValue = 1, MaxValue = 100)]
public int Period1 { get; set; }[Parameter("Fast #2", DefaultValue = 2, MinValue = 1, MaxValue = 100)]
public int Fast2 { get; set; }[Parameter("Slow #2", DefaultValue = 10, MinValue = 1, MaxValue = 100)]
public int Slow2 { get; set; }[Parameter("Period #2", DefaultValue = 40, MinValue = 1, MaxValue = 100)]
public int Period2 { get; set; }#endregion
#region Indicator declarations
private KAMA _Kama1 { get; set; }
private KAMA _Kama2 { get; set; }
public int LastValue { get; private set; }#endregion
#region Indicatordouble _volume;
protected override void OnStart()
{
{
_Kama1 = Indicators.GetIndicator<KAMA>(Source1, Fast1, Slow1, Period1);
_Kama2 = Indicators.GetIndicator<KAMA>(Source2, Fast2, Slow2, Period2);
_volume = Symbol.QuantityToVolumeInUnits(lotsize);
Positions.Closed += Positions_Closed;
}
}
private void Positions_Closed(PositionClosedEventArgs obj)
{
if (obj.Position.NetProfit < 0)
_volume += 1000;
else
_volume = Symbol.QuantityToVolumeInUnits(lotsize);
}
#endregion#region Position management
private void ManagePositions()
{
if (_Kama1.LastValue > _Kama2.LastValue)
{if (!IsPositionOpenByType(TradeType.Buy))
{
OpenPosition(TradeType.Buy);
}
if (_Kama1.LastValue < _Kama2.LastValue)
{if (!IsPositionOpenByType(TradeType.Sell))
{
OpenPosition(TradeType.Sell);
}
}
}
}
private void OpenPosition(TradeType type)
{
// open a new position
ExecuteMarketOrder(type, this.Symbol, _volume, InstanceName, null, null);
}
private void ClosePosition(TradeType type)
{
var p = Positions.Find(InstanceName, this.Symbol, type);if (p != null)
{
ClosePosition(p);
}
}#endregion
#region Position Information
private bool IsPositionOpenByType(TradeType type)
{
var p = Positions.FindAll(InstanceName, Symbol, type);if (p.Count() >= 1)
{
return true;
}return false;
}#endregion
}
}
The above coding does not buy or Sell. Can anyone help.
@ryan.a.blake
ryan.a.blake
15 Jan 2024, 18:10
RE: RE: RE: RE: RE: Open positions per Bar - OnTick
Hi Panagiotis,
Thanks for your help.
I worked it out and it works as expected.
Thanks.
@ryan.a.blake