Topics
Replies

firemyst
30 Aug 2021, 11:18

RE:

krystek128@wp.pl said:

hello everyone is any chance to get robot turn on one every first friday on the month ? 

No, because there is no programmatic way to start/stop cbots. cbots can only be started manually.


@firemyst

firemyst
29 Aug 2021, 12:25

RE:

Nickachino said:

Hi,

I m trying to use 2 EMAs from a custom multi timeframe indicators. I get an error when I call the indicator in my cBot.

This is the indicator code:

using System;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;

namespace cAlgo.Indicators
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC)]
    public class MyMTFEMA : Indicator
    {
        [Parameter(DefaultValue = 8)]
        public int EMAPeriods1 { get; set; }

        [Parameter(DefaultValue = 21)]
        public int EMAPeriods2 { get; set; }

        [Parameter("EMA Timeframe1", DefaultValue = "Hour")]
        public TimeFrame EMATimeframe1 { get; set; }

        [Parameter("EMA Timeframe2", DefaultValue = "Hour")]
        public TimeFrame EMATimeframe2 { get; set; }

        [Output("EMA1", Color = Colors.Blue)]
        public IndicatorDataSeries EMA1 { get; set; }

        [Output("EMA2", Color = Colors.Red)]
        public IndicatorDataSeries EMA2 { get; set; }

        private MarketSeries series1;
        private MarketSeries series2;

        private ExponentialMovingAverage Ema1;
        private ExponentialMovingAverage Ema2;

        protected override void Initialize()
        {
            series1 = MarketData.GetSeries(EMATimeframe1);
            series2 = MarketData.GetSeries(EMATimeframe2);

            Ema1 = Indicators.ExponentialMovingAverage(series1.Close, EMAPeriods1);
            Ema2 = Indicators.ExponentialMovingAverage(series2.Close, EMAPeriods2);

        }

        public override void Calculate(int index)
        {

            var index1 = GetIndexByDate(series1, MarketSeries.OpenTime[index]);
            if (index1 != -1)
            {
                EMA1[index] = Ema1.Result[index1];
            }

            var index2 = GetIndexByDate(series2, MarketSeries.OpenTime[index]);
            if (index2 != -1)
            {
                EMA2[index] = Ema2.Result[index2];
            }

        }


        private int GetIndexByDate(MarketSeries series, DateTime time)
        {
            for (int i = series.Close.Count - 1; i > 0; i--)
            {
                if (time == series.OpenTime[i])
                    return i;
            }
            return -1;
        }
    }
}

