PanagiotisCharalampous's avatar
PanagiotisCharalampous
26 follower(s) 0 following 1006 subscription(s)
Replies

PanagiotisCharalampous
09 Sep 2019, 10:29

Hi Phil,

Thanks for posting in our forum. We could not reproduce any noticeable difference in performance. Are you sure it is not a local problem i.e. your pc performance or slow network? If you can still reproduce the issue, please provide the exact steps you are following. If you can grab a short video demonstrating the steps and the behavior, it would be helpful.

Best Regards,

Panagiotis


@PanagiotisCharalampous

PanagiotisCharalampous
09 Sep 2019, 10:23

Hi buccinator,

Can you share the cBot code with us and provide exact steps to reproduce the problem?

Best Regards,

Panagiotis


@PanagiotisCharalampous

PanagiotisCharalampous
09 Sep 2019, 10:18

Hi ctid1373829,

Please see a corrected cBot below.

using System;
using System.Linq;
using cAlgo.API;

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class NorsePiprunner : Robot
    {
        [Parameter("Buy", DefaultValue = true)]
        public bool Buy { get; set; }

        [Parameter("Sell", DefaultValue = true)]
        public bool Sell { get; set; }

        [Parameter("Pip Step", DefaultValue = 10, MinValue = 1)]
        public int PipStep { get; set; }

        [Parameter("First Volume", DefaultValue = 1000, MinValue = 1000, Step = 1000)]
        public int FirstVolume { get; set; }

        [Parameter("Max Spread", DefaultValue = 3.0)]
        public double MaxSpread { get; set; }

        [Parameter("Average TP", DefaultValue = 3, MinValue = 1)]
        public int AverageTP { get; set; }

        [Parameter("Stop Loss", DefaultValue = 40)]
        public int StopLoss { get; set; }


        [Parameter("Volume Exponent", DefaultValue = 1.0, MinValue = 0.1, MaxValue = 5.0)]
        public double VolumeExponent { get; set; }

        private string Label = "piprunner";
        private Position position;
        private DateTime buyOpenTime;
        private DateTime sellOpenTime;
        private int orderStatus;
        private double currentSpread;
        private bool initial_start = true;
        private bool cStop = false;

        protected override void OnStart()
        {
        }
        protected override void OnTick()
        {
            currentSpread = (Symbol.Ask - Symbol.Bid) / Symbol.PipSize;
            if (activeDirectionCount(TradeType.Buy) > 0)
                TrailBuySL(AverageEntryPrice(TradeType.Buy), AverageTP);
            if (activeDirectionCount(TradeType.Sell) > 0)
                TrailSellSL(AverageEntryPrice(TradeType.Sell), AverageTP);
            if (MaxSpread >= currentSpread && !cStop)
                SimpleLogic();
            DrawDescisionLines();
        }
        protected override void OnError(Error error)
        {
            if (error.Code == ErrorCode.NoMoney)
            {
                cStop = true;
                Print("openning stopped because: not enough money");
            }
        }
        protected override void OnBar()
        {
            RefreshData();
        }
        protected override void OnStop()
        {
            ChartObjects.RemoveAllObjects();
        }
        private void SimpleLogic()
        {
            if (initial_start)
            {
                //Entry Signal previous bar larger than the one before
                if (Buy && activeDirectionCount(TradeType.Buy) == 0 && MarketSeries.Close.Last(1) > MarketSeries.Close.Last(2))
                {
                    orderStatus = OrderSend(TradeType.Buy, Volumizer(FirstVolume));
                    if (orderStatus > 0)
                        buyOpenTime = MarketSeries.OpenTime.Last(0);
                    else
                        Print("First BUY openning error at: ", Symbol.Ask, "Error Type: ", LastResult.Error);
                }
                //Entry signal  previous bar smaller than the one before
                if (Sell && activeDirectionCount(TradeType.Sell) == 0 && MarketSeries.Close.Last(2) > MarketSeries.Close.Last(1))
                {
                    orderStatus = OrderSend(TradeType.Sell, Volumizer(FirstVolume));
                    if (orderStatus > 0)
                        sellOpenTime = MarketSeries.OpenTime.Last(0);
                    else
                        Print("First SELL openning error at: ", Symbol.Bid, "Error Type: ", LastResult.Error);
                }
            }
            Gridernize();
        }


        //Create the Grid sistem based on the PipStep
        private void Gridernize()
        {
            if (activeDirectionCount(TradeType.Buy) > 0)
            {
                if (Math.Round(Symbol.Ask, Symbol.Digits) < Math.Round(GetHighestBuyEntry(TradeType.Buy) - PipStep * Symbol.PipSize, Symbol.Digits) && buyOpenTime != MarketSeries.OpenTime.Last(0))
                {
                    long b_lotS = NextLotSize(TradeType.Buy);
                    orderStatus = OrderSend(TradeType.Buy, Volumizer(b_lotS));
                    if (orderStatus > 0)
                        buyOpenTime = MarketSeries.OpenTime.Last(0);
                    else
                        Print("Next BUY openning error at: ", Symbol.Ask, "Error Type: ", LastResult.Error);
                }
            }
            if (activeDirectionCount(TradeType.Sell) > 0)
            {
                if (Math.Round(Symbol.Bid, Symbol.Digits) > Math.Round(GetLowestSellEntry(TradeType.Sell) + PipStep * Symbol.PipSize, Symbol.Digits) && sellOpenTime != MarketSeries.OpenTime.Last(0))
                {
                    long s_lotS = NextLotSize(TradeType.Sell);
                    orderStatus = OrderSend(TradeType.Sell, Volumizer(s_lotS));
                    if (orderStatus > 0)
                        sellOpenTime = MarketSeries.OpenTime.Last(0);
                    else
                        Print("Next SELL openning error at: ", Symbol.Bid, "Error Type: ", LastResult.Error);
                }
            }
        }
        private int OrderSend(TradeType TrdTp, long iVol)
        {
            int orderStatus = 0;
            if (iVol > 0)
            {
                TradeResult result = ExecuteMarketOrder(TrdTp, Symbol.Name, iVol, Label, StopLoss, 0.0, "smart_grid");

                if (result.IsSuccessful)
                {
                    Print(TrdTp, "Opened at: ", result.Position.EntryPrice);
                    orderStatus = 1;
                }
                else
                    Print(TrdTp, "Openning Error: ", result.Error);
            }
            else
                Print("Volume calculation error: Calculated Volume is: ", iVol);
            return orderStatus;
        }


        //Trail the stoploss position for a BUY Order
        private void TrailBuySL(double price, int tp)
        {
            foreach (var position in Positions)
            {
                if (position.Label == Label && position.SymbolCode == Symbol.Code)
                {
                    if (position.TradeType == TradeType.Buy)
                    {
                        double? new_tp = Math.Round(price + tp * Symbol.PipSize, Symbol.Digits);
                        if (position.TakeProfit != new_tp)
                            ModifyPosition(position, position.StopLoss, new_tp);
                    }
                }
            }
        }


        //Trail the stoploss position for a SELL Order
        private void TrailSellSL(double price, int tp)
        {
            foreach (var position in Positions)
            {
                if (position.Label == Label && position.SymbolCode == Symbol.Code)
                {
                    if (position.TradeType == TradeType.Sell)
                    {
                        double? new_tp = Math.Round(price - tp * Symbol.PipSize, Symbol.Digits);
                        if (position.TakeProfit != new_tp)
                            ModifyPosition(position, position.StopLoss, new_tp);
                    }
                }
            }
        }

        //Draw the Action lines to illustrate the trades
        private void DrawDescisionLines()
        {
            if (activeDirectionCount(TradeType.Buy) > 1)
            {
                double y = AverageEntryPrice(TradeType.Buy);
                ChartObjects.DrawHorizontalLine("bpoint", y, Colors.Yellow, 2, LineStyle.Dots);
            }
            else
                ChartObjects.RemoveObject("bpoint");
            if (activeDirectionCount(TradeType.Sell) > 1)
            {
                double z = AverageEntryPrice(TradeType.Sell);
                ChartObjects.DrawHorizontalLine("spoint", z, Colors.HotPink, 2, LineStyle.Dots);
            }
            else
                ChartObjects.RemoveObject("spoint");
            ChartObjects.DrawText("pan", botText(), StaticPosition.TopLeft, Colors.Tomato);
        }

        //Text to be printed on Screen
        private string botText()
        {
            string printString = "";
            string BPos = "";
            string SPos = "";
            string spread = "";
            string BTA = "";
            string STA = "";
            double CBPOS = 0;
            double CSPOS = 0;

            CBPOS = activeDirectionCount(TradeType.Buy);
            CSPOS = activeDirectionCount(TradeType.Sell);
            spread = "\nSpread = " + Math.Round(currentSpread, 1);
            if (CBPOS > 0)
                BPos = "\nBuy Positions = " + activeDirectionCount(TradeType.Buy);
            if (CSPOS > 0)
                SPos = "\nSell Positions = " + activeDirectionCount(TradeType.Sell);
            if (activeDirectionCount(TradeType.Buy) > 0)
            {
                double abta = Math.Round((AverageEntryPrice(TradeType.Buy) - Symbol.Bid) / Symbol.PipSize, 1);
                BTA = "\nBuy Target Away = " + abta;
            }
            if (activeDirectionCount(TradeType.Sell) > 0)
            {
                double asta = Math.Round((Symbol.Ask - AverageEntryPrice(TradeType.Sell)) / Symbol.PipSize, 1);
                STA = "\nSell Target Away = " + asta;
            }
            if (currentSpread > MaxSpread)
                printString = "MAX SPREAD EXCEED";
            else
                printString = "Foxy Grid" + BPos + spread + SPos + BTA + STA;
            return (printString);
        }

        //Return the active positions of this bot
        private int ActiveLabelCount()
        {
            int ASide = 0;

            for (int i = Positions.Count - 1; i >= 0; i--)
            {
                position = Positions[i];
                if (position.Label == Label && position.SymbolCode == Symbol.Code)
                    ASide++;
            }
            return ASide;
        }

        //Return the position count of trades of specific type (BUY/SELL)
        private int activeDirectionCount(TradeType TrdTp)
        {
            int TSide = 0;

            for (int i = Positions.Count - 1; i >= 0; i--)
            {
                position = Positions[i];
                if (position.Label == Label && position.SymbolCode == Symbol.Code)
                {
                    if (position.TradeType == TrdTp)
                        TSide++;
                }
            }
            return TSide;
        }

        //The Avarage EtryPrice for all positions of a specific type (SELL/BUY)
        private double AverageEntryPrice(TradeType TrdTp)
        {
            double Result = 0;
            double AveragePrice = 0;
            long Count = 0;

            for (int i = Positions.Count - 1; i >= 0; i--)
            {
                position = Positions[i];
                if (position.Label == Label && position.SymbolCode == Symbol.Code)
                {
                    if (position.TradeType == TrdTp)
                    {
                        AveragePrice += position.EntryPrice * position.Volume;
                        Count += position.Volume;
                    }
                }
            }
            if (AveragePrice > 0 && Count > 0)
                Result = Math.Round(AveragePrice / Count, Symbol.Digits);
            return Result;
        }


        private double GetHighestBuyEntry(TradeType TrdTp)
        {
            double GetHighestBuyEntry = 0;

            for (int i = Positions.Count - 1; i >= 0; i--)
            {
                position = Positions[i];
                if (position.Label == Label && position.SymbolCode == Symbol.Code)
                {
                    if (position.TradeType == TrdTp)
                    {
                        if (GetHighestBuyEntry == 0)
                        {
                            GetHighestBuyEntry = position.EntryPrice;
                            continue;
                        }
                        if (position.EntryPrice < GetHighestBuyEntry)
                            GetHighestBuyEntry = position.EntryPrice;
                    }
                }
            }
            return GetHighestBuyEntry;
        }


        private double GetLowestSellEntry(TradeType TrdTp)
        {
            double GetLowestSellEntry = 0;

            for (int i = Positions.Count - 1; i >= 0; i--)
            {
                position = Positions[i];
                if (position.Label == Label && position.SymbolCode == Symbol.Code)
                {
                    if (position.TradeType == TrdTp)
                    {
                        if (GetLowestSellEntry == 0)
                        {
                            GetLowestSellEntry = position.EntryPrice;
                            continue;
                        }
                        if (position.EntryPrice > GetLowestSellEntry)
                            GetLowestSellEntry = position.EntryPrice;
                    }
                }
            }
            return GetLowestSellEntry;
        }


        private double LastEntry(TradeType TrdTp)
        {
            double LastEntryPrice = 0;
            int APositionID = 0;
            for (int i = Positions.Count - 1; i >= 0; i--)
            {
                position = Positions[i];
                if (position.Label == Label && position.SymbolCode == Symbol.Code)
                {
                    if (position.TradeType == TrdTp)
                    {
                        if (APositionID == 0 || APositionID > position.Id)
                        {
                            LastEntryPrice = position.EntryPrice;
                            APositionID = position.Id;
                        }
                    }
                }
            }
            return LastEntryPrice;
        }


        private long LastVolume(TradeType TrdTp)
        {
            long LastVolumeTraded = 0;
            int APositionID = 0;
            for (int i = Positions.Count - 1; i >= 0; i--)
            {
                position = Positions[i];
                if (position.Label == Label && position.SymbolCode == Symbol.Code)
                {
                    if (position.TradeType == TrdTp)
                    {
                        if (APositionID == 0 || APositionID > position.Id)
                        {
                            LastVolumeTraded = position.Volume;
                            APositionID = position.Id;
                        }
                    }
                }
            }
            return LastVolumeTraded;
        }


        private long clt(TradeType TrdTp)
        {
            long Result = 0;
            for (int i = Positions.Count - 1; i >= 0; i--)
            {
                position = Positions[i];
                if (position.Label == Label && position.SymbolCode == Symbol.Code)
                {
                    if (position.TradeType == TrdTp)
                        Result += position.Volume;
                }
            }
            return Result;
        }


        private int GridCount(TradeType TrdTp1, TradeType TrdTp2)
        {
            double LastEntryPrice = LastEntry(TrdTp2);
            int APositionID = 0;
            for (int i = Positions.Count - 1; i >= 0; i--)
            {
                position = Positions[i];
                if (position.Label == Label && position.SymbolCode == Symbol.Code)
                {
                    if (position.TradeType == TrdTp1 && TrdTp1 == TradeType.Buy)
                    {
                        if (Math.Round(position.EntryPrice, Symbol.Digits) <= Math.Round(LastEntryPrice, Symbol.Digits))
                            APositionID++;
                    }
                    if (position.TradeType == TrdTp1 && TrdTp1 == TradeType.Sell)
                    {
                        if (Math.Round(position.EntryPrice, Symbol.Digits) >= Math.Round(LastEntryPrice, Symbol.Digits))
                            APositionID++;
                    }
                }
            }
            return APositionID;
        }


        private long NextLotSize(TradeType TrdRp)
        {
            int current_Volume = GridCount(TrdRp, TrdRp);
            long last_Volume = LastVolume(TrdRp);
            long next_Volume = Symbol.NormalizeVolume(last_Volume * Math.Pow(VolumeExponent, current_Volume));
            return next_Volume;
        }


        private long Volumizer(long vol)
        {
            long volmin = Symbol.VolumeMin;
            long volmax = Symbol.VolumeMax;
            long voltemp = vol;

            if (voltemp < volmin)
                voltemp = volmin;
            if (voltemp > volmax)
                voltemp = volmax;
            return voltemp;
        }
    }
}

