Topics

Forum Topics not found

Replies

amusleh
16 Feb 2022, 08:23

Hi,

You can't send a new order request with take profit or trailing stop loss by using FIX API.

I recommend you to use cTrader Open API for that instead of FIX API.


@amusleh

amusleh
15 Feb 2022, 09:19

Hi,

I see identical results from both indicators, on second indicator you have removed some outputs.

What's the exact issue?

You can't make changes on a code without basic knowledge of the programming language or environment and expect same output.

Please learn the .NET C# basics first before starting to develop indicators/cBots.


@amusleh

amusleh
15 Feb 2022, 09:11

Hi,

You can do something like this:

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class NewcBot : Robot
    {
        private Dictionary<int, double> _positionsVolume = new Dictionary<int, double>(100);

        protected override void OnStart()
        {
            foreach (var position in Positions)
            {
                _positionsVolume.Add(position.Id, position.VolumeInUnits);
            }

            Positions.Opened += Positions_Opened;
            Positions.Closed += Positions_Closed;
            Positions.Modified += Positions_Modified;
        }

        private void Positions_Closed(PositionClosedEventArgs obj)
        {
            if (_positionsVolume.ContainsKey(obj.Position.Id))
            {
                _positionsVolume.Remove(obj.Position.Id);
            }
        }

        private void Positions_Opened(PositionOpenedEventArgs obj)
        {
            _positionsVolume.Add(obj.Position.Id, obj.Position.VolumeInUnits);
        }

        private void Positions_Modified(PositionModifiedEventArgs obj)
        {
            if (_positionsVolume.ContainsKey(obj.Position.Id))
            {
                var positionPreviousVolume = _positionsVolume[obj.Position.Id];

                if (positionPreviousVolume == obj.Position.VolumeInUnits)
                {
                    // It means volume desn't changed
                }
                // volume changed
                else
                {
                    // new volume added
                    if (positionPreviousVolume < obj.Position.VolumeInUnits)
                    {
                        Print("Position {0} volume increased, new volume: {1} | previous volume: {2}", obj.Position.Id, obj.Position.VolumeInUnits, positionPreviousVolume);
                    }
                    // position partially closed
                    else
                    {
                        Print("Position {0} partially closed, new volume: {1} | previous volume: {2}", obj.Position.Id, obj.Position.VolumeInUnits, positionPreviousVolume);
                    }
                }

                _positionsVolume[obj.Position.Id] = obj.Position.VolumeInUnits;
            }
            else
            {
                _positionsVolume.Add(obj.Position.Id, obj.Position.VolumeInUnits);
            }
        }
    }
}

 


@amusleh

amusleh
15 Feb 2022, 09:01

Hi,

You can use an enum, ex:

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class NewcBot : Robot
    {
        [Parameter("Instance Name", DefaultValue = "001")]
        public string InstanceName { get; set; }

        [Parameter("Lot Size", DefaultValue = 0.1)]
        public double LotSize { get; set; }

        [Parameter("Source SMA #1", DefaultValue = DataSource.Low)]
        public DataSource SourceSma1 { get; set; }

        [Parameter("Source SMA #2", DefaultValue = DataSource.High)]
        public DataSource SourceSma2 { get; set; }

        [Parameter("Period SMA #1", DefaultValue = 5, MinValue = 1, MaxValue = 100)]
        public int PeriodsSma1 { get; set; }

        [Parameter("Period SMA #2", DefaultValue = 20, MinValue = 1, MaxValue = 100)]
        public int PeriodsSma2 { get; set; }

        [Parameter("Calculate OnBar", DefaultValue = false)]
        public bool CalculateOnBar { get; set; }

        #region Indicator declarations

        private SimpleMovingAverage _sma1 { get; set; }
        private SimpleMovingAverage _sma2 { get; set; }

        #endregion Indicator declarations

        /// <summary>
        /// This is called when the robot first starts, it is only called once.
        /// </summary>
        protected override void OnStart()
        {
            // construct the indicators
            _sma1 = Indicators.SimpleMovingAverage(GetSeries(SourceSma1), PeriodsSma1);
            _sma2 = Indicators.SimpleMovingAverage(GetSeries(SourceSma2), PeriodsSma2);
        }

        private DataSeries GetSeries(DataSource source)
        {
            switch (source)
            {
                case DataSource.High:
                    return Bars.HighPrices;

                case DataSource.Low:
                    return Bars.LowPrices;

                case DataSource.Close:
                    return Bars.ClosePrices;

                case DataSource.Open:
                    return Bars.OpenPrices;

                default:
                    throw new ArgumentOutOfRangeException("source");
            }
        }
    }

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

 