The I call it like this:

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 SIMPLEandPROFITABLEForexScalping : Robot
    {
        [Parameter("Risk %", DefaultValue = 0.02)]
        public double RiskPct { get; set; }

        [Parameter("EMA1 period", DefaultValue = 8)]
        public int EMA1Period { get; set; }

        [Parameter("EMA2 period", DefaultValue = 13)]
        public int EMA2Period { get; set; }

        [Parameter("EMA3 period", DefaultValue = 21)]
        public int EMA3Period { get; set; }

        private MovingAverage EMA1;
        private MovingAverage EMA2;
        private MovingAverage EMA3;
        private MyMTFEMA MTFEMA;

        protected override void OnStart()
        {
            // Put your initialization logic here
            EMA1 = Indicators.MovingAverage(Bars.ClosePrices, EMA1Period, MovingAverageType.Exponential);
            EMA2 = Indicators.MovingAverage(Bars.ClosePrices, EMA2Period, MovingAverageType.Exponential);
            EMA3 = Indicators.MovingAverage(Bars.ClosePrices, EMA3Period, MovingAverageType.Exponential);
            MTFEMA = Indicators.GetIndicator<MyMTFEMA>(8, 21, "Hour", "Hour");
            
        }

However I get an error when trying to run the cBot with this message:

31/12/2019 02:00:00.000 | Backtesting started
31/12/2019 02:00:00.000 | Crashed in OnStart with AlgoActivationException: Can not set "Hour" as a value for "EMATimeframe1" parameter
31/12/2019 02:00:00.000 | Backtesting was stopped

I have tried various ways to change the way I call the parameters using the 8, 21 and two "Hour" options but still get an error.

 

Any assistance would be appreciated.
 

 

Of course it's crashing there. You're passing in "Hour" as a string. The parameter is specifically for a TimeFrame object.

So you have to pass the timeframe similar to:

 

MTFEMA = Indicators.GetIndicator<MyMTFEMA>(8, 21, TimeFrame.Hour, TimeFrame.Hour);

 


@firemyst

firemyst
29 Aug 2021, 12:21

RE:

herculesone said:

Hello there! 

I would like some help to make an indicator, which is fairly simple but does not show as I want it.

I would like to show the closing prices of different timeframes on the same chart. However, I am unable to make the chart match the output I want to show.

Here is the code:

 

using System;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
using cAlgo.Indicators;

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class Closes_4hr_D_W_M_Q_Y : Indicator
    {

        [Output("4 Hour", LineColor = "Green", PlotType = PlotType.Points, Thickness = 2)]
        public IndicatorDataSeries Hour4 { get; set; }

        [Output("Daily", LineColor = "Black", PlotType = PlotType.Line, LineStyle = LineStyle.Solid, Thickness = 2)]
        public IndicatorDataSeries Daily { get; set; }

        [Output("Weekly", LineColor = "Red", PlotType = PlotType.Line, LineStyle = LineStyle.Solid, Thickness = 2)]
        public IndicatorDataSeries Weekly { get; set; }

        [Output("Monthly", LineColor = "Navy", PlotType = PlotType.Line, LineStyle = LineStyle.Solid, Thickness = 2)]
        public IndicatorDataSeries Monthly { get; set; }

        public Bars _daily, _4h, _weekly, _month;

        protected override void Initialize()
        {
            _4h = MarketData.GetBars(TimeFrame.Hour4);
            _daily = MarketData.GetBars(TimeFrame.Daily);
            _weekly = MarketData.GetBars(TimeFrame.Weekly);
            _month = MarketData.GetBars(TimeFrame.Monthly);
        }

        public override void Calculate(int index)
        {            
            Hour4[index] = _4h.ClosePrices[index];
            Daily[index] = _daily.ClosePrices[index];
            Weekly[index] = _weekly.ClosePrices[index];
            Monthly[index] = _month.ClosePrices[index];
        }
    }
}

 

I would expect that on a 1 hour chart, the Daily output would show as a straight line until the next day, when there would be another straight line etc. Instead, the indicators paint further back as if they are attached to another chart.

It is like the "index" applies to the chart I am calling and not the "index" of the applicable chart, which does make sense in a way but I want to work around it and cannot figure out how.

In essence when I call "index" of a 1 hour chart, the price on the daily chart of the same index should be the same until all the hours are complete. 

Any help is appreciated, thank you!

 

The index of the current chart won't be the same as the index on the other timeframe charts.That's why you're having the issue. For all the timeframes, you're getting the current index on the chart you're viewing. Since there's significantly more bars on the H4 chart than there are in the D1 chart for the day, you're going to have multiple incorrect readings.

For instance, when viewing the H4 chart, you need to get the corresponding index on the D, W, and M charts.

//Example code to get the correct Daily index on the H4 chart in the Calculate method. 
//This code assumes you'll always be looking at the H4 chart.

int altIndexD1 = _daily.OpenTimes.GetIndexByTime(Bars.OpenTimes[index]);

 


@firemyst

firemyst
29 Aug 2021, 12:13

Use Positions.Find()

//Example code
Position p = Positions.Find(positionLabel);
//or
Position p = Positions.Find(positionLabel, Symbol.Name);
//or
Position p = Positions.Find(positionLabel, Symbol.Name, TradeType);

 


@firemyst

firemyst
24 May 2021, 16:58

RE:

PanagiotisCharalampous said:

Hi firemyst,

Check Chart.Drag and Chart.ObjectsUpdated events.

Best Regards,

Panagiotis 

Join us on Telegram

Thanks for that.

Another question. I have the following sample code -- see my question in the commented code:

 

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

