Topics
12 Mar 2024, 11:00
 0
 343
 0
10 Mar 2024, 20:53
 439
 1
Replies

jani
20 Feb 2020, 13:09

OpenTime.GetIndexByTime replaced by what?

It's quite frustrating to run into warnings and error messages due to thwe 3,7 changes and there is no instructions on how to replace the old code!

 

for example, I have:

 

public Bars hour;

 hour = MarketData.GetBars(TimeFrame.Hour);

public override void Calculate(int index)
        {
              int i_hour = hour.OpenTime.GetIndexByTime(MarketSeries.OpenTime[index]);
          //  int i_hour = hour.OpenTime.GetIndexByTime(Bars.OpenTimes[index]);

....

 

I cannot find anywhere how to replace

hour.OpenTime.GetIndexByTime(MarketSeries.OpenTime[index]);

I tried just adding

Bars.OpenTimes[index]

instead of

MarketSeries.OpenTime[index]

but still getting an error message, and the problem is the 

OpenTime

I just cannot find anywhere what to replace it with?

 

I also have:

_hour[index] = hour.Open[i_hour];

What to replace "Open" with?

API reference is a nightmare to try to find anything (expecially since I do not even know what I'm looking for as old API definitions are removed and new ones I'm not familiar with) and if I do find syntax I usually do not understand it because there are no or only a few short examples... 

 

 

Spotware , when you make large changes like 3.7. updates to you API code, please help us less professional programmers to translate the code, that is if you want to keep people like me here...  Would it be totally impossible to have the error message tell what to replace old code with?


@jani

jani
13 Feb 2020, 00:28

Sample code regarding 3.7. update Ticks?

I think it is great that Spotware keeps updating and improving cTrader, and the new additions on 3.7. look very nice!

However, for someone like me with very limited understanding of programming, it is sometimes hard to keep up...

I have also difficulty understanding the API reference syntax, and I really only understand code by seeing examples of it in a code snippet, indicator or cBot.

Would it be possible to get some examples of how to use these new Ticks API data?

 

Ticks

Automate API adds Ticks to work with tick data.
Ticks is a collection of Tick objects with following properties

Tick.Bid
Tick.Ask
Tick.Time

Note, in the previous versions tick data was accessible only if cBot or indicator was running on Tick1 chart and only for bid prices using old MarketSeries. With the new API you can access tick data from any timeframe and use bid and ask prices

 

 


@jani

jani
10 Feb 2020, 19:17

RE:

thanks for your reply.

 

 I was only referring to the same instance having concurrent buy & sell open positions. I think I would need to better understand how 

Positions.Find(...)

API function is treating each individual Buy and Sell position.

 

I was assuming that it would find any position and if the condition

  if (position.Pips >= TriggerWhenGaining)

would be true, if either Sell OR Buy position were satisfying the "TriggerWhenGaining" condition. And therefore for example when Buy side qualify "TriggerWhenGaining" condition it would let the logic also to update Sell side stop without the step condition being met?  ..or perhaps I have some syntax error in my thought process...LOL


@jani

jani
08 Feb 2020, 23:31

RE:

Hi Panagiotis ,

 

thanks for your message, sorry a bit late reply from me...

 

if I understood correctly

if (position.Pips >= TriggerWhenGaining)

Allow trailing to start if EITHER buy or sell position is in profit for more than TriggerWhenGaining ?,  

Say we use Step=5 and buy has moved to Step but Sell only halfway,  if (position.Pips >= TriggerWhenGaining)  would allow also the Sell stop to be moved/trailed even though it has not yet reached the step, am I correct?

Do you think this would work?

 

  private void SetMultiMaTrailingStop()
        {
            var sellPositions = Positions.FindAll(InstanceName, SymbolName, TradeType.Sell);

            foreach (Position position in sellPositions)
            {
                   double distance = position.EntryPrice - neutral1;
                if (distance < BuyTriggerWhenGaining)
                    continue;

                 BuyTriggerWhenGaining += Step * Symbol.PipSize;

                double newStopLossPrice = neutral1 + T3StopFromLineExit * Symbol.PipSize;

                if (position.StopLoss == null || newStopLossPrice < position.StopLoss)
                {
                    ModifyPosition(position, newStopLossPrice, position.TakeProfit);
                }

                BuyTriggerWhenGaining += Step * Symbol.PipSize;
            }

            //---------

            var buyPositions = Positions.FindAll(InstanceName, SymbolName, TradeType.Buy);

            foreach (Position position in buyPositions)
            {
                double distance = neutral1 - position.EntryPrice;
        
                if (distance < SellTriggerWhenGaining)
                    continue;
                  double newStopLossPrice = neutral1 - T3StopFromLineExit * Symbol.PipSize;

                if (position.StopLoss == null || newStopLossPrice > position.StopLoss)
                {
                    ModifyPosition(position, newStopLossPrice, position.TakeProfit);
                }
                SellTriggerWhenGaining += Step * Symbol.PipSize;
            }
           
        }

 

Step feature is a bit hard to verify by backtesting, but I think I was getting the correct results.....


@jani

jani
08 Feb 2020, 13:04

Calendar intergration with cBots

Economic Calendar is a great addition to cTrader!!

Is there any way to reference/call this calendar by cBot?  For example pause trading before and after important news events.


@jani

jani
20 Jan 2020, 13:16

NOTICE !!! Open indicator instances at Automate are using memory !!!

I thought that I had a memory leak issue with cTrader 3.6. as the platform was taking over 4Gb even when only one chart was open with no indicators attached (no cBots running)

Then I noticed I had many indicator instances left open at 'Automate' tab. each of these instances seems to take resources and that was causing the excessive memory-hogging!


@jani

jani
14 Dec 2019, 22:17

RE:

Thank you very much for the very helpfull example! For a beginner like myself, it is sometimes quite impossible to figure out the actual code from API reference.

Could any tell how can I draw histograms with opacity?  I have :

 

        [Output("Histogram Down", PlotType = PlotType.Histogram, LineColor = "Red")]
        public IndicatorDataSeries HistogramNegative { get; set; }

 

How can I use  in this public output parameter definition the below opacity setting?:

       Color color = Color.FromArgb(50, Color.Red);

 

 


@jani

jani
30 Nov 2019, 22:39

ChartObject.DrawLine definition missing

Spotware said:

Dear Trader,

Please be advised that you can Draw the  lines with using ChartObject.DrawLine function. You can then refer to the respective objects. /api/reference/internals/chartobjects/drawline 

Hello,

Can you please tell me where the API reference for ChartObject.DrawLine is?

 

The above url /api/reference/internals/chartobjects/drawline you posted above is not valid  and returns:

 

The server returned a "404 Not Found".

 I tried to search everywhere and could not find anything.


@jani

jani
25 Nov 2019, 23:21

RE:

Panagiotis Charalampous said:

Hi Anton,

Here is how

 Positions.Where(x => x.Label == "My Label").OrderByDescending(x => x.EntryTime).First();

Best Regards,

Panagiotis

Could you show an example how this is used in a cBot? For example if I want to print out the last opened position time?

I'm trying to limit trade openings OnTick with a timer or a bar counter. Would be nice to have an example code for this I know many other people are looking for the same thing...


@jani

jani
20 Nov 2019, 23:56

Trailing Stop Loss with Trailing Distance and Step

Hello,

thank you for the example. It is really valuable to get these examples here, especially for a beginner programmer like myself.

It would be great if you could show how to add a "STEP to the trailing stop. More often than not,  it is not necessary to update the trailing stop on every tick advanced to the trade's direction and it would save a lot of resources to add a "STEP" to the trail, so that the trailing stop is only updated when price has moved the "STEP" amount to profit.

 

Below is my version of a trailing stop function (stop is trailing a custom indicator value : maketemaExit(1) )

 

 

private void SetT3ExitTrailingStop()
        {
            var sellPositions = Positions.FindAll(InstanceName, Symbol, TradeType.Sell);

            foreach (Position position in sellPositions)
            {
               
                double distance = position.EntryPrice - maketemaExit(1);

                if (distance < MinT3DistanceExit * Symbol.PipSize)
                    continue;

                double newStopLossPrice = maketemaExit(1) + T3StopFromLineExit * Symbol.PipSize;

                if (position.StopLoss == null || newStopLossPrice < position.StopLoss)
                {
                    ModifyPosition(position, newStopLossPrice, position.TakeProfit);
                }
            }

            var buyPositions = Positions.FindAll(InstanceName, Symbol, TradeType.Buy);

            foreach (Position position in buyPositions)
            {
                double distance = maketemaExit(1) - position.EntryPrice;

                if (distance < MinT3DistanceExit * Symbol.PipSize)
                    continue;

                double newStopLossPrice = maketemaExit(1) - T3StopFromLineExit * Symbol.PipSize;
                if (position.StopLoss == null || newStopLossPrice > position.StopLoss)
                {
                    ModifyPosition(position, newStopLossPrice, position.TakeProfit);
                }
            }
        }

 


@jani

jani
13 Nov 2019, 17:17

I have a strategy testing template with over 40 parameters. I takes a long time to tick most of them of. Anyway I don't understand why they are all ticked by default? It makes no sense as usually, it is best to just optimize a few parameters at a time


@jani

jani
10 Nov 2019, 16:32

RE:

Panagiotis Charalampous said:

Hi Jan,

Shouldn't the bar counter be after the actual trade execution logic? 

The counter starts after a position is opened as per the requirement

How about resetting the counter after the trade is closed?

This is just an example on how to implement such logic. Further to that, each one needs to adjust it on his cBot logic.

Best Regards,

Panagiotis

Ok, Thank you,  I understand.

 


@jani

jani
09 Nov 2019, 20:29 ( Updated at: 21 Dec 2023, 09:21 )

RE:

Drummond360 said:

Hi All,

I using the code below to open and clsoe positions upon spread size. As you can see the MaxSpread parameter is set to 1 so it should open positions when the spread is < 1 and close them when the spread is > 1 but it isn't respecting these levels.

The screen shot shows the trade log with all the spread is regularly above 1 and I can confirm that it also prints the spread ot be regularly below 1...

Can anyone spot the fault in my code, it seems too simple to get wrong!

 

using System;
using System.Linq;
using System.Collections.Generic;
using cAlgo.API;
using cAlgo.API.Requests;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class Hedging2positionsonly : Robot
    {

        [Parameter("Max Spread", DefaultValue = 0.0, MinValue = -5.0)]
        public double MaxSpread { get; set; }

        string label = "Spread Test";

        protected override void OnStart()
        {

        }
        protected override void OnTick()
        {
            var longPosition = Positions.Find(label, Symbol, TradeType.Buy);
            var shortPosition = Positions.Find(label, Symbol, TradeType.Sell);
            //var spread = Symbol.Spread / Symbol.PipSize;
            var spread = Symbol.Ask - Symbol.Bid;
            //var spread = Math.Round(Symbol.Spread / Symbol.PipSize, 1);
            Print("Spread is " + spread + " Symbol.Spread Value = " + Symbol.Spread);
            {

                if (shortPosition == null && spread <= MaxSpread)
                {
                    ExecuteMarketOrder(TradeType.Sell, Symbol, 1000, label);

                    Print(" enterered short, var spread is " + spread + " MaxSpread = " + MaxSpread);


                }
                if (longPosition == null && spread <= MaxSpread)
                {
                    ExecuteMarketOrder(TradeType.Buy, Symbol, 1000, label);

                    Print(" entered long, var spread is " + spread + " MaxSpread = " + MaxSpread);
                }
            }


            var symbolSearch = Positions.FindAll(label, Symbol);

            if (spread >= MaxSpread)
            {
                foreach (Position position in symbolSearch)
                {
                    ClosePosition(position);
                    Print("Exit because Spread @ " + spread + " closing positions");
                }

            }
        }
    }
}

 

