Replies

rgasch
24 Jan 2021, 23:04

RE:

Thank you for your help, I got it to work ... 

 

PanagiotisCharalampous said:

Hi rgasch,

1) Print() method for indicators works only in cTrader Automate

2) Your indicator code seems outdated. Please use the one below

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

namespace cAlgo.Indicators
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class HeikenAshiPro : Indicator
    {
        [Output("_haOpen")]
        public IndicatorDataSeries _haOpen { get; set; }
        [Output("_haClose")]
        public IndicatorDataSeries _haClose { get; set; }
        [Output("_haHigh")]
        public IndicatorDataSeries _haHigh { get; set; }
        [Output("_haLow")]
        public IndicatorDataSeries _haLow { get; set; }
        [Output("_haColorDir")]
        public IndicatorDataSeries _haColorDir { get; set; }


        protected override void Initialize()
        {
        }


        public override void Calculate(int index)
        {
            var open = Bars.OpenPrices[index];
            var high = Bars.HighPrices[index];
            var low = Bars.LowPrices[index];
            var close = Bars.ClosePrices[index];
            var time = Bars.OpenTimes[index];

            var haClose = (open + high + low + close) / 4;
            var haOpen = (index > 0) ? (_haOpen[index - 1] + _haClose[index - 1]) / 2 : (open + close) / 2;
            var haHigh = Math.Max(Math.Max(high, haOpen), haClose);
            var haLow = Math.Min(Math.Min(low, haOpen), haClose);

            _haOpen[index] = haOpen;
            _haHigh[index] = haHigh;
            _haLow[index] = haLow;
            _haClose[index] = haClose;
            _haColorDir[index] = haClose > haOpen ? 1 : -1;
            Print("XXX " + index);
            Print("YYY " + _haOpen[index]);

            Chart.ChartType = ChartType.Line;
            drawCandle(index, time, haOpen, haHigh, haLow, haClose);
        }


        private void drawTrendLine(int id, DateTime time1, double open1, DateTime time2, double open2, double close2)
        {
            var clr = close2 > open2 ? Color.ForestGreen : Color.OrangeRed;
            Chart.DrawTrendLine("trendline" + id, time1, open1, time2, open2, clr, 2);
        }


        private void drawCandle(int id, DateTime t, double open, double high, double low, double close)
        {

            var clr = close > open ? Color.ForestGreen : Color.OrangeRed;
            Chart.DrawTrendLine("candlebody" + id, t, open, t, close, clr, candlewidth(Chart.ZoomLevel));
            Chart.DrawTrendLine("candlewick" + id, t, high, t, low, clr, 1);

            Chart.DrawEllipse("price" + id, t, Bars.ClosePrices.LastValue, t, Bars.ClosePrices.LastValue, Color.Blue, 8);
            resetCandlewidth();

        }


        private int candlewidth(int zoomlevel)
        {
            return zoomlevel <= 10 ? 1 : (zoomlevel <= 20 ? 2 : (zoomlevel <= 40 ? 5 : (zoomlevel <= 80 ? 10 : (zoomlevel <= 180 ? 20 : (zoomlevel <= 320 ? 40 : (60))))));
        }


        private void resetCandlewidth()
        {
            //  if (_previousZoomLevel != Chart.ZoomLevel)
            {
                //_previousZoomLevel = Chart.ZoomLevel;
                for (int i = 0; i < _haOpen.Count; i++)
                {
                    var time = Bars.OpenTimes[i];
                    var haclr = _haClose[i] > _haOpen[i] ? Color.ForestGreen : Color.OrangeRed;
                    Chart.DrawTrendLine("candlebody" + i, time, _haOpen[i], time, _haClose[i], haclr, candlewidth(Chart.ZoomLevel));

                    var dotwidth = Chart.ZoomLevel <= 80 ? 5 : 8;
                    Chart.DrawEllipse("price" + i, time, Bars.ClosePrices[i], time, Bars.ClosePrices[i], Color.Blue, dotwidth);
                }
            }
        }



    }
}

Best Regards,

Panagiotis 

Join us on Telegram

 

 


@rgasch

rgasch
05 Aug 2020, 13:06