@amusleh

amusleh
15 Feb 2022, 08:39 ( Updated at: 21 Dec 2023, 09:22 )

RE:

ys2310 said:

The following code returns index of two different time stamp. The two index show identical number. Why is this?

index1, index2 are supposed to be different numbers, no?

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; }

        protected override void OnStart()
        {
            // Put your initialization logic here
            var series5 = MarketData.GetBars(TimeFrame.Minute);
            long index1 = series5.OpenTimes.GetIndexByTime(DateTime.Parse("2022-02-14 18:50:00"));
            long index2 = series5.OpenTimes.GetIndexByTime(DateTime.Parse("2022-02-14 18:54:15"));
            Print("{0} {1}", index1, index2);
        }        
    }
}

Hi,

I tested your code and the returned indices aren't identical on my case:

The correct way to use the GetIndexByTime method is to pass another series bar open time and get the index on current series, the GetIndexByTime returns the estimated nearest bar index to your passed time.

If you want to be more precise use the GetIndexByExactTime method, it returns a bar index if an exact time was there, otherwise it returns -1.


@amusleh

amusleh
15 Feb 2022, 08:33

RE: RE:

ncel01 said:

amusleh said:

Hi,

The symbol tick value property gives you the monetary value of one single tick of the symbol.

The symbol tick size property gives you the numeric size of a symbol tick.

For getting the symbol bid/ask price you can use Symbol.Bid or Symbol.Ask.

amusleh,

Thanks for your reply.

The purpose is not to get symbol bid/ask price but to get the current currency conversion ratio and, EURUSD is not the applicable instrument here involved.

Symbol.TickValue/Symbol.TickSize is called OnTick() and matching the current EURUSD price when running cBot. However, I have noticed that this value remains constant and not matching EURUSD price afterwards.

Thank you!

Hi,

If the quote currency of a symbol is same as your account deposit currency then the tick value will not change.

For conversion you should use tick value not tick size, tick size is always constant and it's the numeric value of a symbol tick.


@amusleh

amusleh
15 Feb 2022, 08:29

RE: Body size equal to 10 pips

vypchela said:

 

Am I doing it right, I need to find the size of the body equal to 10 pips of a bearish candle
var bar = Bars[1];
var barBodyRange = Math.Abs(bar.Open - bar.Close)/ Symbol.PipSize;
if (barBodyRange  >= 10)
Thanks again.

 

Hi,

Yes, your calculation is correct.

The 1 bar index means the second bar on your chart from beginning, so be sure to use the correct indices when working with bars.


@amusleh

amusleh
14 Feb 2022, 09:04

Hi,

Which API you are using for your strategy? automate API or Open API?

As you opened the thread on Open API section, for calculation of Pip/tick size/value you can use this tutorial: Profit/Loss Calculation - Open API (spotware.github.io)


@amusleh

amusleh
14 Feb 2022, 09:02

Hi,

The symbol tick value property gives you the monetary value of one single tick of the symbol.

The symbol tick size property gives you the numeric size of a symbol tick.

For getting the symbol bid/ask price you can use Symbol.Bid or Symbol.Ask.


@amusleh

amusleh
14 Feb 2022, 09:01

Hi,

You can use Position Modified event for partial closes.


@amusleh

amusleh
14 Feb 2022, 08:57

Hi,

No, the data type is double for based class and you can't create a child class from it with a different data type.

You can use collections like List.


@amusleh

amusleh
14 Feb 2022, 08:55

RE: RE:

ys2310 said:

Thank you for the code, it seems bar.OpenTime creates identical results and I know this.

Discrepancies happen when I use MarketData.GetBars(TimeFrame.Minute, "SP") as a second symbol for data feed.

Can you also please try this on your side and check the difference?

Best regards,

 

Hi,

There is no discrepancies at all. when you load the data with code, or you use the back test data, or the data the is loaded automatically on your chart, all of them came from same source.

The GetBars method loads some number of bars from that symbol, the index values of current symbol data with your loaded bars will not match.