Many thanks in advance, Drummond...

I think  you just need to add:

 if (shortPosition == null && spread <= MaxSpread*Symbol.PipSize)

 


@jani

jani
07 Nov 2019, 19:31

RE:

Panagiotis Charalampous said:

Hi irmscher,

Yes you can specify market range in the ExecuteMarketOrder function.

Best Regards,

Panagiotis

Hello,

 

can you please give some examples of ::

 double basePrice

in   ExecuteMarketRangeOrder?


@jani

jani
07 Nov 2019, 16:32

RE:

Panagiotis Charalampous said:

Hi marwaha1@gmail.com,

See below

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 NewcBot : Robot
    {
        [Parameter(DefaultValue = 0.0)]
        public double Parameter { get; set; }
        private int _barCount;
        private bool _startCounting;
        protected override void OnStart()
        {
            Positions.Opened += OnPositionsOpened;
        }

        void OnPositionsOpened(PositionOpenedEventArgs obj)
        {
            _startCounting = true;
        }

        protected override void OnBar()
        {
            if (_startCounting)
                _barCount++;
        }

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

Let me know if this helps,

Best Regards,

Panagiotis

Shouldn't the bar counter be after the actual trade execution logic? How about resetting the counter after the trade is closed?


@jani

jani
07 Nov 2019, 15:40

RE:

Spotware said:

Dear hungtonydang,

If you wish to set the _lastExecutedOrder only whenever an order is executed, you should apply the following changes to your code.

First of all you need to an event handler for the Positions.Opened event as follows
 

        protected override void OnStart()
        {
            BB = Indicators.BollingerBands(Source, Periods, Deviations, MAType);
            Positions.Opened += OnPositionsOpened;
        }

Then in the event handler you can set the _lastExecutedOrder. See below

        void OnPositionsOpened(PositionOpenedEventArgs obj)
        {
            _lastExecutedOrder = DateTime.Now;
        }

See the full modified code below

 

using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Requests;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
using System.Threading;
using System.Threading.Tasks;

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.TasmaniaStandardTime, AccessRights = AccessRights.None)]
    public class HunterBB : Robot
    {
        [Parameter("Source")]
        public DataSeries Source { get; set; }

        [Parameter("Stop Loss (pips)", DefaultValue = 40, MinValue = 1)]
        public int StopLossInPips { get; set; }

        [Parameter("Take Profit (pips)", DefaultValue = 40, MinValue = 1)]
        public int TakeProfitInPips { get; set; }

        [Parameter("Quantity (Lots)", DefaultValue = 1, MinValue = 0.01, Step = 0.01)]
        public double Quantity { get; set; }

        [Parameter("Cooldown (hours)", DefaultValue = 2, MinValue = 1, Step = 1)]
        public double CD { get; set; }

        [Parameter("Bollinger Bands Deviations", DefaultValue = 2)]
        public double Deviations { get; set; }

        [Parameter("Bollinger Bands Periods", DefaultValue = 20)]
        public int Periods { get; set; }

        [Parameter("Bollinger Bands MA Type")]
        public MovingAverageType MAType { get; set; }

        [Parameter("Position Id", DefaultValue = "Pid")]
        public string PositionId { get; set; }

        public Position position;
        private DateTime _lastExecutedOrder;

        BollingerBands BB;


        protected override void OnStart()
        {
            BB = Indicators.BollingerBands(Source, Periods, Deviations, MAType);
            Positions.Opened += OnPositionsOpened;
        }

        void OnPositionsOpened(PositionOpenedEventArgs obj)
        {
            _lastExecutedOrder = DateTime.Now;
        }

        protected override void OnBar()
        {

            var midbb = BB.Main.Last(0);
            var topnow = BB.Top.Last(0);
            var bottomnow = BB.Bottom.Last(0);

            var volumeInUnits = Symbol.QuantityToVolume(Quantity);
            var expiry = Time.AddHours(1);


            if (_lastExecutedOrder.AddHours(CD) < DateTime.Now)
            {
                //higher than indicator target price
                PlaceLimitOrder(TradeType.Sell, Symbol, volumeInUnits, topnow + 5 * Symbol.PipSize, PositionId, StopLossInPips, null, expiry);
                //lower than indicator target price
                PlaceLimitOrder(TradeType.Buy, Symbol, volumeInUnits, bottomnow - 5 * Symbol.PipSize, PositionId, StopLossInPips, null, expiry);
            }

            foreach (var position in Positions)
            {
                if (Symbol.Code == position.SymbolCode)
                {
                    ModifyPositionAsync(position, position.StopLoss, midbb);
                    Print("New Position TP price is {0}", position.TakeProfit);
                }
            }
        }

        protected override void OnStop()
        {
            Stop();
        }
    }
}