If you are not familiar with programming, I would suggest you do not make changes yourself but contact a professional instead.

Best Regards,

Panagiotis


@PanagiotisCharalampous

PanagiotisCharalampous
09 Sep 2019, 10:07

Hi therealnakedtrader,

There is no such option at the moment.

Best Regards,

Panagiotis


@PanagiotisCharalampous

PanagiotisCharalampous
09 Sep 2019, 10:06

Hi calgodemo,

  1. Yes you can but you need to add it manually. The instance on the chart is a different instance to the cBot one
  2. cTrader Automate is not thread safe thus does not support multithreading
    1. Backtesting sometimes skips some ticks for indicator calculation on the backesting chart. This can cause discrepancies between the indicator value shown on the chart and the indicator referenced inside the cBot. The correct one is the one referenced inside the cBot. To be able to detemine if this is the case we need the indicator code
    2. The above

Best Regards,

Panagiotis

 


@PanagiotisCharalampous

PanagiotisCharalampous
09 Sep 2019, 09:55

Hi Aiki1000,

My example demonstrated how to use an enum in the if statement. If you want to add more conditions in the statement just add them with a && operator.

Regarding

Also, is there a way to enumerate (each of the enums) within the IF argyument?

I am not sure what do you mean. If you want to check all the cases of an enum you can consider a switch statement 