namespace cAlgo.Indicators
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class Test : Indicator
    {
        private ChartHorizontalLine _chl;
        private double _value;

        protected override void Initialize()
        {
            _value = MarketData.GetBars(Chart.TimeFrame, Symbol.Name).ClosePrices.LastValue;
            _chl = Chart.DrawHorizontalLine("test line", _value, Color.Goldenrod, 2, LineStyle.Solid);
            _chl.IsInteractive = true;

            Chart.ObjectsUpdated += LineUpdated;
        }

        public override void Calculate(int index)
        {
        }

        //When I drag the horizontal line created on the chart, why does this method get called numerous times?
        //Every time I drag the line, if I set a breakpoint on the opening curly brace, this method gets hit for each
        //object on the chart.
        //Is there a way to to reduce this so it only gets called for horizontal line objects?
        private void LineUpdated(ChartObjectsUpdatedEventArgs args)
        {   
            ChartHorizontalLine obj = (ChartHorizontalLine)args.Chart.FindObject("test line");
            if (obj != null && obj.Y != _value)
            {
                _value = obj.Y;
                Chart.DrawStaticText("value", _value.ToString(), VerticalAlignment.Top, HorizontalAlignment.Right, Color.Goldenrod);
            }
        }

    }
}

 


@firemyst

firemyst
22 May 2021, 10:24

Currently, there's known issues with the built in cTrader SuperTrend indicator which might be causing you problems as well.

See this thread:

You might be trying to set a SL on an ST value which doesn't exist.

 


@firemyst

firemyst
22 May 2021, 10:19

For starters it would help to know what parameter values you're using as they make a big difference.


@firemyst

firemyst
22 May 2021, 10:15

Use either the Chart.DrawText method or Chart.DrawStaticText method depending on where/how you want to display the text on the chart.

 


@firemyst

firemyst
29 Apr 2021, 06:24

cTrader is unfortunately very limited in its alerting abilities, and I think the only alerts possible are those based on "price". Although I'm sure someone from Spotware can correct me if I'm wrong.

If you need this, I see a few options:

1) sign up with another trading platform like ThinkTrader, which has awesome alerting functionality built in, where you can customize any kind of alert from one indicator crossing a price/indicator, price notifications, or a lot of other options.

2) program a 3 ema indicator yourself to alert you of when prices ema values are crossing.

3) use or find someone else's prebuilt indicator that has such alerting functionality provided.


@firemyst

firemyst
29 Apr 2021, 06:15

RE: RE:

bienve.pf said:

PanagiotisCharalampous said:

Hi bienve.pf,

The reason it doesn't move is because the retrieved bars are consist of completed bars. So you get the completed bar of the specific date. The price will change as soon as the date changes. There is a similar discussion about this here.

Best Regards,

Panagiotis 

Join us on Telegram

I understand,
But if I test multi-timeframe indicator in backtesting I need receive data like in realtime to parse all tics at the moment. Now,  with all the finalized bars and finalized values the ClosePrices no moves and It is not a real stage.

Two questions:

1) have you chosen "tick data" from the backtesting menu option?

2) A lot of chart operations are not supported (as far as I understand) in backtesting mode. Try surrounding your indicator with

if (!IsBacktesting)

{

// ... indicator calls here

}

and see what happens.


@firemyst

firemyst
23 Apr 2021, 03:43

Glad that helped!

 

Something else to try is using IsLastBar such as follows:

 

if (!notified && IsLastBar())
            {
                notified = true;
                PlaySound();
            }

so it only plays on the last bar. If you're watching the charts live, this will be the most current bar. Thus you don't have to worry about the sound being played on any previous bars.


@firemyst

firemyst
22 Apr 2021, 10:16 ( Updated at: 24 May 2022, 03:29 )

RE:

amusleh said:

Hi,

You can call Bars.OpenTimes.GetindexByTime two times with two indices, for example you call it first with index 5 and then 6, and it returns 10 for the first call and 20 for the second call, then you know from 10 to 20 belongs to first index.

Thank you!

That makes perfect sense!!