You have to use the Bars.OpenTimes.GetIndexByTime method to get the correct index, for samples check this link: https://help.ctrader.com/ctrader-automate/indicator_code_samples#multiple-timeframes

 


@amusleh

amusleh
14 Feb 2022, 08:51

Hi,

You can use Robot ExecuteMarketOrder method to open a position: Method ExecuteMarketOrder | API reference | cTrader Community

You can find full sample cBot examples here: cAlgo API Reference - Position Interface (ctrader.com)


@amusleh

amusleh
14 Feb 2022, 08:48

Hi,

Try this:

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class Siple_MA : Robot
    {
        public enum ENUM_TP_TYPE
        {
            Fixed = 0,
            RiskRatio = 1
        }

        public enum ENUM_RISK_SOURCE
        {
            Equity = 0,
            Balance = 1
        }

        public enum ENUM_LOT_TYPE
        {
            Fixed_Lot = 0,
            Percent = 1
        }

        public enum ENUM_CROSS_TYPE
        {
            Ask_Bid = 1,

            // Ask/Bid
            Close_Price = 0

            // Close Price
        }

        public enum ENUM_SIGNAL_TYPE
        {
            MA_Cross = 0,

            // MAs cross
            Price_Touch = 1

            // Price hits First MA
        }

        #region Input Fast MA Parameters

        [Parameter("Fast MA Type", Group = "Fast MA Parameters")]
        public MovingAverageType FastType { get; set; }

        [Parameter("Fast MA Source", Group = "Fast MA Parameters")]
        public DataSeries FastSeries { get; set; }

        [Parameter("Fast MA Period", Group = "Fast MA Parameters", DefaultValue = 10)]
        public int FastPeriods { get; set; }

        #endregion Input Fast MA Parameters

        #region Input Slow MA Parameters

        [Parameter("Slow MA Type", Group = "Slow MA Parameters")]
        public MovingAverageType SlowType { get; set; }

        [Parameter("Slow MA Source", Group = "Slow MA Parameters")]
        public DataSeries SlowSeries { get; set; }

        [Parameter("Slow MA Period", Group = "Slow MA Parameters", DefaultValue = 60)]
        public int SlowPeriods { get; set; }

        #endregion Input Slow MA Parameters

        #region Input Trade Parameters

        [Parameter("Label", Group = "Trade Parameters", DefaultValue = "Gad Elias")]
        public string Label { get; set; }

        [Parameter("Applied price", Group = "Trade Parameters", DefaultValue = ENUM_CROSS_TYPE.Close_Price)]
        public ENUM_CROSS_TYPE priceType { get; set; }

        [Parameter("Signal Type", Group = "Trade Parameters", DefaultValue = ENUM_SIGNAL_TYPE.MA_Cross)]
        public ENUM_SIGNAL_TYPE signalType { get; set; }

        [Parameter("Take Profit type", Group = "Trade Parameters", DefaultValue = ENUM_TP_TYPE.Fixed)]
        public ENUM_TP_TYPE tpType { get; set; }

        [Parameter("Stop Loss in pips", Group = "Trade Parameters", DefaultValue = 0)]
        public double SL { get; set; }

        [Parameter("Take Profit value", Group = "Trade Parameters", DefaultValue = 0)]
        public double TP { get; set; }

        [Parameter("Close on the opposite signal", Group = "Trade Parameters", DefaultValue = true)]
        public bool oppositeClose { get; set; }

        [Parameter("Max Orders", Group = "Trade Parameters", DefaultValue = 1)]
        public int maxOrders { get; set; }

        [Parameter("Use Reverse Trade", Group = "Trade Parameters", DefaultValue = true)]
        public bool reverseTrade { get; set; }

        #endregion Input Trade Parameters

        #region Input Lot Size Parameters

        [Parameter("Lot Type", Group = "Lot Size", DefaultValue = ENUM_LOT_TYPE.Fixed_Lot)]
        public ENUM_LOT_TYPE lotType { get; set; }

        [Parameter("Risk Source", Group = "Lot Size", DefaultValue = ENUM_RISK_SOURCE.Balance)]
        public ENUM_RISK_SOURCE riskSource { get; set; }

        [Parameter("Risk/Lot Value", Group = "Lot Size", DefaultValue = 0.1)]
        public double risk { get; set; }

        #endregion Input Lot Size Parameters

        #region Input Break Even Parameters

        [Parameter("Use BreakEven", Group = "BreakEven", DefaultValue = false)]
        public bool UseBE { get; set; }

        [Parameter("BreakEven Start(pips)", Group = "BreakEven", DefaultValue = 10)]
        public double BEStart { get; set; }

        [Parameter("BreakEven Profit(pips)", Group = "BreakEven", DefaultValue = 0)]
        public double BEProfit { get; set; }

        #endregion Input Break Even Parameters

        private List<DayOfWeek> _pauseDays;

        private TimeSpan _startTime, _endTime;

        private bool _isPaused;

        [Parameter("Days", DefaultValue = "Friday,Saturday", Group = "Pause")]
        public string Days { get; set; }

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

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

        private MovingAverage fastMA;
        private MovingAverage slowMA;

        protected override void OnStart()
        {
            fastMA = Indicators.MovingAverage(FastSeries, FastPeriods, FastType);
            slowMA = Indicators.MovingAverage(SlowSeries, SlowPeriods, SlowType);

            if (priceType == ENUM_CROSS_TYPE.Ask_Bid)
            {
                lastAsk = Ask;
                lastBid = Bid;
            }
            else
            {
                lastClose = Bars.ClosePrices.Last(0);
            }
            lastMA = fastMA.Result.Last(0);
            // Put your initialization logic here

            _pauseDays = Days.Split(',').Select(day => (DayOfWeek)Enum.Parse(typeof(DayOfWeek), day)).ToList();

            if (TimeSpan.TryParse(StartTime, CultureInfo.InvariantCulture, out _startTime) == false)
            {
                Print("Invalid StartTime");
                Stop();
            }

            if (TimeSpan.TryParse(EndTime, CultureInfo.InvariantCulture, out _endTime) == false)
            {
                Print("Invalid EndTime");
                Stop();
            }

            Timer.Start(1);
        }

        protected override void OnTimer()
        {
            if (_pauseDays.Contains(Server.Time.DayOfWeek) && Server.Time.TimeOfDay >= _startTime && Server.Time.TimeOfDay <= _endTime)
            {
                _isPaused = true;
            }

            _isPaused = false;
        }

        private double lastAsk;
        private double lastBid;
        private double lastClose;
        private double lastMA;

        private DateTime lastBar;

        protected override void OnTick()
        {
            if (_isPaused) return;

            if (UseBE)
                BreakEven();
            double ma = 0;
            // Put your core logic here
            if (lastBar != Bars.OpenTimes.Last(0))
            {
                if (signalType == ENUM_SIGNAL_TYPE.MA_Cross)
                {
                    lastBar = Bars.OpenTimes.Last(0);
                    double ma1 = fastMA.Result.Last(1);
                    double ma1prev = fastMA.Result.Last(2);
                    double ma2 = slowMA.Result.Last(1);
                    double ma2prev = slowMA.Result.Last(2);
                    int currCross = CheckCross(ma1, ma1prev, ma2, ma2prev);
                    if (currCross == 0)
                    {
                        if (oppositeClose)
                        {
                            CloseOrders(TradeType.Sell);
                        }
                        if ((CalculateOrders() < maxOrders))
                        {
                            OpenOrder(TradeType.Buy);
                        }
                    }
                    if (currCross == 1)
                    {
                        if (oppositeClose)
                        {
                            CloseOrders(TradeType.Buy);
                        }
                        if ((CalculateOrders() < maxOrders))
                        {
                            OpenOrder(TradeType.Sell);
                        }
                    }
                }
                else
                {
                    ma = fastMA.Result.Last(0);

                    double prevPrice = priceType == ENUM_CROSS_TYPE.Ask_Bid ? lastAsk : lastClose;
                    double currPrice = priceType == ENUM_CROSS_TYPE.Ask_Bid ? Ask : Bars.ClosePrices.Last(0);
                    if (currPrice >= ma && prevPrice < lastMA)
                    {
                        if (CheckOrders())
                        {
                            OpenOrder(TradeType.Buy);
                        }
                        //Open Buy
                    }
                    prevPrice = priceType == ENUM_CROSS_TYPE.Ask_Bid ? lastBid : lastClose;
                    currPrice = priceType == ENUM_CROSS_TYPE.Ask_Bid ? Bid : Bars.ClosePrices.Last(0);
                    if (currPrice <= ma && prevPrice > lastMA)
                    {
                        if (CheckOrders())
                        {
                            OpenOrder(TradeType.Sell);
                        }
                        //Open Sell
                    }
                }
            }
            lastMA = ma;
            lastAsk = Ask;
            lastBid = Bid;
            lastClose = Bars.ClosePrices.Last(0);
        }

        private bool CheckOrders()
        {
            if (Positions.Find(Label, Symbol) != null)
                return false;
            return true;
        }

        private int CalculateOrders()
        {
            return Positions.FindAll(Label, Symbol).Length;
        }

        private void CloseOrders(TradeType type)
        {
            if (reverseTrade)
                type = type == TradeType.Buy ? TradeType.Sell : TradeType.Buy;

            foreach (var pos in Positions.FindAll(Label, Symbol, type))
            {
                ClosePosition(pos);
            }
        }

        private void OpenOrder(TradeType type)
        {
            if (reverseTrade)
                type = type == TradeType.Buy ? TradeType.Sell : TradeType.Buy;

            double op;
            double tp = tpType == ENUM_TP_TYPE.Fixed ? TP : SL * TP;
            double sl;

            double source = riskSource == ENUM_RISK_SOURCE.Balance ? Account.Balance : Account.Equity;

            double volumeInUnits = 0;
            if (lotType == ENUM_LOT_TYPE.Fixed_Lot)
                volumeInUnits = Symbol.QuantityToVolumeInUnits(risk);
            else
                volumeInUnits = CalculateVolume(SL, risk, source);

            if (volumeInUnits == -1)
                return;
            ExecuteMarketOrder(type, SymbolName, volumeInUnits, Label, SL, TP);
        }

        private double CalculateVolume(double stopLossPips, double riskSize, double source)
        {
            // source = Account.Balance or Account.Equity
            double riskPerTrade = source * riskSize / 100;
            double totalPips = stopLossPips;

            double _volume;
            double exactVolume = riskPerTrade / (Symbol.PipValue * totalPips);
            if (exactVolume >= Symbol.VolumeInUnitsMin)
            {
                _volume = Symbol.NormalizeVolumeInUnits(exactVolume);
            }
            else
            {
                _volume = -1;
                Print("Not enough Equity to place minimum trade, exactVolume " + exactVolume + " is not >= Symbol.VolumeInUnitsMin " + Symbol.VolumeInUnitsMin);
            }
            return _volume;
        }

        private int CheckCross(double v1, double v1prev, double v2, double v2prev)
        {
            if (v1prev < v2prev && v1 > v2)
                return 0;
            if (v1prev > v2prev && v1 < v2)
                return 1;
            return -1;
        }

        private void BreakEven()
        {
            if (!UseBE)
                return;

            foreach (var pos in Positions.FindAll(Label, SymbolName))
            {
                if (pos.TradeType == TradeType.Buy)
                {
                    if (Symbol.Ask >= pos.EntryPrice + BEStart * Symbol.PipSize && (pos.StopLoss < pos.EntryPrice + BEProfit * Symbol.PipSize || pos.StopLoss == null))
                    {
                        ModifyPosition(pos, pos.EntryPrice + BEProfit * Symbol.PipSize, pos.TakeProfit);
                    }
                }
                if (pos.TradeType == TradeType.Sell)
                {
                    if (Symbol.Bid <= pos.EntryPrice - BEStart * Symbol.PipSize && (pos.StopLoss > pos.EntryPrice - BEProfit * Symbol.PipSize || pos.StopLoss == null))
                    {
                        ModifyPosition(pos, pos.EntryPrice + BEProfit * Symbol.PipSize, pos.TakeProfit);
                    }
                }
            }
        }

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

 


@amusleh

amusleh
14 Feb 2022, 08:43

Hi,

In cTrader automate are available bars on your chart are inside a collection called Bars, you can access each bar with an index integer, example:

var bar = Bars[myBarIndex];
// To use Math functions you have to add using System; on top of your indicator/cBot
// The .NET Math.Abs method gives you the absolute value of a number
var barBodyRange = Math.Abs(bar.Open - bar.Close);

 


@amusleh

amusleh
11 Feb 2022, 09:15

Hi,

I tested the SP symbol data 1 minute bars from 6th to 9th of February 2022, and real time data was identical to back test data.

To test you can use this cBot code:

using System;
using cAlgo.API;
using System.Text;
using System.IO;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FileSystem)]
    public class DataTester : Robot
    {
        protected override void OnStop()
        {
            var startTime = new DateTime(2022, 2, 6, 0, 0, 0, DateTimeKind.Utc);
            var endTime = new DateTime(2022, 2, 9, 0, 0, 0, DateTimeKind.Utc);

            var stringBuilder = new StringBuilder();

            stringBuilder.AppendLine("Time,Open,High,Low,Close,Volume");

            foreach (var bar in Bars)
            {
                if (bar.OpenTime < startTime || bar.OpenTime > endTime)
                {
                    continue;
                }

                stringBuilder.AppendFormat("{0:o},{1},{2},{3},{4},{5}", bar.OpenTime, bar.Open, bar.High, bar.Low, bar.Close, bar.TickVolume);
                stringBuilder.AppendLine();
            }

            var filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), string.Format("data_{0}.csv", RunningMode));

            using (var stream = File.CreateText(filePath))
            {
                stream.Write(stringBuilder.ToString());
            }
        }
    }
}