RE:

Yes, this works. Thank you!

 

PanagiotisCharalampous said:

Hi rgasch,

Here is the correct way to do this

        private Supertrend _st;
        protected override void OnStart()
        {
            _st = Indicators.Supertrend(10, 3);
        }

Best Regards,

Panagiotis 

Join us on Telegram

 

 


@rgasch

rgasch
29 Jul 2020, 02:01

RE:

I've been playing around with this idea in the back of my head and have written a few lines of test code... I have these questions in case someone knows the answers (I should mention that I'm a quite experienced developer but this is my first time using C#, so I'm not familiar with the ecosystem, apologies if these are questions which would be completely obvious to someone with real C# experience): 

1) Does anybody know the arguments the "Bar" constructor will accept? It's not documented anywhere. I understand that it's probably only used internally but my guess is, it exists and can be used. 

2) Assuming #1 can be used/solved, how would I create a new instance of Bars with a leading/first element being the Bar created in #1. I've found that .Net 4.5 comes with an IEnumerable.prepend() method but my understanding is that CAlgo is not on 4.5 yet. 

Thank you in advance

 

rgasch said:

Would it be possible to generate theoretical/predictive MA values? I would like to be able to check the next/future MA value based on the prediction/possibility that the next bar is [insert next bar characteristics here]. 

I'm thinking that it should be possible to create a custom data array of data values and plug this into an MA function but I don't really see how to go about this. If you look at this piece of code as a sample 

_ma = Indicators.MovingAverage(Bars.ClosePrices, maPeriod, MAType);

then this suggests that it should be possible to create a custom/altered bars data array and pass this to the MovingAverage method but I'm not sure how to go about doing this. Could someone maybe suggest a few lines of code which demonstrate how to do this? 

 


@rgasch

rgasch
17 Jul 2020, 11:45

RE:

Thank you for your confirmation ...

 

PanagiotisCharalampous said:

Hi rgasch,

Does "Bars.Last(0)" return the currently active bar (ie: the bar which is still being painted/altered (for the case of Renko, the candle which has still not completed a move across the Renko pip size))

Yes this is the case.

 Does the same logic hold for accessing moving-average values?

Yes

 is my above code correct if I wish to check the value of the last closed/completed bar against the last completed MA value? 

Yes

 Best Regards,

Panagiotis 

Join us on Telegram

 

 


@rgasch

rgasch
16 Jul 2020, 12:36

RE:

I'm an idiot who made a stupid programming error ... 

Thank you for getting back to me. 

 


@rgasch

rgasch
16 Jul 2020, 12:27

RE:

Thank you for your clarification ...

 

PanagiotisCharalampous said:

Hi rgasch,

PositionModifiedEventArgs contains a reference to the position that was modified. If you want to know what was modified exactly, you will need to track this information yourself.

Best Regards,

Panagiotis 

Join us on Telegram

 


@rgasch

rgasch
16 Jul 2020, 02:19

RE:

+1 for Renko backtesting ...

 

anxolandeira said:

I would like to see this feature, since it cannot be used yet. Also, doing the "walaround" with an indicator doesnt always work fine.

 


@rgasch

rgasch
16 Jul 2020, 00:43

RE:

The formula/code you provided makes perfect sense, but for some reason I have a USDCAD chart (renko size = 5 pips) where this returns "10" as a result. Any ideas what could be causing this? 

Thank you in advance

 

PanagiotisCharalampous said:

Hi rgasch,

Just get one of the previous bricks and check the difference in pips between the open and close prices e.g.

 var size = Math.Abs(Bars.ClosePrices.Last(1) - Bars.OpenPrices.Last(1)) / Symbol.PipSize;

Best Regards,

Panagiotis 

Join us on Telegram

 

 


@rgasch

rgasch
13 Jul 2020, 10:54

RE:

Simple and effective, thank you very much!

 

PanagiotisCharalampous said:

Hi rgasch,

Just get one of the previous bricks and check the difference in pips between the open and close prices e.g.

 var size = Math.Abs(Bars.ClosePrices.Last(1) - Bars.OpenPrices.Last(1)) / Symbol.PipSize;

Best Regards,