I appreciate your help!!


@firemyst

firemyst
22 Apr 2021, 09:42 ( Updated at: 22 Apr 2021, 09:44 )

RE:

amusleh said:

Hi,

Indices are not fixed, they can change, instead use bar open times.

If you want to get index of a bar on a different time frame you can use GetIndexByTime method of Bars.OpenTimes, check this sample indicator code:

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

namespace cAlgo
{
    [Cloud("Top", "Bottom", Opacity = 0.2)]
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class BollingerBandsMTFCloudSample : Indicator
    {
        private BollingerBands _bollingerBands;

        private Bars _baseBars;

        [Parameter("Base TimeFrame", DefaultValue = "Daily")]
        public TimeFrame BaseTimeFrame { get; set; }

        [Parameter("Source", DefaultValue = DataSeriesType.Close)]
        public DataSeriesType DataSeriesType { get; set; }

        [Parameter("Periods", DefaultValue = 14, MinValue = 0)]
        public int Periods { get; set; }

        [Parameter("Standard Deviation", DefaultValue = 2, MinValue = 0)]
        public double StandardDeviation { get; set; }

        [Parameter("MA Type", DefaultValue = MovingAverageType.Simple)]
        public MovingAverageType MaType { get; set; }

        [Output("Main", LineColor = "Yellow", PlotType = PlotType.Line, Thickness = 1)]
        public IndicatorDataSeries Main { get; set; }

        [Output("Top", LineColor = "Red", PlotType = PlotType.Line, Thickness = 1)]
        public IndicatorDataSeries Top { get; set; }

        [Output("Bottom", LineColor = "Red", PlotType = PlotType.Line, Thickness = 1)]
        public IndicatorDataSeries Bottom { get; set; }

        protected override void Initialize()
        {
            _baseBars = MarketData.GetBars(BaseTimeFrame);

            var baseSeries = GetBaseSeries();

            _bollingerBands = Indicators.BollingerBands(baseSeries, Periods, StandardDeviation, MaType);
        }

        public override void Calculate(int index)
        {
            var baseIndex = _baseBars.OpenTimes.GetIndexByTime(Bars.OpenTimes[index]);

            Main[index] = _bollingerBands.Main[baseIndex];
            Top[index] = _bollingerBands.Top[baseIndex];
            Bottom[index] = _bollingerBands.Bottom[baseIndex];
        }

        private DataSeries GetBaseSeries()
        {
            switch (DataSeriesType)
            {
                case DataSeriesType.Open:
                    return _baseBars.OpenPrices;

                case DataSeriesType.High:
                    return _baseBars.HighPrices;

                case DataSeriesType.Low:
                    return _baseBars.LowPrices;

                case DataSeriesType.Close:
                    return _baseBars.ClosePrices;
                default:

                    throw new ArgumentOutOfRangeException("DataSeriesType");
            }
        }
    }

    public enum DataSeriesType
    {
        Open,
        High,
        Low,
        Close
    }
}

 

 

Thank you, but this doesn't help and doesn't work for what I need.

 

What your code is doing is getting the indexes of the bars in the faster time frame and mapping that to a single index to the bars in the slower time frame.

With your method, it's going from "many" to "one".

I need the opposite. I have 1 index in a higher time frame and need to map it to all the related indexes in the faster time frame.

I have "one" and need to map it to "many".

If you try doing the opposite:

Bars.OpenTimes.GetIndexByTime(_baseBars.OpenTimes[index]);

simply won't work because it will not return all the indexes related. That is, if _baseBars is M15, and the chart is M1, Bars.OpenTimes.GetindexByTime will only return 1 index, not the corresponding 15 indexes I need.

 


@firemyst

firemyst
22 Apr 2021, 09:21

RE:

sascha.dawe said:

Hi,

 

I am having trouble playing sound notifications in an indicator in the latest version of Ctrader 4.0.

Yes, I have sound enabled and notifications on Ctrader and Filesystem access is enabled. I have

also converted this code to a cBot and the sound works fine. What could be causing this issue?

See demonstration code below.