It creates two CSV files on your desktop, run it both on real time chart and back tester.

Then use a text matching tool to compare the content of them, like this site: Text Compare! - An online diff tool that can find the difference between two text files (text-compare.com)

You will see that both have the same content.


@amusleh

amusleh
11 Feb 2022, 08:14

RE: Absolute value

florent.herb said:

Hi,

Thank you for your answer!

One question. How to code in C# absolute values? Thank you for your help.

Regards,

HERB Florent

Hi,

Do you mean how to get the absolute value of a number? you can use Math.Abs to get a number absolute value.


@amusleh

amusleh
10 Feb 2022, 08:44

Hi,

The calculation code differs, at line (first indicator):

double hma = ma5 + expSR * dh;

And for second indicator the same line is:

double ehma = pehma + expSR * eeh;

The "ma5" variable is different from "pechma".

You should change the calculation code of second indicator to:

            double pema = EMA[pi];
            double e = p - pema;
            double ema = pema + exp * e;
            EMA[index] = ema;

            double pemah = EMAH[pi];
            double eh = p - pemah;
            double emah = pemah + expH * eh;
            EMAH[index] = emah;

            double emai = 2 * emah - ema;
            EMAI[index] = emai;

            double pehma = EHMA[pi];
            double eeh = emai - pehma;
            double ehma = emai + expSR * eeh;
            EHMA[index] = ehma;

 