Let us know if this is what you are looking for.

Best Regards,

cTrader Team

Problem with this code is that it is not working in backtesting as DateTime.Now give current computer time not the server time backtesting is reading.

if (_lastExecutedOrder.AddHours(CD) < DateTime.Now)

I would never run any cBot live before I have backtested it.... But thanks for your effort. I'll try to look if I can find a solution

 


@jani

jani
07 Nov 2019, 12:51

RE:

Panagiotis Charalampous said:

Hi Jan,

In the posts above I forgot to mention that you also need to install the extension for VS2017. You can also consider VS 2019 since you are upgrading.

Best Regards,

Panagiotis

Hello,

Thank for the reply.

Currently trying to uninstall VS 2015 but it seems to act like a virus and removing it is not easy... have to browse through GitHub for solutions...

Is there any way to instruct cAlgo to open VS 2017 instead of the broken 2015?


@jani

jani
07 Nov 2019, 12:35

RE:

Panagiotis Charalampous said:

Hi Piero,

Visual Studio extension supports both 2015 and 2017 so there is nothing special you need to do. Just install VS 2017 and make is the default program to open solution files. The next time you will click on Edit in Visual Studio VS 2017 should launch instead.

Best Regards,

Panagiotis

Hello,

 

i made VS 2017 my default program to open .algo files but cTrader is still opening with VS 20+15. Do I need to uninstall 2015?  2015 is very unstable on my computer and keeps crashing when building cAlgo


