Entry price out of chart range (using ModifyPosition)

Created at 01 Sep 2018, 11:44
How’s your experience with the cTrader Platform?
Your feedback is crucial to cTrader's development. Please take a few seconds to share your opinion and help us improve your trading experience. Thanks!
nordic's avatar

nordic

Joined 02.02.2017

Entry price out of chart range (using ModifyPosition)
01 Sep 2018, 11:44


Hoping someone can shed some light on this.  I've created a cBot with a simple scale-in function using the ModifyPosition method just to see how it works.  Entries are placed with MarketOrder with 25-pip SL and 50-pip TP just for the time being.

During backtest, as per below image I'm finding that some trades enter and close on prices that aren't on the chart.  However, this only happens after the ModifyPosition method kicks in and adds volume to the position; if I don't use ModifyPosition, all entries/exits are within candle ranges.  This is an H1 chart, so I figure I'm not getting hit with the spread (price feed is Pepperstone tick data).

Code below for the bot I'm testing.  Any help explaining why this happens would be appreciated.

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 TESTBOT : Robot
    {
        [Parameter("Bar Range", DefaultValue = 10)]
        public int BR { get; set; }

        [Parameter("Volume Increase Threshold", DefaultValue = 10)]
        public int VIT { get; set; }

        private TriangularMovingAverage TMAshort;
        private TriangularMovingAverage TMAlong;

        public int barcount;
        public int newposid;

        protected override void OnStart()
        {
            Positions.Opened += OnPositionsOpened;
            Positions.Closed += OnPositionsClosed;
            TMAshort = Indicators.TriangularMovingAverage(MarketSeries.Close, 5);
            TMAlong = Indicators.TriangularMovingAverage(MarketSeries.Close, 50);
        }

        void OnPositionsOpened(PositionOpenedEventArgs obj)
        {
            var p1 = Positions.Find("Trade");
            {
                newposid = p1.Id;
                Print("New Pos ID: {0}", newposid);
            }

        }

        void OnPositionsClosed(PositionClosedEventArgs obj)
        {
            barcount = 0;
        }

        protected override void OnBar()
        {
            if (Positions.Count > 0)
            {
                barcount++;
                Print("{0}", barcount);
                VolumeModifier();
            }

            if (Functions.HasCrossedAbove(TMAshort.Result, TMAlong.Result, 1))
            {
                BuyEntry();
            }

            if (Functions.HasCrossedBelow(TMAshort.Result, TMAlong.Result, 1))
            {
                SellEntry();
            }

        }

        private void VolumeModifier()
        {
            var p1 = Positions.Find("Trade");
            if (p1 != null)
            {
                if (p1.GrossProfit > 0)
                {
                    if (barcount == VIT)
                    {
                        ModifyPosition(p1, 20000);
                        Print("Position volume modified");
                    }
                }
            }
        }

        private void BuyEntry()
        {
            if (Positions.Count == 0)
            {
                ExecuteMarketOrder(TradeType.Buy, Symbol, 1000, "Trade", 25, 50);
                double entryprice = LastResult.Position.EntryPrice;
                Print("Entry: {0}", entryprice);
            }
        }

        private void SellEntry()
        {
            if (Positions.Count == 0)
            {
                ExecuteMarketOrder(TradeType.Sell, Symbol, 1000, "Trade", 25, 50);
                double entryprice = LastResult.Position.EntryPrice;
                Print("Entry: {0}", entryprice);
            }
        }

    }
}

 

 


@nordic
Replies

nordic
01 Sep 2018, 11:47 ( Updated at: 21 Dec 2023, 09:20 )

Example of the above issue:

Also, shouldn't ModifyPosition re-set the SL and TP values from the point the volume of the position is modified as it's essentially a new order?  The below seems to retain the original SL and TP values after the position is modified.


@nordic

PanagiotisCharalampous
03 Sep 2018, 11:20

Hi nordic,

This is a known bug and has been fixed in Spotware cTrader Public Beta. Can you try it as well and confirm that is working properly for your cBot?

Best Regards,

Panagiotis


@PanagiotisCharalampous

nordic
04 Sep 2018, 15:46

Thanks Panagiotis, I hadn't tried the Beta in a while - and holy hell, visual backtesting is here, and it works wonderfully!  I had no idea.  Being able to cross-check with Visual mode made me realise this isn't a bug, just unclear notation on the chart.  The line on the chart begins on the X-axis where the initial entry was made, and when ModifyPosition kicks in, the line is offset to where the position volume was modified, but only on the Y axis.

Using standard backtesting it looks like a bug on the finished chart, but with Visual mode it's clear that what happens is in fact accurate.

By the way, my hat off to the team who built the Visual system. My only qualm is that it has no rewind ability during backtest, but it's a minor gripe as it seems to function very well, and much faster than previously.  This will give a huge extra dimension to algo development on cTrader. Love it.


@nordic