Replies

PUdPUd
02 Apr 2021, 15:32

RE:

Thanks for your thoughts Afhacker. Your suggested amendment gives the following error: Error CS0136: A local variable named 'TargetLongMath' cannot be declared in this scope because it would give a different meaning to 'TargetLongMath', which is already used in a 'parent or current' scope to denote something else

 


@PUdPUd

PUdPUd
02 Apr 2021, 13:31

RE:

Thank you for the syntax changes Amusleh, much appreciated. None of my variables start with a number so I am not sure what you refer to above.

 

My only outstanding problem is being able to select the predefined TP and SL from each of the model coefficients I have developed depending on the level of GBPUSD yesterday. Depending on the level of GBPUSD the cbot needs to select the appropriate TP and SL, some levels have the same TP and SL and some don't, and some have a combination of new and old TP and SL, hence the repetition. If there is a better way to select this than using if, else statements please say so so that I can investigate. If I could afford someone to code it for me I would!

 

If anyone can advise on why my I am getting Error CS0103: The name 'TargetLongMath' does not exist in the current context and the same for TargetShortMath that would be much appreciated.

 

Updated code here with all variables: 

 

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 aNarrowestCI : Robot

    {

        [Parameter(DefaultValue = 0.0)]

        public double Parameter { get; set; }

 

        private Bars series2, series3;

        private Symbol symbol2, symbol3;

 

        [Parameter(DefaultValue = "EURUSD")]

        public string Symbol2 { get; set; }

 

        [Parameter(DefaultValue = "GBPUSD")]

        public string Symbol3 { get; set; }

 

        protected override void OnStart()

        {

            var dailyBars = MarketData.GetBars(TimeFrame.Daily);

            dailyBars.BarOpened += OnDailyBarsBarOpened;

        }

 

        void OnDailyBarsBarOpened(BarOpenedEventArgs obj)

        {

 

            var Lag1USDCADHigh = obj.Bars.HighPrices.Last(1);

            var Lag1USDCADOpen = obj.Bars.OpenPrices.Last(1);

            var Lag1USDCADLow = obj.Bars.LowPrices.Last(1);

            var Lag1USDCADOpenHigh = Lag1USDCADHigh - Lag1USDCADOpen;

            var Lag1USDCADOpenLow = Lag1USDCADOpen - Lag1USDCADLow;

            var Lag1USDCADVolume = obj.Bars.TickVolumes.Last(1);

            var Lag1USDCADPropOH = (Lag1USDCADOpenHigh / Lag1USDCADOpen) * 100;

 

            var symbol2 = Symbols.GetSymbol(Symbol2);

            series2 = MarketData.GetBars(TimeFrame.Daily, Symbol2);

            var GBPUSDYDaysClose = series2.ClosePrices.Last(0);

            var Lag1GBPUSDHigh = series2.HighPrices.Last(0);

            var Lag1GBPUSDLow = series2.LowPrices.Last(0);

            var Lag1GBPUSDOpen = series2.OpenPrices.Last(0);

            var Lag1GBPUSDOpenLow = Lag1GBPUSDOpen - Lag1GBPUSDLow;

            var Lag1GBPUSDOpenHigh = Lag1GBPUSDHigh - Lag1GBPUSDOpen;

            var Lag1GBPUSDPropHighLow = ((Lag1GBPUSDHigh - Lag1GBPUSDLow) / Lag1GBPUSDOpen) * 100;

 

            var symbol3 = Symbols.GetSymbol(Symbol3);

            series3 = MarketData.GetBars(TimeFrame.Daily, Symbol3);

            var Lag1EURUSDHigh = series3.HighPrices.Last(0);

            var Lag1EURUSDOpen = series3.OpenPrices.Last(0);

            var Lag1EURUSDVolume = series3.TickVolumes.Last(1);

 

 

            // < 1.10

            //Long Model 5

            var FM5LongMath = -1 + (2 * Lag1USDCADHigh) + (3* Lag1USDCADOpenLow) + (4 * Lag1GBPUSDOpenLow) + (-5 * Lag1GBPUSDPropHighLow) + (6 * Lag1EURUSDHigh);

            //Short Model 2

            var FM2ShortMath = -7 + (8 * Lag1USDCADLow) + (9 * Lag1USDCADOpenHigh);

            var FM5LongSL_15 = -10;

            var FM2ShortSL_15 = 9;

 

            //>= 1.10 GBPUSDYDaysClose < 1.20         

            //Long Model 5

            var FM5LongSL_15_20 = -8;

            //Short Model 3

            var FM3ShortMath = 7 + (6 * Lag1USDCADLow) + (5 * Lag1USDCADOpenHigh) + (-4 * Lag1GBPUSDOpen);

            var FM3ShortSL_15_20 = 3;

 

            //>= 1.20 GBPUSDYDaysClose < 1.25

            //Long Model 5

            var FM5LongSL_20_25 = 2;

            //Short Model 2

            var FM2ShortSL_20_25 = 1;

 

            //  >= 1.25 GBPUSDYDaysClose < 1.30

            //Long Model 5

            var FM5LongSL_25_30 = -1;

            //Short Model 2

            var SM2ShortMath = -2 + (3 * Lag1USDCADOpen) + (4 * Lag1USDCADPropOH);

            var SM2ShortSL_25_30 = 5;

 

            //>= 1.30 GBPUSDYDaysClose < 1.45

            //Long Model 5

            var FM5LongSL_30_45 = -6;

            //Short Model 4

            var FM4ShortMath = 7 + (8 * Lag1USDCADLow) + (9 * Lag1USDCADOpenHigh) + (-8 * Lag1GBPUSDOpen) + (-1 * Lag1USDCADOpenLow);

            var FM4ShortSL_30_45 = 2;

 

            //GBPUSDYDaysClose >= 1.45

            //Long Model 1

            var BM1LongMath = -3 + (4 * GBPUSDYDaysClose) + (5 * Lag1USDCADOpen) + (-6 * Lag1USDCADVolume) + (-7 * Lag1GBPUSDOpenHigh) + (8 * Lag1EURUSDVolume) + (9 * Lag1USDCADOpenHigh) + (8 * Lag1USDCADOpenLow) + (7 * Lag1GBPUSDPropHighLow) + 6 * Lag1EURUSDOpen);

            var BM1LongSL_45 = -54.13;

 

            //Short Model 3

            var FM3ShortSL_45 = 102.914;

 

 

            if (GBPUSDYDaysClose < 15)

            {

                var TargetLongMath = FM5LongMath;

                // var LongSL = FM5LongSL_15;

                //var TargetShortMath = FM2ShortMath;

                // var ShortSL = FM2ShortSL_15;

            }

 

            else

            {

                if ((GBPUSDYDaysClose >= 15) && (GBPUSDYDaysClose < 20))

                {

                    var TargetLongMath = FM5LongMath;

                    //var LongSL = FM5LongSL_15_20;

                    //var TargetShortMath = FM3ShortMath;

                    //var ShortSL = FM3ShortSL_15_20;

 

                }

 

 

                else if ((GBPUSDYDaysClose >= 20) && (GBPUSDYDaysClose < 25))

                {

                    var TargetLongMath = FM5LongMath;

                    // var LongSL = FM5LongSL_20_25;

                    //var TargetShortMath = FM2ShortMath;

                    //var ShortSL = FM2ShortSL_20_25;

                }

 

                else if ((GBPUSDYDaysClose >= 25) && (GBPUSDYDaysClose < 30))

                {

                    var TargetLongMath = FM5LongMath;

                    // var LongSL = FM5LongSL_25_30;

                    //var TargetShortMath = SM2ShortMath;

                    // var ShortSL = SM2ShortSL_25_30;

                }

 

                else if ((GBPUSDYDaysClose >= 30) && (GBPUSDYDaysClose < 45))

                {

                    var TargetLongMath = FM5LongMath;

                    // var LongSL = FM5LongSL_30_45;

                    //var TargetShortMath = FM4ShortMath;

                    //var ShortSL = FM4ShortSL_30_45;

                }

 

                else if (GBPUSDYDaysClose >= 45)

                {

                    var TargetLongMath = BM1LongMath;

                    // var LongSL = BM1LongSL_45;

                    //var TargetShortMath = FM3ShortMath;

                    //var ShortSL = FM3ShortSL_45;

 

                }

 

 

                //Long structure

                //var Targetlong = TargetLongMath;

                var TargetLong = (Math.Round(TargetLongMath, 3));

                var TargetPipslong = TargetLong - Symbol.Bid * Symbol.PipSize;

                var TargetPipsLong = (Math.Round(TargetPipslong, 3));

 

 

                //Short structure

                var TargetShort = (Math.Round(TargetShortMath, 3));

                var TargetPipsshort = TargetShort - Symbol.Ask * Symbol.PipSize;

                var TargetPipsShort = (Math.Round(TargetPipsshort, 3));

 

 

                foreach (var position in Positions)

                {

                    ClosePosition(position);

                }

 

                if (TargetPipsLong > 0)

                {

                    if (TargetPipsShort > 0)

                    {

                        var risk = 0.95;

 

                        double Volume = (long)Math.Ceiling(Account.Equity / 100) * risk;

                        double MaxVolume = Volume / 100;

 

                        Volume = Symbol.NormalizeVolumeInUnits(Volume, RoundingMode.Down);

 

                        if (Volume > 100)

                            Volume = 100;

 

                        var SLprop = 0.0;

                        var SLBid = (Math.Round(Symbol.Bid * SLprop, 2));

                        var SLAsk = (Math.Round(Symbol.Ask * SLprop, 2));

 

                        var TPBidProp = TargetPipsLong;

                        var TPBid = (Math.Round(TPBidProp * Symbol.PipSize, 2));

 

                        var TPAskProp = TargetPipsShort;

                        var TPAsk = (Math.Round(TPAskProp * Symbol.PipSize, 2));

 

                        PlaceStopOrder(TradeType.Buy, SymbolName, Volume, Symbol.Bid + 3 * Symbol.PipSize, "OpenStopBuy", SLBid, TPBid, Server.Time.AddHours(23));

 

                        PlaceStopOrder(TradeType.Sell, SymbolName, Volume, Symbol.Ask - 3 * Symbol.PipSize, "OpenStopSell", SLAsk, TPAsk, Server.Time.AddHours(23));

 

                    }

                }

 

 

            }

        }

 

 

 

 

        protected override void OnTick()

        {

            // Put your core logic here

        }

 

        protected override void OnStop()

        {

            // Put your deinitialization logic here

        }

    }

}

 