using System;
using System.IO;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
using cAlgo.Indicators;

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.FileSystem)]
    public class TestSound : Indicator
    {
        [Parameter("Enable Sound Alerts", Group = "Sound", DefaultValue = false)]
        public bool soundAlerts { get; set; }
        [Parameter("Sound Filename", Group = "Sound", DefaultValue = "foghorn.mp3")]
        public string filename { get; set; }

        private string path;
        private bool notified = false;

        protected override void Initialize()
        {
            try
            {
                var desktopFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
                path = Path.Combine(desktopFolder, filename);
                Print(path);
            } catch (Exception error)
            {
                Print("Error: " + error);
            }
            PlaySound();
        }

        public override void Calculate(int index)
        {
            if (!notified)
            {
                notified = true;
                PlaySound();
            }
        }

        private void PlaySound()
        {
            if (soundAlerts)
            {
                try
                {
                    Notifications.PlaySound(path);
                } catch (Exception error)
                {
                    Print("Error: " + error);
                }
            }
        }
    }
}

 

 

Have you tried stepping through your code in Visual Studio debug mode to see what happens?

Also, because ticks could be coming in rather quickly, the system might be trying to play, but then gets stopped immediately when the next tick comes in because the "notified" variable is never set to true. I've had that happen before when trying to play sounds too quickly in succession.

Finally, what's the Print/logging output?


@firemyst

firemyst
22 Apr 2021, 09:12

Rough pseudo logic:

 

DateTime startTime = new DateTime(2021,4,22,6,0,0);

int startTimeIndex = Bars.OpenTimes.GetIndexByTime(startTime);

DateTime endTime = new DateTime(2021,4,22,10,0,0);

int endTimeIndex = Bars.OpenTimes.GetIndexByTime(endTime);

double highestPrice = 0;

for (int x= startTimeIndex; x <= endTimeIndex; x++)

{

    if (Bars.HighPrices[x] > highestPrice)

       highestPrice = Bars.HighPrices[x];

}


@firemyst

firemyst
13 Apr 2021, 15:28

RE:

amusleh said:

Hi,

Right now there is no way to change a chart time frame while a cBot instance is running on that chart.

We have plans to allow changing the time frame but we can't give you any ETA for that, I recommend you to open a thread for this feature request on forum suggestions section.

For clarification, yomm0401 didn't specifically ask if the "chart" time frame itself could be changed, only if the timeframe could be changed.

The answer to the latter question is yes in cBot code if that's what the intended question was.

The cbot code can always call:

MarketData.GetBars(TimeFrame.xxx, Symbol.Name);

and get data from a diffferent symbol and/or timeframe than what's on the chart.


@firemyst

firemyst
13 Apr 2021, 05:40

RE:

PanagiotisCharalampous said:

Hi caglar_G,

There is no option for the shift in the API at the moment, but it is not hard to implement it yourself.

Best Regards,

Panagiotis 

Join us on Telegram

Just wanted to follow up on this as I was looking for this parameter today as well, and it's not there (yet?) with the latest cTrader release.

Is it on a road map to implement natively? Seems like an easy job that shouldn't take a @Spotware programmer more than half a day since it's basically 1 important line of code similar to:

Result[index + Shift] = _movingAverage.Result[index];

THank you. :-)

 


@firemyst

firemyst
05 Apr 2021, 11:43

RE:

PanagiotisCharalampous said:

Hi firemyst,

It is not possible at the moment. To avoid this, you could use a trend line instead.

Best Regards,

Panagiotis 

Join us on Telegram

Thank you @Panagiotis. I'll do that. Hopefully that API option will be available in a future release.


@firemyst

firemyst
05 Apr 2021, 10:38

RE:

travkinsm1 said:

Hello! When testing the indicator, I noticed that one of the variables (_isLong) is displayed differently in the indicator and in the robot. If you do not pay attention to the different processing of ticks by the robot and the indicator, you can verify this by analyzing 2 log files. Tell me, please, what could be the matter? (For testing, you need to change the paths to the files)

using System;
using System.Linq;
using System.Windows;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;


