Topics
Replies
aronbara664
21 Dec 2017, 12:44
( Updated at: 21 Dec 2023, 09:20 )
Hi there!
Thank you very much! This is really cool but I have one problem though:
When I try running this, it works for the first time, then I get this error:
@aronbara664
aronbara664
12 Dec 2017, 15:21
Hi there,
Thank you for the quick response!
I have a little bit of a more complicated problem though.
I'll try to give you some context.
My robot utilizes onbar to open a position. So the opening hour is always an even number like 12:00, 13:00 etc... this is not a problem.
However, my robot closes positions in 3 different ways.
1) If price crosses 200MA, CLOSE - Hourly - This is based on a function
2) If we made +80 pip profit, CLOSE - Checked every Minute - This is based on a function
3) If position hits STOPLOSS, CLOSE - This is NOT based on a function.
So in short when I close a trade thanks to my CloseAllPos() function, I can get both the Open and Close dates and I can do something with them.
BUT when a position just hits the predetermined SL, (20 pips), I can't find a way to get the CLOSE time at that EXACT moment.
I know this issue is a bit more complex, so my apologies. I guess what I really want to know is, how can I get the CLOSE time at any given point in time? For example if my SL is hit.
@aronbara664
aronbara664
20 Nov 2017, 15:06
Hi!
So I guess the final formula should look something like this:
var askvolume = (Account.Balance * Risk) / CalculateStopLoss() * 10000 * ENTRYPRICE;
Right?
Now, I figured that not only the NET profit is calculated inaccurately but also the chart TP/SL numbers. (How much I win/lose per trade...)
I backtested my robot going only a few months back (Still 2017) and with the formula mentioned above I really do get -100 per LOSING trade and +200 per WINNING. (Almost, very close to it...)
However if I go back X years in time, these numbers will get overextended too. If I go back 3-4 years, I'll have WINNING trades netting me 240EUR or more. Then if I move forward in time a bit there are trades that are netting me LESS than 200 per winning trade. However, the closer I get to the present, the more accurate those numbers are.
So the only explanation I can find for this is that something really is wrong with the backtesting. However, that makes me wonder -- I can't possibly be the only one who noticed this? Thousands of people are developing algos on the platform DAILY, so I'm not sure whether my methods are incorrect or whether there really is something wrong with the platform.
Anyhow, I'll contact SPOTWARE.
Thank you for your help!
@aronbara664
aronbara664
19 Nov 2017, 19:43
( Updated at: 21 Dec 2023, 09:20 )
Hey there!
Alright, first things first -- I rewrote my volume calculation formula to this:
var askvolume = Account.Balance * Risk / CalculateStopLoss() * 10000;
When I referreed to timeframe, I meant the backtesting period -- for example from 2011/4/5 to 2013/5/6. The robot itself trades on the HOURLY Timeframe.
I did some new backtests and had my SLs & TPs printed out. I think I've gotten a lot closer to figuring this out, thanks to you.
Here are the results:
I had my robot do 3 trades in total. I tested 2 timeframes. The volumes match, the SLs match, the TPs match. Everything matches, except two things.
When I look at my chart, it says I should've made 171 EUR in profit. It doesn't change, regardless of the timeframe I test on. However, my NET PROFIT in the trade history section always shows a different number. My theory is that it actually shows the profit in EUR according to the current exchange rate or something similar to that? Since the chart numbers match but the trade history NET PROFT numbers don't.
So now that we have some clarity, one more thing that doesn't make sense to me is the actual SL/TP in EUR. According to the formula I sent above, I should be risking 1% constantly and gaining 2% (As my TP is 2X my SL...)... However, I fall short of that. If you look at my trades, all my TPs are around 173 EUR and my SLs are around 85 EUR. (According to the chart numbers...)
Is there something wrong with the volume calculation formula?
Anyhow, please see screenshots below:
@aronbara664
aronbara664
18 Nov 2017, 21:06
( Updated at: 21 Dec 2023, 09:20 )
Alright so we recreated our volume calculation to this, as laid out in the API reference:
var juro = ((Account.Balance * Risk) / CalculateStopLoss()) / Symbol.PipValue;
We decided to do a backtest with only 1 trade. The only change we made is the timeframe which we trade on. As expected, the TP/SL changes if we change the timeframe, which makes little sense. Please see screenshots below:
@aronbara664
aronbara664
18 Nov 2017, 18:20
Hey there,
Thank you for getting back to me. Yes, my account is in EUR. I created the LotSizing function based on this article: https://www.babypips.com/learn/forex/calculating-position-sizes but it seems like I might really have to take out the * this.Symbol.Ask ... ANYHOW:
So I tried to run a couple more backtests and I found out some really interesting things... If I backtest the algorithm on a very short timeframe, I really do get something close to 197 profit in EUR. However, if I change the backtest time period to a longer period, all my numbers change -- this doesn't seem to be right and it doesn't make any sense to me, since it should be irrelevant. At least when looking at the first X trades.
Any ideas? I'm pretty lost right now lol. Still trying to figure it all out though!
@aronbara664
aronbara664
18 Nov 2017, 15:36
( Updated at: 21 Dec 2023, 09:20 )
Hi there!
Finally managed to get back.
I did a little test on the first 10 trades. I had my Stop Losses printed out. They match. I will also post the simplified version of my whole code.
I'm thinking maybe the issue is that pip value and all these things change while the trade is on and while price is moving up & down? Not sure.
Anyhow, here are the screenshots.
using System; using System.Linq; using cAlgo.API; using cAlgo.API.Indicators; using cAlgo.API.Internals; using cAlgo.Indicators; namespace cAlgo { [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class BB1PercentRiskTradeBOT : Robot { [Parameter("Instance Name", DefaultValue = "003")] public string InstanceName { get; set; } [Parameter("Start Trading (hour)", DefaultValue = 8)] public int StartHour { get; set; } [Parameter("Stop Trading (hour)", DefaultValue = 20)] public int StopHour { get; set; } [Parameter("Stop Opening (hour)", DefaultValue = 17)] public int BedTime { get; set; } [Parameter("Close all positions?", DefaultValue = true)] public bool IsCloseAllPositions { get; set; } [Parameter("Bollinger Source")] public DataSeries BollSource { get; set; } [Parameter("Bollinger Period", DefaultValue = 20)] public int BollPeriod { get; set; } [Parameter("Bollinger Deviation", DefaultValue = 2.0)] public double BollDev { get; set; } [Parameter(" Max Open Positions (at a time)", DefaultValue = 1)] public int positionLimit { get; set; } [Parameter("TP/SL Ratio", DefaultValue = 2)] public int TPRatio { get; set; } [Parameter("Risk [%]", DefaultValue = 0.01)] public double Risk { get; set; } [Parameter("Max Executed Trades", DefaultValue = 500, MinValue = 0, Step = 100)] public int maxTrades { get; set; } private BollingerBands boll; private const string label = "Sample Trend cBot"; private DateTime _tradingTime { get; set; } private int trades = 0; private int buytrades = 0; private int selltrades = 0; public int currentpositions2 = 0; protected override void OnStart() { boll = Indicators.BollingerBands(BollSource, BollPeriod, BollDev, MovingAverageType.Simple); } protected override void OnBar() { _tradingTime = TradingDateTime(); // _tradingTime.Hour >= StartHour : true) : false) if (_tradingTime.DayOfWeek != DayOfWeek.Friday || _tradingTime.DayOfWeek != DayOfWeek.Saturday || _tradingTime.DayOfWeek != DayOfWeek.Sunday) { if (_tradingTime.Hour >= StartHour && _tradingTime.Hour < StopHour) { ManagePositions(); return; } } else if (_tradingTime.DayOfWeek == DayOfWeek.Friday) { if (_tradingTime.Hour >= StartHour && _tradingTime.Hour < BedTime) { ManagePositions(); return; } else if (_tradingTime.Hour >= BedTime) { try { CloseAllPositions(); } catch (Exception ex) { Print("Error: " + ex.Message); } } } } public DateTime TradingDateTime() { if (this.IsBacktesting) { return Server.Time; } else { return TimeZoneInfo.ConvertTime(DateTime.Now, TimeZoneInfo.Local); } } private void CloseAllPositions() { // if user has chosen to close all positions if (IsCloseAllPositions) { foreach (var position in Positions) { ClosePositionAsync(position); } } } private void ManagePositions() { var longPosition = Positions.Find(label, Symbol, TradeType.Buy); var shortPosition = Positions.Find(label, Symbol, TradeType.Sell); #region Variables var upperBoll = boll.Top.Last(1); var lowerBoll = boll.Bottom.Last(1); var middleBoll = boll.Main.Last(1); var lastPrice = MarketSeries.Close.Last(1); var SL = CalculateStopLoss(); if (lastPrice > upperBoll && trades < maxTrades && SL != 0) { if (MaxPositions2() == true) { OpenPosition(TradeType.Sell); Print("STOP LOSS IS: {0}", CalculateStopLoss()); trades++; } } if (lastPrice < lowerBoll && trades < maxTrades && SL != 0) { if (MaxPositions2() == true) { OpenPosition(TradeType.Buy); Print("STOP LOSS IS: {0}", CalculateStopLoss()); trades++; } } } private void OpenPosition(TradeType type) { ExecuteMarketOrder(type, this.Symbol, LotSizingFunction(), InstanceName, CalculateStopLoss(), CalculateTP()); } private bool MaxPositions2() { bool realcount = Positions.Count < positionLimit ? true : false; return realcount; } private int CalculateStopLoss() { double candleClose = MarketSeries.Close.Last(1); double candleOpen = MarketSeries.Open.Last(1); double candleClose2 = candleClose * 10000; double candleOpen2 = candleOpen * 10000; int candleClose3 = Convert.ToInt32(candleClose2); int candleOpen3 = Convert.ToInt32(candleOpen2); int SL; return SL = candleClose3 > candleOpen3 ? candleClose3 - candleOpen3 : candleOpen3 - candleClose3; } private int CalculateTP() { int takeProfit = CalculateStopLoss() * TPRatio; return takeProfit; } private long LotSizingFunction() { var askvolume = (((Account.Balance * Risk) * this.Symbol.Ask / CalculateStopLoss())) * 10000; var aVolume = askvolume - askvolume % 1000; var normalavalue = Symbol.NormalizeVolume(aVolume); return normalavalue; } } #endregion }
You can see the simplified version of my code above. It seems when opening trades, we're risking more than 1%, in fact it's around 1.20% - 1.30%. Both the SL and TP are overextended.
@aronbara664
aronbara664
17 Nov 2017, 17:07
Hi there,
Thank you for reaching out! I'm a newbie so my apologies if I miss something you requested.
I'll post my CalculateStopLoss() function here. This is all I have that gets me the SL in pips. (Returns an integer...)
private int CalculateStopLoss() { double candleClose = MarketSeries.Close.Last(1); double candleOpen = MarketSeries.Open.Last(1); double candleClose2 = candleClose * 10000; double candleOpen2 = candleOpen * 10000; int candleClose3 = Convert.ToInt32(candleClose2); int candleOpen3 = Convert.ToInt32(candleOpen2); int SL; return SL = candleClose3 > candleOpen3 ? candleClose3 - candleOpen3 : candleOpen3 - candleClose3; }
@aronbara664
aronbara664
21 Dec 2017, 12:55
Nevermind, I think I got it now :-)
@aronbara664