@jani

jani
07 Nov 2019, 01:40

RE:

admin said:

UPDATED

This code is a reference to handling multiple positions. This robot is intended to be used as an example and does not guarantee any particular outcome or profit of any kind.

 

using cAlgo.API;
using cAlgo.API.Indicators;

namespace cAlgo.Robots
{
    [Robot]
    public class SampleMultiplePositions : Robot
    {
        private MovingAverage _fastMa;
        private MovingAverage _slowMa;

        [Parameter(DefaultValue = "Sample cBot")]
        public string cBotLabel { get; set; }

        [Parameter]
        public DataSeries SourceSeries { get; set; }

        [Parameter("MA Type")]
        public MovingAverageType MAType { get; set; }

        [Parameter("Slow Periods", DefaultValue = 10)]
        public int SlowPeriods { get; set; }

        [Parameter("Fast Periods", DefaultValue = 5)]
        public int FastPeriods { get; set; }

        [Parameter(DefaultValue = 100000)]
        public int Volume { get; set; }

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

        [Parameter("Take Profit (pips)", DefaultValue = 100)]
        public int TakeProfit { get; set; }

        [Parameter("Trigger (pips)", DefaultValue = 10)]
        public int Trigger { get; set; }

        [Parameter("Trailing Stop (pips)", DefaultValue = 10)]
        public int TrailingStop { get; set; }