Best Regards,

Panagiotis


@PanagiotisCharalampous

PanagiotisCharalampous
09 Sep 2019, 09:50

Hi Tomo,

This needs some development and I cannot engage into custom development. If you need assistance in developing your cBot, I would suggest you contact a Consultant or post a Job.

Best Regards,

Panagiotis


@PanagiotisCharalampous

PanagiotisCharalampous
09 Sep 2019, 09:47

Hi Chris,

You said "then reference that same position via the historic table in cTrader" hence my reply. Trading history is not available via FIX as explained in Limitations of FIX API

Best Regards,

Panagiotis


@PanagiotisCharalampous

PanagiotisCharalampous
09 Sep 2019, 09:44

Hi tmfd,

It should be weeks.

Best Regards,

Panagiotis


@PanagiotisCharalampous

PanagiotisCharalampous
05 Sep 2019, 09:31

Hi Aiki1000,

See below how to do this

            if (BarColor == FormationType.DownClose)
            {
                DotAbove[index] = High + (DotSpacing * Symbol.PipSize);
            }

Best Regards,

Panagiotis


@PanagiotisCharalampous

PanagiotisCharalampous
05 Sep 2019, 09:05

Hi calgodemo,

Please post the indicator code and exact steps to reproduce this behavior.

Best Regards,

