Topics

Forum Topics not found

Replies

amusleh
11 Mar 2021, 13:57

Please try this new indicator code on your cBot:

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

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

        [Output("My")]
        public IndicatorDataSeries _myIsLong { get; set; }

        private ATRMTF_time_History _atr;
        public bool _isLong;

        private MarketSeries _marketSeries;

        //private AverageTrueRange_Cust_lag[,] stop_ind = new ATRStops[perCount, weightCount];
        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");

            _atr = Indicators.GetIndicator<ATRMTF_time_History>(Period, TF, LoadHistory_for_ind, LoadIndHist);

            _marketSeries = MarketData.GetSeries(MarketData.GetSymbol(Symbol.Name), TF);

            //else
            //Print("Не загружено {0} баров", BarCount_set);
        }

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

            if (_isLong)
                _myIsLong[index] = 2;
            else
                _myIsLong[index] = 1;
        }
    }
}

Inside your "_myIsLong" series 2 means True and 1 means False.


@amusleh

amusleh
10 Mar 2021, 09:23

Hello,

Try this:

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

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class MidasIndex : Robot
    {
        [Parameter(DefaultValue = 9)]
        public int PeriodFast { get; set; }

        [Parameter(DefaultValue = 26)]
        public int PeriodMedium { get; set; }

        [Parameter(DefaultValue = 52)]
        public int PeriodSlow { get; set; }

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

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

        [Parameter("Take Profit", DefaultValue = 25)]
        public int TakeProfitPips { get; set; }

        private IchimokuKinkoHyo _ichimoku;

        protected override void OnStart()
        {
            _ichimoku = Indicators.IchimokuKinkoHyo(PeriodFast, PeriodMedium, PeriodSlow);
        }

        protected override void OnBar()
        {
            var positionsBuy = Positions.FindAll("Buy");
            var positionsSell = Positions.FindAll("Sell");

            if (positionsBuy.Length > 0 || positionsSell.Length > 0) return;

            if (Bars.OpenPrices.Last(1) <= _ichimoku.SenkouSpanA.Last(1)
                && Bars.OpenPrices.Last(1) > _ichimoku.SenkouSpanB.Last(1)
                && Bars.ClosePrices.Last(1) > _ichimoku.SenkouSpanA.Last(1)
                && _ichimoku.TenkanSen.Last(1) > _ichimoku.KijunSen.Last(1))
            {
                ExecuteMarketOrder(TradeType.Buy, SymbolName, Volume, "Buy", StopLossPips, TakeProfitPips);
            }

            if (Bars.OpenPrices.Last(1) >= _ichimoku.SenkouSpanA.Last(1)
                && Bars.OpenPrices.Last(1) < _ichimoku.SenkouSpanB.Last(1)
                && Bars.ClosePrices.Last(1) < _ichimoku.SenkouSpanA.Last(1)
                && _ichimoku.TenkanSen.Last(1) < _ichimoku.KijunSen.Last(1))
            {
                ExecuteMarketOrder(TradeType.Sell, SymbolName, Volume, "Sell", StopLossPips, TakeProfitPips);
            }
        }
    }
}

I backtested and it worked fine.


@amusleh

amusleh
09 Mar 2021, 12:33

RE: Re3:

travkinsm1 said:

members of the forum, and first of all amusleh, have any thoughts about my problem?

I tried to compile your code but the "ATRMTF_time_History" indicator is missing, please decrease the amount of your code and post it again so I will be able to find the issue.

Right now I don't see any specific issue on your cBot code, but your indicator might be the problem.

Regarding getting different values, it can be because cBot loads different data, not the same amount of data that indicator uses, your indicator is a multi time frame indicator and it references another multi time frame indicator, which can cause this mismatch.

I recommend you if its possible move your indicator code to your cBot, that will decrease the complexity and you will have direct access to code so you will not much easier what goes wrong.

Try to use the indicator on a small sample cBot, see if you can replicate the issue, if you were able then post that small sample cBot here and I will be able to identify the issue faster


@amusleh

amusleh
08 Mar 2021, 13:07