@PUdPUd

PUdPUd
01 Apr 2021, 21:17

RE:

PanagiotisCharalampous said:

Hi PUdPUd,

Pending orders are sent to the server as soon as they are placed.

Best Regards,

Panagiotis 

Join us on Telegram

Thank you!


@PUdPUd

PUdPUd
29 Mar 2021, 12:12 ( Updated at: 21 Dec 2023, 09:22 )

RE:

I have contacted Pepperstone and they won't upload further data even though they provide plenty of data for other instruments. Does anyone have any recommendations for a broker that has more data for backtesting or a workaround solution? Otherwise I am going to have model this using daily data in an external application. 

 

PanagiotisCharalampous said:

Hi PUdPUd,

You can upload external backtesting data but only for the symbol on which the cBot is executed. If you need the data for another symbol then there is no easy way to do this.

Maybe you can contact your broker in case they can provide a more extended history for you.

Best Regards,

Panagiotis 

Join us on Telegram

 


@PUdPUd

PUdPUd
09 Feb 2021, 22:59

RE:

Hi PanagiotisCharalampous

I am having trouble implementing your code. It works fine once but I would like to run it each day. I added the ExecuteMarketOrder entry into the OnStart and subscribed it to daily bars, but then the code doesn't execute any market order.

 protected override void OnStart()
        {
            var dailyBars = MarketData.GetBars(TimeFrame.Daily);
            dailyBars.BarOpened += OnDailyBarsBarOpened;
        }


        void OnDailyBarsBarOpened(BarOpenedEventArgs obj)
        {

            //Execute a market order based on the direction parameter
            ExecuteMarketOrder(Buy ? TradeType.Buy : TradeType.Sell, SymbolName, Volume, "SampleTrailing", StopLoss, 20);
            //Set the position's highest gain in pips
            _highestGain = Positions[0].Pips;
        }

 