Panagiotis


@PanagiotisCharalampous

PanagiotisCharalampous
04 Sep 2019, 16:12

Hi benpepperwhittaker,

It is not possible with cTrader's chartshot tool but you can still use Windows snipping tool as a workaround.

Best Regards,

Panagiotis


@PanagiotisCharalampous

PanagiotisCharalampous
04 Sep 2019, 10:11 ( Updated at: 04 Sep 2019, 10:12 )

Hi appengine1995,

The message seems correct. I managed to connect using the sample application. See the messages I send and receive

Sent

8=FIX.4.49=11335=A49=fibo.307189756=CSERVER57=QUOTE50=QUOTE34=152=20190904-06:57:4898=0108=30553=3071897554=xxx10=076

Received

8=FIX.4.49=9235=A34=149=CSERVER50=QUOTE52=20190904-06:57:49.26256=fibo.307189757=QUOTE98=0108=3010=215

Make sure that your checksum is calculated correctly.

Note that I have hidden the password in the messages

Best Regards,

Panagiotis


@PanagiotisCharalampous

PanagiotisCharalampous
04 Sep 2019, 09:42 ( Updated at: 04 Sep 2019, 10:12 )

Hi appengine1995,

this host IP changing, and its weird. why it keeping changing ?

This is written explicitly inside the form. You should not use the IP address, you should use the host name. Beside that, I cannot give any further advice an I do not know what is the application doing. If you can please share the FIX Messages exchanged between the application and the server.

