Topics

Forum Topics not found

Replies

amusleh
09 Apr 2021, 21:48

Hi,

The Bars LoadMoreHistory method loads more historical data and allows you to do it via code, it doesn't notify you when user loads more data.

Whenever the indicator initialize method is called it means either more data is loaded or platform re-connected after disconnection, that's the time you can check your saved data file on the disk and load the data from it to your outputs instead of re-calculating.


@amusleh

amusleh
09 Apr 2021, 21:24

If you opened the Windows form with a cBot then you can't change the chart with it as it runs via a cBot but your cBot can execute orders on other symbols, there is no need to change the chart, ask your developer to add this feature to your Windows form cBot.


@amusleh

amusleh
09 Apr 2021, 18:41

Hi,

When a cBot is running on a chart it locks the chart, so you can't change the chart time frame or symbol unless you stop your cBot.

You can change a chart symbol or time frame with an indicator but not with a cBot.

Why you need such a feature?


@amusleh

amusleh
09 Apr 2021, 17:15

Hi,

You have to call your indicator Calculate method from your cBot OnTick/Bar methods, as the indicator Calculate method is a lazy method its not called automatically unless you do it manually.


@amusleh

amusleh
09 Apr 2021, 14:07

Hi,

It calls the OnTick event whenever a new tick arrives and it has precedence over invoking events, that's how it works on real live market and the back tester simulates the same condition.

There is an issue while back testing in slower speed and it should not invoke PendingOrders.Filled event before calling OnTick, we will investigate it and if there was any bug it will be fixed in future releases.


@amusleh

amusleh
08 Apr 2021, 15:44

Hi,

This sample might help you:

using cAlgo.API;

namespace cAlgo
{
    /// <summary>
    /// This sample shows how to use Thickness for defining a chart control margin
    /// </summary>
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class ThicknessSample : Indicator
    {
        protected override void Initialize()
        {
            var stackPanel = new StackPanel
            {
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center,
                BackgroundColor = Color.Gold,
                Opacity = 0.6
            };

            var rectangle = new Rectangle
            {
                StrokeColor = Color.Blue,
                FillColor = Color.Red,
                StrokeThickness = 2,
                Margin = new Thickness(10, 5, 10, 5),
                Width = 300,
                Height = 100,
            };

            stackPanel.AddChild(rectangle);

            Chart.AddControl(stackPanel);
        }

        public override void Calculate(int index)
        {
        }
    }
}

MArgin property type is Thickness.


@amusleh

amusleh
08 Apr 2021, 11:14 ( Updated at: 08 Apr 2021, 11:50 )

Hi,

Whenever you change a parameter of an indicator, load more data, or get disconnected and re-connected cTrader re-initializes the indicator and your indicator have to re-calculate everything from start.

The way cTrader works is much better than other platforms, because it doesn't force developers to manage events and do all the work of updating the indicator outputs for new data or re-adjusting the indicator already calculated data, but yes it consumes more processing power.

To solve the CPU processing power consumption issue, you can write your indicator calculated outputs data on a file and then when indicator initializes check if the file exist, if there is a cache file for indicator data fill the outputs by loading the file data instead of re-calculating the data and escape the bars until you reach the bars that aren't in your file.


@amusleh

amusleh
07 Apr 2021, 18:03 ( Updated at: 21 Dec 2023, 09:22 )

Hi,

You can select the tick data here:


@amusleh

amusleh
07 Apr 2021, 17:21

The server time is based on back test data time not current time of server.

The code inside if block will only run if the server time is equal to 9:01, and for that to work you have to use the tick data for back test not bar data.


@amusleh

amusleh
07 Apr 2021, 13:17

Hi,

OnBar/Tick methods are called based on current chart symbol and time frame, if you want to receive on bar/tick events of other timeframes or symbols yopu have to first get that symbol/timeframe Bars object by calling the MarketData.GetBars method and passing the time frame and symbol name.

After you got the Bars then you can subscribe to its BarOpened and Tick events:

using cAlgo.API;
using System;