Also, I would like to do this for a combination of market orders and to modify stop orders once they are executed so I would need a dictionary. I cannot seem to find documentation on the syntax for Dictionary. Where do I find this?

 

Thanks

 

PanagiotisCharalampous said:

Hi Jan,

Positions.Find will only return one position matching the label. There are several changes that you need to make to this example in order to be adapted to handle any number of positions. For example, you will need to track a separate TriggerWhenGaining for each position, maybe with the use of a dictionary.

Best Regards,

Panagiotis 

Join us on Telegram

 

 


@PUdPUd

PUdPUd
09 Feb 2021, 22:54

RE: Simple and robust trailing algorithm

Hi Abdul

I have tried to implement your code as written and the dictionary component doesn't work and I can't find documentation for the syntax. The error that I am getting is Error CS1502: The best overloaded method match for 'System.Collections.Generic.Dictionary<cAlgo.API.Position,double>.Add(cAlgo.API.Position, double)' has some invalid arguments.

Where is the syntax for dictionary in cTrader?

Thanks for the code

PUdPUd

 

 

 

abdulhamid0yusuf said:

I came here to see how to implement a trailing stop loss, but the code provided by cTrader Team was unnecessarily complicated to me, so I would like to share my way ...

using cAlgo.API;
using System.Collections.Generic;
using System.Linq;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class TestTrailingStop : Robot
    {
        // Save the maximum winning pips each position has reached
        private Dictionary<Position, double> PositionsMaxProfits;

        [Parameter("Winning Pips to protect", DefaultValue = 10)]
        public int PipsToProtect { get; set; }

        [Parameter("Trailing Stop Distance", DefaultValue = 5)]
        public int TrailingDistance { get; set; }


        protected override void OnStart()
        {
            PositionsMaxProfits = new Dictionary<Position, double>();
            // Market order for illustration purposes
            var p = ExecuteMarketOrder(TradeType.Sell, SymbolName, 1000).Position;
            // Add every order you create to the dictionary and set its initial max pips to 0
            PositionsMaxProfits.Add(p, 0);
        }

        protected override void OnTick()
        {
            // Update Stop loss on each tick once the position has yeilded winning pips >= PipsToProtect + TrailingDistance
            foreach (Position position in PositionsMaxProfits.Keys.ToList())
            {
                var positionMaxProfit = PositionsMaxProfits[position];
                // 1st condition checks if winning pips >= PipsToProtect + TrailingDistance
                // 2ed condition checks if winning pips is greater than previous winning pips
                if ((position.Pips >= PipsToProtect + TrailingDistance) && position.Pips > positionMaxProfit)
                {
                    // Assign the new higher winning pips to the position
                    PositionsMaxProfits[position] = position.Pips;
                    // Modify Stop loss to be $TrailingDistance pips away from current winnig pips
                    // ** -1 means put stop loss on oppostie direction than normal
                    position.ModifyStopLossPips(-1 * (position.Pips - TrailingDistance));
                }
            }

        }
    }
}

 

 