Panagiotis 

Join us on Telegram

 

 


@rgasch

rgasch
01 Jul 2020, 19:12

RE:

Thank you, I will check out the link you provided. 

Appreciate your help ...

 

PanagiotisCharalampous said:

Hi rgasch,

There is no API call for this. You will need to convert the relevant amount to base asset units. You need to calculate the rate between your account currency and your symbol's base asset. Here a trader tried to do it for calculating the required margin but it is a good starting point.

Best Regards,

Panagiotis 

Join us on Telegram

 


@rgasch

rgasch
01 Jul 2020, 15:53

RE:

Hi Panagiotis, 

thank you for your reply; it definitely clears up some confusion I had ...

Allow me to inquire, what would the correct API call be to convert a USD or EUR amount to a lot size?

Thank you very much

 

PanagiotisCharalampous said:

Hi rgasch,

You assume that this part of the code is taking as input a value in USD and converts it into Lots

var lots = Symbol.VolumeInUnitsToQuantity(amt);

But this is wrong. VolumeInUnitsToQuantity() takes as input units of the traded symbol and returns the relevant Lot Size. Units always represent units of the base asset. So when you are trading SP5000 you are inputting 10000 contracts of this index and you are receiving as a return 10000 lots since 1 contract = 1 Lot. It works on some FX pairs by luck since the account's currency coincides with the base asset e.g. USD and USDJPY or EUR and EURUSD.

Best Regards,

Panagiotis 

Join us on Telegram

 

 


@rgasch

rgasch
13 May 2020, 12:48

RE:

Thank you such much for your help; I knew it must have been something 'stupid' ...

 


@rgasch

rgasch
12 May 2020, 16:47

RE:

Thank you for your reply. Please find attached a complete test case of a minimum reduced indicator and bot (the bot doesn't do anything useful, but it logs the test/evaluation of the color values the indicator fills). 

Indicator: 

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

namespace cAlgo.Indicators
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class TestIndicator : Indicator
    {

        private MovingAverage _ma;

        [Parameter("MA Period", DefaultValue = 34)]
        public int maPeriod { get; set; }

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

        [OutputAttribute("Moving Average", LineColor = "Red", LineStyle = LineStyle.Lines)]
        public IndicatorDataSeries MaResult { get; set; }

        public IndicatorDataSeries ColorData;



        protected override void Initialize()
        {
            _ma = Indicators.MovingAverage(Bars.ClosePrices, maPeriod, MAType);

            this.ColorData = CreateDataSeries();
        }


        public override void Calculate(int index)
        {
            var color = Color.White;
            var open = Bars.OpenPrices[index];
            var high = Bars.HighPrices[index];
            var low = Bars.LowPrices[index];
            var close = Bars.ClosePrices[index];

            var maValue = _ma.Result[index];
            MaResult[index] = maValue;

            ColorData[index] = open > close ? -1 : 1;
        }
    }
}

 

Bot

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 TestBot : Robot
    {

        [Parameter("MA Period", Group = "Main Moving Average", DefaultValue = 25)]
        public int __MAPeriod { get; set; }

        [Parameter("MA Type", Group = "Main Moving Average")]
        public MovingAverageType __MAType { get; set; }

        [Parameter("Source", Group = "Main Moving Average")]
        public DataSeries __SourceSeries { get; set; }

        private TestIndicator _MA;
        private string _label = "TestBot";


        protected override void OnStart()
        {
            this._MA = Indicators.GetIndicator<TestIndicator>(__MAPeriod, __MAType);
            this._label = "TestBot " + this.SymbolName + this.TimeFrame;
        }


        protected override void OnBar()
        {
            var maCurr = _MA.ColorData.Last(0);
            var maPrev = _MA.ColorData.Last(1);

            Print(_MA.ColorData);
            Print(maCurr);
            Print(maPrev);
            if (maCurr != maPrev)
            {
                // Do something useful here
            }
        }


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

 

Thank you for any insights. 

 

PanagiotisCharalampous said:

Hi rgasch,

To advise further we will need a workable version of the indicator that we can use.

Best Regards,

Panagiotis 

Join us on Telegram

 

 

 


@rgasch