Best Regards,

Panagiotis


@PanagiotisCharalampous

PanagiotisCharalampous
04 Sep 2019, 09:10 ( Updated at: 04 Sep 2019, 10:12 )

Hi appengine1995,

Thanks for posting in our forum. The host seems wrong but maybe you should first contact the developer of the other application. If you need an example how to connect and send/receive messages using FIX API, you can find a sample application here.

Best Regards,

Panagiotis


@PanagiotisCharalampous

PanagiotisCharalampous
04 Sep 2019, 09:07

Hi per.s.andersson,

Thanks for the screenshots. Can you please try clearing your browser cache and let us know if this resolves the issue? Also try in Incognito/Private mode as well.

Best Regards,

Panagiotis


@PanagiotisCharalampous

PanagiotisCharalampous
04 Sep 2019, 09:05

Hi Delta_Gamma,

For execution issues please contact your broker directly.

Best Regards,

Panagiotis


@PanagiotisCharalampous

PanagiotisCharalampous
04 Sep 2019, 09:02

Hi barzaq,

To delete a demo account please contact ICMarkets directly.

Best Regards,

Panagiotis


@PanagiotisCharalampous

PanagiotisCharalampous
04 Sep 2019, 09:01

Hi Kevin,

Is it correct  that the CBOT algorithm  runs locally on the host computer and CBOTs for sale are delivered as an executable like an EA in MT4

Ill investigate this more but I thought I may ask you, many thanks.

Yes this is correct.

Best Regards,

Panagiotis 


@PanagiotisCharalampous

PanagiotisCharalampous
03 Sep 2019, 16:17

Hi Kevin,

The list is up to date. You can see below each broker the indication if cTrader Copy is available or not. FxPro does not offer cTrader Copy and as you can see there is no such indication either. 

Regarding Q3 we cannot answer this question, we am not aware of each broker's size of business.

For Q4, we have millions of registered cTrader IDs

Best Regards,

Panagiotis


@PanagiotisCharalampous