@amusleh

amusleh
10 Feb 2022, 08:32

Hi,

You can use a bool flag to avoid the second call:

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class HorizentalLineTest : Robot
    {
        private ChartHorizontalLine hlStopLoss;

        private bool _updatingComment;

        protected override void OnStart()
        {
            hlStopLoss = Chart.DrawHorizontalLine("StopLoss", Symbol.Bid, Color.FromHex("#BBFF7777"), 1, LineStyle.LinesDots);
            hlStopLoss.IsInteractive = true; hlStopLoss.IsLocked = false; hlStopLoss.Comment = Symbol.Bid.ToString();
            Chart.ObjectsUpdated += SLModified;
        }

        protected override void OnTick()
        { }

        protected override void OnStop()
        { Chart.RemoveObject(hlStopLoss.Name); }

        private void SLModified(ChartObjectsUpdatedEventArgs obj) //Modify HorizentialLine, to update Price in Comments
        {
            if (_updatingComment)
            {
                _updatingComment = false;

                return;
            }

            var horizentalLine = obj.ChartObjects.FirstOrDefault(iObject => iObject.ObjectType == ChartObjectType.HorizontalLine && iObject.Name.Equals(hlStopLoss.Name, StringComparison.OrdinalIgnoreCase));

            if (horizentalLine != null)
            {
                _updatingComment = true;

                hlStopLoss.Comment = hlStopLoss.Y.ToString("0.00000");
                Print("HorizentalLine's Y: " + hlStopLoss.Y.ToString("0.00000"));
            }
        }
    }
}

 


@amusleh

amusleh
10 Feb 2022, 08:27

RE: RE: RE:

ys2310 said:

I'm seeing this data discrepancies with broker called Axiory. For example, the date between 2022/Feb/06 to 2022/Feb/09.

I can see a bit large differences with symbols like SP, CL, and a bit more small differences with EURUSD, USDJPY. 

Best regards, 

 

Hi,

Can you tell us on which time frame data you found this issue?


@amusleh