Try this:

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class TestVWAP_Bot : Robot
    {
        [Parameter("TradeType")]
        public TradeType TradeDir { get; set; }

        [Parameter("Max Buy Positions", DefaultValue = 1, MinValue = 1)]
        public int MaxBuy { get; set; }

        [Parameter("Max Sell Positions", DefaultValue = 1, MinValue = 1)]
        public int MaxSell { get; set; }

        [Parameter("Trade Start Time", DefaultValue = 7, MinValue = 7, MaxValue = 8)]
        public double StartTime { get; set; }

        [Parameter("Trade End Time", DefaultValue = 14, MinValue = 14, MaxValue = 15)]
        public double EndTime { get; set; }

        private TestVWAP _vwap;

        protected override void OnStart()
        {
            _vwap = Indicators.GetIndicator<TestVWAP>();
        }

        protected override void OnBar()
        {
            double Time = Server.Time.TimeOfDay.TotalHours;

            if (!(StartTime <= Time && Time <= EndTime)) return;

            if (TradeDir == TradeType.Buy)
            {
                if (Positions.FindAll("TestVWAP_Bot", Symbol.Name, TradeType.Buy).Length >= MaxBuy) return;

                if (Bars.OpenPrices.Last(1) < _vwap.Result.Last(1) && Bars.ClosePrices.Last(1) > _vwap.Result.Last(1))
                {
                    ExecuteMarketOrder(TradeType.Buy, Symbol.Name, 1000, "TestVWAP_Bot", 30, 60);
                }
            }
            else if (TradeDir == TradeType.Sell)
            {
                if (Positions.FindAll("TestVWAP_Bot", Symbol.Name, TradeType.Sell).Length >= MaxSell) return;

                if (Bars.OpenPrices.Last(1) > _vwap.Result.Last(1) && Bars.ClosePrices.Last(1) < _vwap.Result.Last(1))
                {
                    ExecuteMarketOrder(TradeType.Sell, Symbol.Name, 1000, "TestVWAP_Bot", 30, 60);
                }
            }
        }
    }
}

Next time please also post the custom indicator code you are using.


@amusleh

amusleh
08 Mar 2021, 13:00

Try this:

using cAlgo.API;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class BarColorChangeTrader : Robot
    {
        protected override void OnBar()
        {
            if (Bars.ClosePrices.Last(1) > Bars.OpenPrices.Last(1)
                && Bars.ClosePrices.Last(2) < Bars.OpenPrices.Last(2))
            {
                Print("New bullish/up bar");

                ExecuteMarketOrder(TradeType.Buy, SymbolName, Symbol.VolumeInUnitsMin);
            }
            else if (Bars.ClosePrices.Last(1) < Bars.OpenPrices.Last(1)
                && Bars.ClosePrices.Last(2) > Bars.OpenPrices.Last(2))
            {
                Print("New bearish/down bar");

                ExecuteMarketOrder(TradeType.Sell, SymbolName, Symbol.VolumeInUnitsMin);
            }
        }
    }
}

 


@amusleh

amusleh
05 Mar 2021, 10:59

RE:

amanpathak1997 said:

How can we set multiple Take Profits with different volumes on cTrader Automate? 

For example I have a 1 lot postion on EurUsd.

I want to set Muliple Take Profits as following:

0.5 lots at 10 pips profit.

0.2 lots at 20 pips profit.

and so on.

You can implement multiple take profit levels by Pips like this:

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