namespace cAlgo
{
    [Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class BarsSample : Indicator
    {
        private TextBlock _barTicksNumberTextBlock, _barsStateTextBlock;

        [Output("Range", LineColor = "RoyalBlue")]
        public IndicatorDataSeries Range { get; set; }

        [Output("Body", LineColor = "Yellow")]
        public IndicatorDataSeries Body { get; set; }

        protected override void Initialize()
        {
            // Bars events
            Bars.BarOpened += Bars_BarOpened;

            Bars.Tick += Bars_Tick;

            Bars.HistoryLoaded += Bars_HistoryLoaded;

            Bars.Reloaded += Bars_Reloaded;

            var grid = new Grid(2, 2) 
            {
                BackgroundColor = Color.DarkGoldenrod,
                HorizontalAlignment = HorizontalAlignment.Right,
                VerticalAlignment = VerticalAlignment.Top,
                Opacity = 0.5
            };

            grid.AddChild(new TextBlock 
            {
                Text = "Bar Ticks #",
                Margin = 5
            }, 0, 0);

            _barTicksNumberTextBlock = new TextBlock 
            {
                Text = "0",
                Margin = 5
            };

            grid.AddChild(_barTicksNumberTextBlock, 0, 1);

            grid.AddChild(new TextBlock 
            {
                Text = "Bars State",
                Margin = 5
            }, 1, 0);

            _barsStateTextBlock = new TextBlock 
            {
                Margin = 5
            };

            grid.AddChild(_barsStateTextBlock, 1, 1);

            IndicatorArea.AddControl(grid);
        }

        private void Bars_Reloaded(BarsHistoryLoadedEventArgs obj)
        {
            _barsStateTextBlock.Text = "Reloaded";
        }

        private void Bars_HistoryLoaded(BarsHistoryLoadedEventArgs obj)
        {
            _barsStateTextBlock.Text = "History Loaded";
        }

        private void Bars_Tick(BarsTickEventArgs obj)
        {
            _barTicksNumberTextBlock.Text = Bars.TickVolumes.LastValue.ToString();
        }

        private void Bars_BarOpened(BarOpenedEventArgs obj)
        {
            _barsStateTextBlock.Text = "New Bar Opened";
        }

        public override void Calculate(int index)
        {
            Range[index] = Bars.HighPrices[index] - Bars.LowPrices[index];
            Body[index] = Math.Abs(Bars.ClosePrices[index] - Bars.OpenPrices[index]);
        }
    }
}

 

Getting Bars of another timeframe/symbol:

using cAlgo.API;
using cAlgo.API.Internals;

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class MarketDataSample : Indicator
    {
        private Bars _bars;

        private Ticks _ticks;

        private MarketDepth _marketDepth;

        [Parameter("Use Current Symbol", DefaultValue = true)]
        public bool UseCurrentSymbol { get; set; }

        [Parameter("Other Symbol Name", DefaultValue = "GBPUSD")]
        public string OtherSymbolName { get; set; }

        [Parameter("Use Current TimeFrame", DefaultValue = true)]
        public bool UseCurrentTimeFrame { get; set; }

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

        protected override void Initialize()
        {
            var symbol = UseCurrentSymbol ? Symbol : Symbols.GetSymbol(OtherSymbolName);
            var timeframe = UseCurrentTimeFrame ? TimeFrame : OtherTimeFrame;

            // You can use GetBarsAsync instead of GetBars
            _bars = MarketData.GetBars(timeframe, symbol.Name);
            // You can use GetTicksAsync instead of GetTicks
            _ticks = MarketData.GetTicks(symbol.Name);

            _marketDepth = MarketData.GetMarketDepth(symbol.Name);
        }

        public override void Calculate(int index)
        {
        }
    }
}

 


@amusleh

amusleh
07 Apr 2021, 11:16

Hi,

You should do it like this:

using cAlgo.API;