        [Parameter("MinBalance", DefaultValue = 5000)]
        public double MinBalance { get; set; }

        [Parameter("MinLoss", DefaultValue = -200.0)]
        public double MinLoss { get; set; }

        [Parameter(DefaultValue = 3)]
        public int MaxPositions { get; set; }


        protected override void OnStart()
        {
            _fastMa = Indicators.MovingAverage(SourceSeries, FastPeriods, MAType);
            _slowMa = Indicators.MovingAverage(SourceSeries, SlowPeriods, MAType);

            Positions.Opened += PositionsOnOpened;
            Positions.Closed += PositionsOnClosed;
        }

        protected override void OnBar()
        {
            var cBotPositions = Positions.FindAll(cBotLabel);

            if (cBotPositions.Length > MaxPositions) return;

            var currentSlowMa = _slowMa.Result.Last(0);
            var currentFastMa = _fastMa.Result.Last(0);

            var previousSlowMa = _slowMa.Result.Last(1);
            var previousFastMa = _fastMa.Result.Last(1);

            // Condition to Buy
            if (previousSlowMa > previousFastMa && currentSlowMa <= currentFastMa)
                ExecuteMarketOrder(TradeType.Buy, Symbol, Volume, cBotLabel, StopLoss, TakeProfit);
            else if (previousSlowMa < previousFastMa && currentSlowMa >= currentFastMa)
                ExecuteMarketOrder(TradeType.Sell, Symbol, Volume, cBotLabel, StopLoss, TakeProfit);

            // Some condition to close all positions
            if (Account.Balance < MinBalance)
                foreach (var position in cBotPositions)
                    ClosePosition(position);

            // Some condition to close one position
            foreach (var position in cBotPositions)
                if (position.GrossProfit < MinLoss)
                    ClosePosition(position);

            // Trailing Stop for all positions
            SetTrailingStop();
        }