namespace cAlgo.Robots
{
    /// <summary>
    /// Allows setting multiple take profit levels for positions
    /// Set a take profit volume parameter value to 0 if you don't want to use it
    /// </summary>
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class MultiTPBot : Robot
    {
        private double _firstTakeProfitVolumeInUnits;
        private double _secondTakeProfitVolumeInUnits;
        private double _thirdTakeProfitVolumeInUnits;
        private double _fourthTakeProfitVolumeInUnits;

        private List<long> _firstTakeProfitTriggeredPositionIds = new List<long>();
        private List<long> _secondTakeProfitTriggeredPositionIds = new List<long>();
        private List<long> _thirdTakeProfitTriggeredPositionIds = new List<long>();
        private List<long> _fourthTakeProfitTriggeredPositionIds = new List<long>();

        [Parameter("1st TP", DefaultValue = 0.01, MinValue = 0, Group = "Volume (Lots)")]
        public double FirstTakePrfitVolumeInLots { get; set; }

        [Parameter("2nd TP", DefaultValue = 0.03, MinValue = 0, Group = "Volume (Lots)")]
        public double SecondTakePrfitVolumeInLots { get; set; }

        [Parameter("3rd TP", DefaultValue = 0.05, MinValue = 0, Group = "Volume (Lots)")]
        public double ThirdTakePrfitVolumeInLots { get; set; }

        [Parameter("4th TP", DefaultValue = 0.1, MinValue = 0, Group = "Volume (Lots)")]
        public double FourthTakePrfitVolumeInLots { get; set; }

        [Parameter("1st TP", DefaultValue = 10, MinValue = 0, Group = "Pips")]
        public double FirstTakePrfitPips { get; set; }

        [Parameter("2nd TP", DefaultValue = 20, MinValue = 0, Group = "Pips")]
        public double SecondTakePrfitPips { get; set; }

        [Parameter("3rd TP", DefaultValue = 30, MinValue = 0, Group = "Pips")]
        public double ThirdTakePrfitPips { get; set; }

        [Parameter("4th TP", DefaultValue = 40, MinValue = 0, Group = "Pips")]
        public double FourthTakePrfitPips { get; set; }

        protected override void OnStart()
        {
            _firstTakeProfitVolumeInUnits = Symbol.QuantityToVolumeInUnits(FirstTakePrfitVolumeInLots);
            _secondTakeProfitVolumeInUnits = Symbol.QuantityToVolumeInUnits(SecondTakePrfitVolumeInLots);
            _thirdTakeProfitVolumeInUnits = Symbol.QuantityToVolumeInUnits(ThirdTakePrfitVolumeInLots);
            _fourthTakeProfitVolumeInUnits = Symbol.QuantityToVolumeInUnits(FourthTakePrfitVolumeInLots);
        }

        protected override void OnTick()
        {
            foreach (var position in Positions)
            {
                if (!position.SymbolName.Equals(SymbolName, StringComparison.OrdinalIgnoreCase)) continue;

                TriggerTakeProfitIfReached(position, _firstTakeProfitVolumeInUnits, FirstTakePrfitPips,
                    _firstTakeProfitTriggeredPositionIds);

                TriggerTakeProfitIfReached(position, _secondTakeProfitVolumeInUnits, SecondTakePrfitPips,
                    _secondTakeProfitTriggeredPositionIds);

                TriggerTakeProfitIfReached(position, _thirdTakeProfitVolumeInUnits, ThirdTakePrfitPips,
                    _thirdTakeProfitTriggeredPositionIds);

                TriggerTakeProfitIfReached(position, _fourthTakeProfitVolumeInUnits, FourthTakePrfitPips,
                    _fourthTakeProfitTriggeredPositionIds);
            }
        }

        private void ModifyPositionVolume(Position position, double newVolume)
        {
            if (position.VolumeInUnits > newVolume)
            {
                ModifyPosition(position, newVolume);
            }
            else
            {
                ClosePosition(position);
            }
        }

        private void TriggerTakeProfitIfReached(Position position, double takeProfitVolumeInUnits, double takeProfitPips,
            List<long> triggeredPositionIds)
        {
            if (triggeredPositionIds.Contains(position.Id)) return;

            if (takeProfitVolumeInUnits > 0 && position.Pips >= takeProfitPips)
            {
                triggeredPositionIds.Add(position.Id);

                ModifyPositionVolume(position, position.VolumeInUnits - takeProfitVolumeInUnits);
            }
        }
    }
}

 


@amusleh

amusleh
04 Mar 2021, 11:01

RE:

sergiualexandrugrigore19932018 said:

Wouldn't it be great to have the option to activate a function in cTrader platform to change the normal SL in TSL after the price has moved a certain amount of pips?

Example: if my SL is at 20pips and my TP is at 200 pips, I would like the platform to change my SL in TSL after I'm in 60 pips profit without me having to manually do that.

I think this a great idea, hope you can consider it, after all you already have the advanced stop loss which moves the SL to breakeven after a certain amount of pips in profit, I think it would be fairly easy for you to code this. 

 