namespace cAlgo
{
    [Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class NewIndicator : Indicator
    {
        [Parameter("Period", DefaultValue = 10)]
        public int Period { get; set; }

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

        protected override void Initialize()
        {
        }

        public override void Calculate(int index)
        {
            var highest = Bars.ClosePrices.Maximum(Period);

            Result[index] = (highest - Bars.LowPrices[index]) / highest * 100;
        }
    }
}

 

Please learn C# basics and read cTrader Automate API references before trying to develop a cBot/indicator for cTrader.


@amusleh

amusleh
07 Apr 2021, 11:10

RE: RE:

animate44x said:

amusleh said:

Hi,

Not sure what do you mean by command, but you can access other time frames data from current or other symbols, here is a sample:

Once you got the bars then you can access the open/high/clow/close prices.

Thank you, that is what I was looking for. Could not find how to specify timeframe with the bars syntax.

The first parameter of MarketData.GetBars method is time frame, its in the sample if you check the code.


@amusleh

amusleh
07 Apr 2021, 11:08

Hi,

Please use my sample code for adding time range on your cBot, your cBot code is not correct and it even doesn't compile.

Next time you post code use the editor code snippet feature.

I recommend you to study C# basic and API references.

I consider this thread closed, we can't develop your cBot for you, all you need is already posted.


@amusleh

amusleh
07 Apr 2021, 11:03

Hi,

The methods works the way I explained on my previous post, just tested with this sample:

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

namespace cAlgo
{
    [Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class HasCrossedSample : Indicator
    {
        private SimpleMovingAverage _fastMa, _slowMa;

        [Parameter("Type", DefaultValue = CrossType.Above)]
        public CrossType CrossType { get; set; }
        
        [Parameter("Period", DefaultValue = 10)]
        public int Period { get; set; }

        [Output("Fast MA", LineColor = "Red", Thickness = 1)]
        public IndicatorDataSeries FastMa { get; set; }

        [Output("Slow MA", LineColor = "Yellow", Thickness = 2)]
        public IndicatorDataSeries SlowMa { get; set; }

        protected override void Initialize()
        {
            _fastMa = Indicators.SimpleMovingAverage(Bars.ClosePrices, 9);
            _slowMa = Indicators.SimpleMovingAverage(Bars.ClosePrices, 20);
        }

        public override void Calculate(int index)
        {
            FastMa[index] = _fastMa.Result[index];
            SlowMa[index] = _slowMa.Result[index];

            if (!IsLastBar) return;

            Chart.DrawVerticalLine("line", index - Period, Color.Red, 2);

            if (CrossType == CrossType.Above && FastMa.HasCrossedAbove(SlowMa, Period)) Print("Crossed");
            else if (CrossType == CrossType.Below && FastMa.HasCrossedBelow(SlowMa, Period)) Print("Crossed");
        }
    }
    
    public enum CrossType
    {
        Above,
        Below
    }
}

The sample indicator will draw a vertical line on period start, and then if fast MA crossed above/below slow MA it will print "Crossed" on log.

A cross must happen during the period values.


@amusleh

amusleh
07 Apr 2021, 09:25

Hi,

Not sure what do you mean by command, but you can access other time frames data from current or other symbols, here is a sample:

Once you got the bars then you can access the open/high/clow/close prices.


@amusleh

amusleh
07 Apr 2021, 09:21

In case you still have problem with chart events or if you are reading this thread and you have similar issue here is a sample indicator:

 


@amusleh

amusleh
06 Apr 2021, 15:04

Hi,

The methods check if there was any cross in x last periods, if there was any it returns true otherwise it returns false.

If you use HasCrossedAbove with 10 as period, then it checks if is the crossing series has crossed at least one time the crossed series upward in last 10 values or not, if it did then the method returns true otherwise it returns false.

Same for HasCrossedBelow, except it checks for downward cross.

An up cross happens if a value inside crossing series goes above//equal to crossed series value and previous value of crossing series was below crossed series value.

A down cross happens if a value inside crossing series goes below//equal to crossed series value and previous value of crossing series was above crossed series value.


@amusleh

amusleh
06 Apr 2021, 11:23

Hi,

You can change date time to a numerical unit like Unix time and then use it instead of date time for your statistical models, as I know all time series data uses the date time for x coordinate.


@amusleh

amusleh
06 Apr 2021, 10:47

Hi,

This sample cBot might help you:

using cAlgo.API;
using System;
using System.Globalization;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
    public class TradeTime : Robot
    {
        private TimeSpan _startTime, _endTime;

        [Parameter("Start Time", DefaultValue = "07:00:00", Group = "Time Filter")]
        public string StartTime { get; set; }

        [Parameter("End Time", DefaultValue = "16:00:00", Group = "Time Filter")]
        public string EndTime { get; set; }

        private DateTime CurrentTime
        {
            get { return Server.TimeInUtc.Add(-Application.UserTimeOffset); }
        }

        private bool IsTimeCorrect
        {
            get { return (_startTime > _endTime && (CurrentTime.TimeOfDay >= _startTime || CurrentTime.TimeOfDay <= _endTime)) || (_startTime < _endTime && (CurrentTime.TimeOfDay >= _startTime && CurrentTime.TimeOfDay <= _endTime)); }
        }

        protected override void OnStart()
        {
            if (!TimeSpan.TryParse(StartTime, CultureInfo.InvariantCulture, out _startTime))
            {
                Print("Invalid start time input");

                Stop();
            }

            if (!TimeSpan.TryParse(EndTime, CultureInfo.InvariantCulture, out _endTime))
            {
                Print("Invalid end time input");

                Stop();
            }
        }

        protected override void OnBar()
        {
            // Return if current time is not in start/end time range
            if (!IsTimeCorrect) return;
        }
    }
}

Please take a look on Server.Time, Server.TimeInUtc, Application.UserTimeOffset, .NET TimeSpan, and DateTime.

If you know the C# basics and cTrader automate API references then you can easily do it.


@amusleh

amusleh
05 Apr 2021, 19:06

Oi,
Você pode nos dizer qual é o problema em inglês?


@amusleh