        private void PositionsOnOpened(PositionOpenedEventArgs obj)
        {
            Position openedPosition = obj.Position;
            if (openedPosition.Label != cBotLabel) return;

            Print("position opened at {0}", openedPosition.EntryPrice);
        }

        private void PositionsOnClosed(PositionClosedEventArgs obj)
        {
            Position closedPosition = obj.Position;
            if (closedPosition.Label != cBotLabel) return;

            Print("position closed with {0} gross profit", closedPosition.GrossProfit);
        }


        /// <summary>
        /// When the profit in pips is above or equal to Trigger the stop loss will start trailing the spot price.
        /// TrailingStop defines the number of pips the Stop Loss trails the spot price by. 
        /// If Trigger is 0 trailing will begin immediately. 
        /// </summary>
        private void SetTrailingStop()
        {
            var sellPositions = Positions.FindAll(cBotLabel, Symbol, TradeType.Sell);

            foreach (Position position in sellPositions)
            {
                double distance = position.EntryPrice - Symbol.Ask;

                if (distance < Trigger*Symbol.PipSize) continue;

                double newStopLossPrice = Symbol.Ask + TrailingStop*Symbol.PipSize;

                if (position.StopLoss == null || newStopLossPrice < position.StopLoss)
                    ModifyPosition(position, newStopLossPrice, position.TakeProfit);
            }

            var buyPositions = Positions.FindAll(cBotLabel, Symbol, TradeType.Buy);

            foreach (Position position in buyPositions)
            {
                double distance = Symbol.Bid - position.EntryPrice;

                if (distance < Trigger*Symbol.PipSize) continue;

                double newStopLossPrice = Symbol.Bid - TrailingStop*Symbol.PipSize;
                if (position.StopLoss == null || newStopLossPrice > position.StopLoss)
                    ModifyPosition(position, newStopLossPrice, position.TakeProfit);
            }
        }
    }
}

 

Correction to this code, if you want only one opened position when MaxPositions is set to 1 you should put:

if (cBotPositions.Length >= MaxPositions) return;

NOT

if (cBotPositions.Length > MaxPositions) return;

Above will give you 2 open positions for MaxPosition value 1


@jani

jani
02 Nov 2019, 19:34

Add this to Calculate:

  public override void Calculate(int index)
        {
            if (IsLastBar)
            {
                 if (IsLastBar)
            {
                if (index != lastindex)
                    lastindex = index;
                else
                    return;
            } 

...And to Parameters:

 int lastindex = 0;

That should do it

If I only need values on closed bars. I use this to save CPU resources.


@jani