@PUdPUd

PUdPUd
26 Jan 2021, 13:48 ( Updated at: 21 Dec 2023, 09:22 )

RE: RE:

Here are some screenshots corresponding to the problems described. Here on 03/01/2020 over a dozen orders were placed:

Here only the first two trades in the list are placed each day:


@PUdPUd

PUdPUd
26 Jan 2021, 13:36

RE:

Dear Panagiotis 

I don't expect 6 trades a day, I expect 6 stop orders per day. This code prints the name of the stop order once placed, and according to the log file the incorrect number of stop orders are placed as described previously. 

PUdPud

 


@PUdPUd

PUdPUd
26 Jan 2021, 13:08 ( Updated at: 26 Jan 2021, 13:09 )

RE:

Dear Panagiotis 

The code is very simple and without indicators and is supplied below. Both versions were applied to US500 Daily chart. Here is the code for where the order is replicated anywhere between 8-25 times per day, the other code is supplied after that:.

---------------------------------------------------------------Code that produces 8-25 trades per day rather than 6

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.EasternStandardTime, AccessRights = AccessRights.None)]
    public class Test2 : Robot
    {
        [Parameter(DefaultValue = 0.0)]
        public double Parameter { get; set; }


        protected override void OnStart()
        {
            var dailyBars = MarketData.GetBars(TimeFrame.Daily);
            dailyBars.BarOpened += OnDailyBarsBarOpened;
        }

        void OnDailyBarsBarOpened(BarOpenedEventArgs obj)
        {
            PlaceStopOrder(TradeType.Buy, SymbolName, 1, Symbol.Bid + 2 * Symbol.PipSize, "OpenStopBuy", 18, 21);
            PlaceStopOrder(TradeType.Sell, SymbolName, 1, Symbol.Ask - 2 * Symbol.PipSize, "OpenStopSell", 18, 21);
            PlaceStopOrder(TradeType.Buy, SymbolName, 1, Symbol.Bid + 22 * Symbol.PipSize, "2ndStopBuy", 18, 21);
            PlaceStopOrder(TradeType.Sell, SymbolName, 1, Symbol.Ask - 22 * Symbol.PipSize, "2ndStopSell", 18, 21);
            PlaceStopOrder(TradeType.Buy, SymbolName, 1, Symbol.Bid + 42 * Symbol.PipSize, "3rdStopBuy", 18, 21);
            PlaceStopOrder(TradeType.Sell, SymbolName, 1, Symbol.Ask - 42 * Symbol.PipSize, "3rdStopSell", 18, 21);

            foreach (var pendingOrder in PendingOrders)
            {
                Print("Order placed with label {0}, id {1}", pendingOrder.Label, pendingOrder.Id);
            }

        }


        protected override void OnBar()
        {

        }


        protected override void OnStop()
        {
            // Put your deinitialization logic here
        }
    }
}

 

