Indicators returning different values than what's displayed on chart
Indicators returning different values than what's displayed on chart
02 Jun 2019, 17:49
Hello Team SpotWare/@Panagiotis:
I'm running the code that follows on Pepperstone's cTrader 3.3.
Look at the screen capture below. You can see that the values that are printed out from the indicator are NOT the values that are displayed on the chart:
How is it the values displayed in the PRINT statement are obviously not the same as what's displayed on the chart?
For example, 2 bars ago is says the value is 111.42; yet the chart shows the indicator line hasn't even crossed 111.40.
cBot code below:
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using System.Timers; using cAlgo.API; using cAlgo.API.Indicators; using cAlgo.API.Internals; using cAlgo.Indicators; using Microsoft.Win32; namespace cAlgo.Robots { [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)] public class BugBot : Robot { private MarketSeries _marketSeries; private Supertrend _superTrend = new Supertrend(); private string _positionLabel = "bug test"; //Run this code against USDJPY from March 1, 2019 - May 25, 2019 15 minute on Pepperstone. //For the SuperTrend indicator, only display the "Main" (Result) line. // //On the very first bar after the bot places an order, you will see the discreptancy //in the values that indicator returns vs what's graphed on the chart! // //For example, you will see: //01/03/2019 00:15:00.000 | 2 bars ago B2: 111.428148657891 yet on the chart the SuperTrend "Main" line hasn't crossed above 111.37. // //so how can the value from 2 bars ago be 111.42?! It's a straight flatline from 20:30 Feb 28 @ 111.36. protected override void OnStart() { _marketSeries = MarketData.GetSeries(Symbol, MarketSeries.TimeFrame); DataSeries series = _marketSeries.Close; _superTrend = Indicators.GetIndicator<Supertrend>(13, 1.5); } protected override void OnBar() { Position p = Positions.Find(_positionLabel, Symbol); double currentSL = p.StopLoss.GetValueOrDefault(); GetLatestIndicatorData(); double b0 = _superTrend.Result.Last(0); double b1 = _superTrend.Result.Last(1); double b2 = _superTrend.Result.Last(2); Print("VALUES:"); Print("Current Bar B0: {0}", b0); Print("1 Bar ago B1: {0}", b1); Print("2 bars ago B2: {0}", b2); Print("The values for B0, B1, and B2 DO NOT match up with what's actually drawn on the chart. Why is this?!"); } protected override void OnTick() { if (CountOfPositions(_positionLabel, Symbol) == 0) { TradeResult r = ExecuteMarketOrder(TradeType.Buy, Symbol, 100000, _positionLabel, 25, null, null, "this is the bug test", true); if (r.IsSuccessful) { Position p = Positions.Find(_positionLabel, Symbol); double stopLossPrice = p.EntryPrice - (Symbol.PipSize * 10); r = p.ModifyStopLossPrice(stopLossPrice); if (r.IsSuccessful) { p.ModifyTrailingStop(false); } } } } private void GetLatestIndicatorData() { double a = _superTrend.Result.Last(0); } private int CountOfPositions(string label, Symbol symbol) { Position p = Positions.Find(label, symbol); if (p == null) return 0; else return 1; } } }
And here is the code for the indicator:
using System; using System.Collections.Generic; using cAlgo.API; using cAlgo.API.Indicators; namespace cAlgo.Indicators { [Indicator("Super Trend", IsOverlay = true, AccessRights = AccessRights.None, TimeZone = TimeZones.UTC)] public class Supertrend : Indicator { [Parameter(DefaultValue = 13)] public int Period { get; set; } [Parameter(DefaultValue = 1.5)] public double Multiplier { get; set; } [Output("Main", PlotType = PlotType.Line, LineStyle = LineStyle.Lines, LineColor = "Blue", Thickness = 2)] public IndicatorDataSeries Result { get; set; } private IndicatorDataSeries _upBuffer; private IndicatorDataSeries _downBuffer; private AverageTrueRange _averageTrueRange; private List<int> _trend; private bool _hasTrendChanged; private double _close; private double _upBufferPrev; private double _downBufferPrev; protected override void Initialize() { _trend = new List<int>(); _upBuffer = CreateDataSeries(); _downBuffer = CreateDataSeries(); _averageTrueRange = Indicators.AverageTrueRange(Period, MovingAverageType.WilderSmoothing); } public override void Calculate(int index) { Result[index] = double.NaN; double median = (MarketSeries.High[index] + MarketSeries.Low[index]) / 2; double atr = _averageTrueRange.Result[index]; _upBuffer[index] = median + Multiplier * atr; _downBuffer[index] = median - Multiplier * atr; if (index < 1) { _trend.Add(1); return; } _trend.Add(0); _trend[index] = 0; _close = MarketSeries.Close[index]; _upBufferPrev = _upBuffer[index - 1]; _downBufferPrev = _downBuffer[index - 1]; if (_close > _upBufferPrev) { _trend[index] = 1; if (_trend[index - 1] != 1) _hasTrendChanged = true; } else if (_close < _downBufferPrev) { _trend[index] = -1; if (_trend[index - 1] != -1) _hasTrendChanged = true; } else if (_trend[index - 1] == 1) { _trend[index] = 1; _hasTrendChanged = false; } else if (_trend[index - 1] == -1) { _trend[index] = -1; _hasTrendChanged = false; } if (_trend[index] < 0 && _trend[index - 1] > 0) _upBuffer[index] = median + (Multiplier * atr); else if (_trend[index] < 0 && _upBuffer[index] > _upBufferPrev) _upBuffer[index] = _upBufferPrev; if (_trend[index] > 0 && _trend[index - 1] < 0) _downBuffer[index] = median - (Multiplier * atr); else if (_trend[index] > 0 && _downBuffer[index] < _downBufferPrev) _downBuffer[index] = _downBufferPrev; // Draw Indicator if (_trend[index] == 1) { Result[index] = _downBuffer[index]; if (_hasTrendChanged) { _hasTrendChanged = false; } } else if (_trend[index] == -1) { Result[index] = _upBuffer[index]; if (_hasTrendChanged) { _hasTrendChanged = false; } } } } }
Replies
firemyst
05 Jun 2019, 12:14
RE:
Panagiotis Charalampous said:
Hi FireMyst,
We have investigated this issue. The reason this happens is that during Visual Backtesting chart and the indicators added to it receive a subset of all the ticks in backtesting. The number of lost ticks depends on backtesting speed and this a necessary compromise to achieve acceptable speed. However this does not come without side effects and this is one of them. For this specific indicator all ticks matter since the value for each bar is calculated for each index using the median price of the trend bar. If you miss one tick in a bar somewhere in the middle, indicator would have a different value than in case you calculate it on every tick. You should not experience this issue in silent backtesting or on during live execution.
Best Regards,
Panagiotis
HI @Panagiotis:
THank you for your investigation. I'm afraid I'm a bit confused and here's why.
I ran some tests today. It works perfectly with SpotWare's cTrader 3.5, and IC Markets version 3.3 of cTrader.
It doesn't work as expected with Pepperstone's version 3.3 of cTrader.
All run in visual backtesting mode.
So if only a subset of ticks are received and utilized, and that's the way cTrader operates, why does it work the same with all the other providers of cTrader except Pepperstone's? I would expect it to work the same with every single broker since the underlying logic of cTrader should be the same, and thus leads me to believe there's an issue with Pepperstone's version of cTrader?
??
@firemyst
PanagiotisCharalampous
05 Jun 2019, 12:18
Hi FireMyst,
Each provider has his own set of backtesting tick data and that is probably the reason for this behavior. Since the indicator is sensitive to each tick information received then I would expect different results on different brokers.
Best Regards,
Panagiotis
@PanagiotisCharalampous
PanagiotisCharalampous
05 Jun 2019, 10:24
Hi FireMyst,
We have investigated this issue. The reason this happens is that during Visual Backtesting chart and the indicators added to it receive a subset of all the ticks in backtesting. The number of lost ticks depends on backtesting speed and this a necessary compromise to achieve acceptable speed. However this does not come without side effects and this is one of them. For this specific indicator all ticks matter since the value for each bar is calculated for each index using the median price of the trend bar. If you miss one tick in a bar somewhere in the middle, indicator would have a different value than in case you calculate it on every tick. You should not experience this issue in silent backtesting or on during live execution.
Best Regards,
Panagiotis
@PanagiotisCharalampous