namespace cAlgo
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
    public class MycBot : Robot
    {
        [Parameter("MA Method", DefaultValue = MovingAverageType.Simple)]
        public MovingAverageType MaType { get; set; }


        [Parameter("True:High_Low False:Close", DefaultValue = false)]
        public bool UseHighAndLow { get; set; }

        [Parameter("Timeframe1", DefaultValue = "Ticks10")]
        public TimeFrame TF { get; set; }

        [Parameter("Загрузить Баров", DefaultValue = 30000)]
        public int BarCount_set { get; set; }

        [Parameter("Загрузка ист. в индикаторе", DefaultValue = false)]
        public bool LoadIndHist { get; set; }

        [Parameter("Запись в файл", DefaultValue = true)]
        public bool FileWrite { get; set; }
        [Parameter("Запись торговли в файл", DefaultValue = true)]
        public bool FileWrite2 { get; set; }

        private Bars Bars2;
        public StreamWriter file;
        public int LoadHistory_for_ind = 3000;


        protected override void OnStart()
        {
            while (Bars.Count < BarCount_set)
            {
                var loadedCount = Bars.LoadMoreHistory();
                Print("Loaded {0} bars", loadedCount);
                Print("Total bars {0}", Bars.Count);
                if (loadedCount == 0)
                    break;
            }
            Print("Finished, total bars {0}", Bars.Count);
            Bars2 = MarketData.GetBars(TF, Symbol.Name);
            while (Bars2.Count < (BarCount_set / 10))
            {
                var loadedCount = Bars2.LoadMoreHistory();
                if (loadedCount == 0)
                    break;
            }
            Print("Finished, total bars {0}", Bars2.Count);
            file = new StreamWriter("C:\\Users\\travk_000\\Documents\\bot1.3_is_long2.txt", false);
            file.WriteLine("Begin");
            file.Flush();
            file.Close();
        }
        protected override void OnTick()
        {
            bool dirInd = Indicators.GetIndicator<ATR_Stops_time_MarketData_History>(TF, MaType, 10, 4, UseHighAndLow, LoadHistory_for_ind, LoadIndHist)._isLong;
            file = new StreamWriter("C:\\Users\\travk_000\\Documents\\bot1.3_is_long2.txt", true);
            file.WriteLine("Bot " + Bars.OpenPrices.LastValue + " " + Bars.OpenTimes.LastValue + " " + dirInd);
            file.Flush();
            file.Close();
        }
    }
}
using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
namespace cAlgo.Indicators
{
    [Indicator("ATR Trailing Stop", AutoRescale = false, IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.FileSystem)]
    public class ATR_Stops_time_MarketData_History : Indicator
    {

        [Parameter("Timeframe", DefaultValue = 0.0)]
        public TimeFrame TF { get; set; }

        [Parameter("MA Method", DefaultValue = MovingAverageType.Simple)]
        public MovingAverageType MaType { get; set; }

        [Parameter("Period", DefaultValue = 10, MinValue = 2, MaxValue = 50000)]
        public int Period { get; set; }

        [Parameter("Weight", DefaultValue = 4.0, MinValue = 0.1, MaxValue = 400.0)]
        public double Weight { get; set; }

        [Parameter("True:High_Low False:Close", DefaultValue = false)]
        public bool UseHighAndLow { get; set; }

        [Parameter(DefaultValue = 16000)]
        public int LoadHistory_for_ind { get; set; }

        [Parameter("Загрузка ист. в индикаторе", DefaultValue = false)]
        public bool LoadIndHist { get; set; }


        [Output("Main")]
        public IndicatorDataSeries Result { get; set; }

        private ATRMTF_time_History _atr;
        public bool _isLong;

        private MarketSeries _marketSeries;

        private Bars Bars2;
        public StreamWriter file3;