You can use a cBot, use this sample cBot:

using cAlgo.API;
using System;

namespace cAlgo.Robots
{
    /// <summary>
    /// Changes current symbol positions normal stop loss to trailing stop loss once it reached x amount of pips in profit
    /// </summary>
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class StopLossToTSL : Robot
    {
        [Parameter("Pips Profit", DefaultValue = 20)]
        public double PipsProfit { get; set; }

        protected override void OnTick()
        {
            foreach (var position in Positions)
            {
                if (!position.SymbolName.Equals(SymbolName, StringComparison.OrdinalIgnoreCase)
                    || position.HasTrailingStop
                    || !position.StopLoss.HasValue
                    || position.Pips < PipsProfit) continue;

                ModifyPosition(position, position.StopLoss, position.TakeProfit, true, position.StopLossTriggerMethod);
            }
        }
    }
}

 


@amusleh

amusleh
04 Mar 2021, 09:55

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();

        }
    }
}

 

Inside your cBot OnTick method: 

            bool dirInd = Indicators.GetIndicator<ATR_Stops_time_MarketData_History>(TF, MaType, 10, 4, UseHighAndLow, LoadHistory_for_ind, LoadIndHist)._isLong;

You should not do this, you have to initialize a custom indicator on your cBot OnStart method not inside OnTick method.

And don't use properties/fields of your custom indicator, instead try to use IndicatorDataSeries, you can't get the actual value of properties/fields inside your cBot.


@amusleh

amusleh
03 Mar 2021, 09:44

RE: RE:

SmartArtsStudio said:

PanagiotisCharalampous said:

Hi SmartArtsStudio,

There is no such option in the API to achieve that. The only way to achieve it is to set your time2 variable in a distant future time and keep the distance far away as the chart moves to the right.

Best Regards,

Panagiotis 

Join us on Telegram

That will work.
What would be the simplest method to add the ChartArea.Width to Chart.LastVisibleBarIndex to come up with a DateTime or X value in the future?
Thanks

The chart width unit is not in number of bars, its the width of chart, try this:

using cAlgo.API;

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class InfinitRectangle : Indicator
    {
        // Use this later if you want to extend the rectangle more as user zoom in/out or scroll
        private ChartRectangle _rectangle;

        protected override void Initialize()
        {
            var numberOfVisibleBars = Chart.LastVisibleBarIndex - Chart.FirstVisibleBarIndex;

            var lastVisibleBarIndex = Chart.FirstVisibleBarIndex + Chart.MaxVisibleBars;

            _rectangle = Chart.DrawRectangle("rect", Chart.FirstVisibleBarIndex, Bars.HighPrices.Maximum(numberOfVisibleBars),
                lastVisibleBarIndex, Bars.LowPrices.Minimum(numberOfVisibleBars), Color.Red);
        }

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

 


@amusleh

amusleh
03 Mar 2021, 07:46

RE: RE: RE:

amirus.stark said:

afhacker said:

 

Why you are not using text block? you are trying to mix chart objects with chart controls, Canvas is a chart control, and the Chart.DrawStaticText draws a chart object on the chart.

You have to use a chart control inside canvas not an object, try text block.

You can add multiple text blocks for each character so they will have different colors.

Well basically because in the same line some characters have different colors than others and in TextBlock you can pick a color for a whole string :/

 

You can do something like this:

using cAlgo.API;

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class DifferentColorText : Indicator
    {
        protected override void Initialize()
        {
            var canvas = new Canvas
            {
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center
            };

            canvas.AddChild(new TextBlock
            {
                ForegroundColor = Color.Blue,
                Text = "A ",
                Left = 10,
                Top = 15,
            });

            canvas.AddChild(new TextBlock
            {
                ForegroundColor = Color.Yellow,
                Text = "B ",
                Left = 20,
                Top = 15,
            });

            canvas.AddChild(new TextBlock
            {
                ForegroundColor = Color.Green,
                Text = "C ",
                Left = 30,
                Top = 15,
            });

            canvas.AddChild(new TextBlock
            {
                ForegroundColor = Color.Magenta,
                Text = "D",
                Left = 40,
                Top = 15,
            });

            Chart.AddControl(canvas);
        }

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

Or to make it easier you can create a custom control for it.


@amusleh

amusleh
01 Mar 2021, 11:29 ( Updated at: 01 Mar 2021, 11:30 )

The issue with your code is that you are using mouse position on chart not screen, the window form location (x,y) is based on your screen coordinates not chart.

To solve the issue you have two option, either use the chart controls or use Windows API to get the location of mouse on your screen.

Here is an example of how you can show a tooltip with chart controls:

using cAlgo.API;

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
    public class CustomData : Indicator
    {
        [Parameter(DefaultValue = 0.0)]
        public double Parameter { get; set; }

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

        private Tooltip _tooltip;

        protected override void Initialize()
        {
            var content = new TextBlock { Text = "Here you can put any control", Margin = 5 };

            _tooltip = new Tooltip(content)
            {
                VerticalAlignment = VerticalAlignment.Top,
                HorizontalAlignment = HorizontalAlignment.Left,
                IsVisible = false,
                Width = 160,
                Height = 40
            };

            Chart.AddControl(_tooltip);

            Chart.MouseMove += OnMouseMove;
            Chart.MouseLeave += OnMouseLeave;
            Chart.MouseEnter += Chart_MouseEnter;
        }

        private void Chart_MouseEnter(ChartMouseEventArgs obj)
        {
            _tooltip.IsVisible = true;
        }

        public override void Calculate(int index)
        {
            // Calculate value at specified index
            // Result[index] = ...
        }

        protected void OnMouseMove(ChartMouseEventArgs obj)
        {
            var extraDelta = 10;
            var width = _tooltip.Width;
            var height = _tooltip.Height;
            var left = Chart.Width - obj.MouseX > width + extraDelta ? obj.MouseX + extraDelta : obj.MouseX - width - extraDelta;
            var right = Chart.Height - obj.MouseY > height + extraDelta ? obj.MouseY + extraDelta : obj.MouseY - height - extraDelta;

            _tooltip.Margin = new Thickness(left, right, 0, 0);
        }

        protected void OnMouseLeave(ChartMouseEventArgs obj)
        {
            _tooltip.IsVisible = false;
        }
    }

    public class Tooltip : CustomControl
    {
        public Tooltip(ControlBase content)
        {
            var border = new Border
            {
                BackgroundColor = "#3F3F3F",
                BorderColor = "#969696",
                BorderThickness = 1,
                CornerRadius = 5
            };

            border.Child = content;

            AddChild(border);
        }
    }
}

If you want to use a Windows form then you have to use the Windows API to get the mouse location on screen.

For using Windows API you can use my GlobalHook library: 

 

Example:

using cAlgo.API;
using Gma.UserActivityMonitor;
using System;
using System.Threading;

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
    public class CustomData : Indicator
    {
        private DataForm _dataForm = new DataForm();

        private Thread _appThread;

        protected override void Initialize()
        {
            Chart.MouseLeave += OnMouseLeave;
            Chart.MouseEnter += Chart_MouseEnter;

            RunApplicationThread();
        }

        public override void Calculate(int index)
        {
        }

        private void HookManager_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            _dataForm.Location = e.Location;
        }

        private void Chart_MouseEnter(ChartMouseEventArgs obj)
        {
            _dataForm.Visible = true;

            _dataForm.TopMost = true;
        }

        protected void OnMouseLeave(ChartMouseEventArgs obj)
        {
            _dataForm.Visible = false;
        }

        private void RunApplicationThread()
        {
            _appThread = new Thread(() =>
            {
                try
                {
                    HookManager.MouseMove += HookManager_MouseMove;

                    // Without a running application loop the global hook will not work!
                    System.Windows.Forms.Application.Run(_dataForm);

                    _dataForm.Visible = false;
                }
                catch (Exception ex)
                {
                    Print(ex);
                }
            });

            _appThread.SetApartmentState(ApartmentState.STA);
            _appThread.DisableComObjectEagerCleanup();

            _appThread.Start();
        }
    }
}

 

If you use a windows form as a tooltip and move it alongside mouse cursor it will use too much resource so I recommend you to use chart controls instead.


@amusleh