---------------------------------------------------------------Code that produces only two trades out of the six per day:

 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.EasternStandardTime, AccessRights = AccessRights.None)]
    public class Test2 : Robot
    
    {
        [Parameter(DefaultValue = 0.0)]
        public double Parameter { get; set; }


        protected override void OnStart()
        {
            var dailyBars = MarketData.GetBars(TimeFrame.Daily);
            dailyBars.BarOpened += OnDailyBarsBarOpened;
        }
        
        protected override void OnBar()
        void OnDailyBarsBarOpened(BarOpenedEventArgs obj)
        {
           PlaceStopOrder(TradeType.Buy, SymbolName, 1, Symbol.Bid + 2 * Symbol.PipSize, "OpenStopBuy", 18, 21);
           PlaceStopOrder(TradeType.Sell, SymbolName, 1, Symbol.Ask - 2 * Symbol.PipSize, "OpenStopSell", 18, 21);
           PlaceStopOrder(TradeType.Buy, SymbolName, 1, Symbol.Bid + 22 * Symbol.PipSize, "2ndStopBuy", 18, 21);
           PlaceStopOrder(TradeType.Sell, SymbolName, 1, Symbol.Ask - 22 * Symbol.PipSize, "2ndStopSell", 18, 21);
           PlaceStopOrder(TradeType.Buy, SymbolName, 1, Symbol.Bid + 42 * Symbol.PipSize, "3rdStopBuy", 18, 21);
           PlaceStopOrder(TradeType.Sell, SymbolName, 1, Symbol.Ask - 42 * Symbol.PipSize, "3rdStopSell", 18, 21);
           

            foreach (var pendingOrder in PendingOrders)
            {
                Print("Order placed with label {0}, id {1}", pendingOrder.Label, pendingOrder.Id);
            }
        }


        protected override void OnStop()
        {
            // Put your deinitialization logic here
        }
    }
}

 


@PUdPUd

PUdPUd
25 Jan 2021, 19:05 ( Updated at: 25 Jan 2021, 19:18 )

RE: RE:

Hi Panagiotis 

Thanks for your comments. I tried your recommendation and during backtesting the first day 6 stop orders were successfully entered into the system, but  every other day after then anywhere between 8 and 25 stop orders were placed per day. Also, this only seems to work for indices and commodities but not currency pairs. Perhaps I have missed something? If I put that logic in OnBar() only the first 2 stop orders are executed but on some days 3 stop orders are executed by duplicating the first or second order again. 

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.EasternStandardTime, AccessRights = AccessRights.None)]
    public class Test2 : Robot
    {
        [Parameter(DefaultValue = 0.0)]
        public double Parameter { get; set; }


        protected override void OnStart()
        {
            var dailyBars = MarketData.GetBars(TimeFrame.Daily);
            dailyBars.BarOpened += OnDailyBarsBarOpened;
        }

        void OnDailyBarsBarOpened(BarOpenedEventArgs obj)
        {
            PlaceStopOrder(TradeType.Buy, SymbolName, 1, Symbol.Bid, "Trade1");
            PlaceStopOrder(TradeType.Sell, SymbolName, 1, Symbol.Ask, "Trade2");
            PlaceStopOrder(TradeType.Buy, SymbolName, 1, Symbol.Bid, "Trade3");
            PlaceStopOrder(TradeType.Sell, SymbolName, 1, Symbol.Ask, "Trade4");
            PlaceStopOrder(TradeType.Buy, SymbolName, 1, Symbol.Bid, "Trade5");
            PlaceStopOrder(TradeType.Sell, SymbolName, 1, Symbol.Ask, "Trade6");            

foreach (var pendingOrder in PendingOrders)
            {
                Print("Order placed with label {0}, id {1}", pendingOrder.Label, pendingOrder.Id);
            }

        }


        protected override void OnBar()
        {

        }


        protected override void OnStop()
        {
            // Put your deinitialization logic here
        }
    }
}

 

 


@PUdPUd