        protected override void Initialize()
        {
            Print("Start");

            Bars2 = MarketData.GetBars(TF, Symbol.Name);
            Print("{0} bar on the chart. Loading 2.000.000 bars", Bars2.Count);
            if (LoadIndHist == true)
            {
                while (Bars2.Count < LoadHistory_for_ind)
                {
                    var loadedCount = Bars2.LoadMoreHistory();
                    if (loadedCount == 0)
                        break;
                }
                Print("Finished, total bars {0}", Bars2.Count);
            }
            Print("1");
            this._marketSeries = MarketData.GetSeries(MarketData.GetSymbol(Symbol.Name), TF);

        }


        public override void Calculate(int index)
        {
            var currentAtr = Weight * _atr.Result[index];

            if (double.IsNaN(currentAtr))
                return;

if (double.IsNaN(Result[index - 1]) && !double.IsNaN(_atr.Result[index - 1]))
            {
                var previousATR = Weight * _atr.Result[index - 1];

                _isLong = MarketSeries.Close.IsRising();

                var previous = UseHighAndLow ? (_isLong ? this._marketSeries.High[_marketSeries.OpenTime.GetIndexByTime(MarketSeries.OpenTime[index - 1])] : this._marketSeries.Low[_marketSeries.OpenTime.GetIndexByTime(MarketSeries.OpenTime[index - 1])]) : this._marketSeries.Close[_marketSeries.OpenTime.GetIndexByTime(MarketSeries.OpenTime[index - 1])];

                Result[index] = _isLong ? previous - previousATR : previous + previousATR;
            }
            else
            {
                var current = this._marketSeries.Close[_marketSeries.OpenTime.GetIndexByTime(MarketSeries.OpenTime[index])];

                if (_isLong)
                {
                    if (current >= Result[index - 1])
                    {
                        if (UseHighAndLow)
                            current = this._marketSeries.High[_marketSeries.OpenTime.GetIndexByTime(MarketSeries.OpenTime[index])];
                        Result[index] = Math.Max(Result[index - 1], current - currentAtr);
                    }
                    else
                    {
                        _isLong = false;
                        if (UseHighAndLow)
                            current = this._marketSeries.Low[_marketSeries.OpenTime.GetIndexByTime(MarketSeries.OpenTime[index])];
                        Result[index] = current + currentAtr;
                    }
                }
                else
                {
                    if (current <= Result[index - 1])
                    {
                        if (UseHighAndLow)
                            current = this._marketSeries.Low[_marketSeries.OpenTime.GetIndexByTime(MarketSeries.OpenTime[index])];
                        Result[index] = Math.Min(Result[index - 1], current + currentAtr);
                    }
                    else
                    {
                        _isLong = true;
                        if (UseHighAndLow)
                            current = this._marketSeries.High[_marketSeries.OpenTime.GetIndexByTime(MarketSeries.OpenTime[index])];
                        Result[index] = current - currentAtr;
                    }
                }
            }
            file3 = new StreamWriter("C:\\Users\\travk_000\\Documents\\bot1.3_is_long.txt", true);
            file3.WriteLine("Indicator " + Bars.OpenPrices.LastValue + " " + Bars.OpenTimes.LastValue + " " + Period + " " + Weight + " " + _isLong);
            file3.Flush();
            file3.Close();

        }
    }
}

 

When calling an indicator from a bot, you ALWAYS have to get the latest value from the indicator, which you aren't doing. You're initializing the indicator on every tick in the bot, but you're not getting its latest value.

You need to do something like the following in your bot:

//because cTrader does "lazy loading" of indicator values, so force it
double a = YourIndicator.Result.Last(0); 

//now that the indicator's values have been refresh above, get the latest value.
_isLong = YourIndicator.Result.Last(0);

 


@firemyst

firemyst
04 Apr 2021, 13:38

RE:

PanagiotisCharalampous said:

Hi firemyst,

It seems to be a bug. We will fix it in an upcoming update.

Best Regards,

Panagiotis 

Join us on Telegram

Awesome.

Thank you @Panagiotis! If you could update here when fixed that would be great.

ALSO! Would it be possible to include within the API a "data source" parameter within the constructor? It seems incredibly limiting that we cannot pass in another datasource (eg, different time frame for example) like we can with PSARs and other indicators.

Thank you. And Happy Easter if you celebrate it. :-)


@firemyst