Replies

lukaszpe
21 Jun 2024, 17:24 ( Updated at: 26 Jun 2024, 05:46 )

RE: Bug: Why is core useage for optimization limited to 64 cores only?

Hi PanagiotisCharalampous,

same here. I rented a 96-Core machine to optimise an algorithm and here I have a usage of ⅓ of the cores. I am able to run 3 instances of CTrader with optimisation running, every instance tests 31 combinations…

Troubleshooting has been submitted.

Best,
Lukasz

PanagiotisCharalampous said: 

Hi Heinrich,

Thanks for reporting this. Could you please send us some troubleshooting information the next time this happens? Please paste a link to this discussion inside the text box before you submit it.

Best regards,


 

 


@lukaszpe

lukaszpe
04 Jun 2024, 07:27

RE: Programatically bring chart which generated pop-up window to front

PanagiotisCharalampous said: 

Hi Lukasz,

Can you please share the complete indicator code and instructions how to reproduce this behavior?

Best regards,

Panagiotis

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

namespace cAlgo
{
    [Cloud(topBand, bottomBand)]
    [Cloud(ClosePriceLine, OpenPriceLine, Opacity = 0.4)]
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class Advanced_Signal_Line : Indicator
    {
        public const string ClosePriceLine = "Close Price", OpenPriceLine = "Open Price",
        topBand = "Top Band", bottomBand = "Bottom Band";

        public enum priceType
        {
            Open,
            High,
            Low,
            Close,
            OC2,
            HL2,
            HLC3,
            OHLC4
        }
        public enum signalType
        {

            Open,
            High,
            Low,
            Close,
            OC2,
            HL2,
            HLC3,
            HLCC4,
            OHLC4,
            HeikenAshiOpen,
            HeikenAshiOC2
        }
        private double priceData(priceType reqPrice, int i)
        {
            var o = Bars.OpenPrices[i];
            var h = Bars.HighPrices[i];
            var l = Bars.LowPrices[i];
            var c = Bars.ClosePrices[i];
            switch (reqPrice)
            {
                case priceType.Open:
                    return o;
                case priceType.High:
                    return h;
                case priceType.Low:
                    return l;
                case priceType.Close:
                    return c;
                case priceType.OC2:
                    return (o + c) / 2.0;
                case priceType.HL2:
                    return (h + l) / 2.0;
                case priceType.HLC3:
                    return (h + l + c) / 3.0;
                case priceType.OHLC4:
                    return (o + h + l + c) / 4.0;
                default:
                    return c;
            }
        }
        private double signalLine(signalType st, int i)
        {
            var o = Bars.OpenPrices[i];
            var h = Bars.HighPrices[i];
            var l = Bars.LowPrices[i];
            var c = Bars.ClosePrices[i];
            switch (st)
            {
                case signalType.Open:
                    return o;
                case signalType.High:
                    return h;
                case signalType.Low:
                    return l;
                case signalType.Close:
                    return c;
                case signalType.OC2:
                    return (o + c) / 2.0;
                case signalType.HL2:
                    return (h + l) / 2.0;
                case signalType.HLC3:
                    return (h + l + c) / 3.0;
                case signalType.HLCC4:
                    return (h + l + c + c) / 4.0;
                case signalType.OHLC4:
                    return (o + h + l + c) / 4.0;
                case signalType.HeikenAshiOpen:
                    if (i > 0)
                        return (signalLine(signalType.HeikenAshiOpen, i - 1) + signalLine(signalType.OHLC4, i - 1)) / 2;
                    else
                        return priceData(priceType.OC2, i);
                case signalType.HeikenAshiOC2:
                    return (signalLine(signalType.HeikenAshiOpen, i) + signalLine(signalType.OHLC4, i)) / 2;
                default:
                    return c;
            }
        }
        public enum SigSrc
        {
            Middle,
            Middle_To_Bands,
            Bands,
            Mirrored_Bands,
            Band_without_neutral
        }

        [Parameter("Price source for MA Calculation", DefaultValue = priceType.Close, Group = "MA and ATR")]
        public priceType src { get; set; }

        [Parameter("MA Type", DefaultValue = MovingAverageType.WilderSmoothing, Group = "MA and ATR")]
        public MovingAverageType maType { get; set; }

        [Parameter("MA and ATR Period", DefaultValue = 30, MinValue = 1, Group = "MA and ATR")]
        public int maPeriod { get; set; }

        [Parameter("Use Hurst channel", DefaultValue = true, Group = "MA and ATR")]
        public bool maUseHurst { get; set; }

        [Parameter("ATR from MA offset Multiplier", DefaultValue = 2.0, MinValue = 0, Group = "MA and ATR")]
        public double maMultiplier { get; set; }

        [Parameter("Schow standard deviation lines", DefaultValue = true, Group = "MA and ATR")]
        public bool stDevLinesShow { get; set; }

        [Parameter("Standard deviation from MA offset Multiplier", DefaultValue = 2.0, MinValue = 0, Group = "MA and ATR")]
        public double stDevMultiplier { get; set; }

        [Parameter("Draw Heiken Ashi cloud", DefaultValue = false, Group = "Signal")]
        public bool haCloudDraw { get; set; }

        [Parameter("Signal line source", DefaultValue = signalType.Close, Group = "Signal")]
        public signalType haSigType { get; set; }

        [Parameter("Use MA on Signal", DefaultValue = false, Group = "Signal")]
        public bool sigMAUse { get; set; }

        [Parameter("Signal MA Type", DefaultValue = MovingAverageType.WilderSmoothing, Group = "Signal")]
        public MovingAverageType sigMAType { get; set; }

        [Parameter("Signal MA Period", DefaultValue = 30, MinValue = 1, Group = "Signal")]
        public int sigMAPeriod { get; set; }

        [Parameter("Signal boundary", DefaultValue = SigSrc.Middle, Group = "Signal")]
        public SigSrc haSigBoundary { get; set; }
        //MA Outputs
        [Output("StDev +", LineColor = "Yellow", Thickness = 1, LineStyle = LineStyle.Dots)]
        public IndicatorDataSeries stDevTop { get; set; }

        [Output(topBand, LineColor = "White", Thickness = 2)]
        public IndicatorDataSeries maTop { get; set; }

        [Output("Middle", LineColor = "White", Thickness = 1, LineStyle = LineStyle.LinesDots)]
        public IndicatorDataSeries maMiddle { get; set; }

        [Output(bottomBand, LineColor = "White", Thickness = 2)]
        public IndicatorDataSeries maBottom { get; set; }

        [Output("StDev -", LineColor = "Yellow", Thickness = 1, LineStyle = LineStyle.Dots)]
        public IndicatorDataSeries stDevBottom { get; set; }

        // Heikin Ashi outputs
        [Output(ClosePriceLine, LineColor = "Yellow", Thickness = 1)]
        public IndicatorDataSeries closePrice { get; set; }

        [Output("Average Heikin Ashi Price line", LineColor = "White", Thickness = 1, LineStyle = LineStyle.LinesDots)]
        public IndicatorDataSeries avgPrice { get; set; }

        [Output("Long signal", LineColor = "Lime", Thickness = 2, PlotType = PlotType.DiscontinuousLine)]
        public IndicatorDataSeries lngSig { get; set; }

        [Output("Short signal", LineColor = "Red", Thickness = 2, PlotType = PlotType.DiscontinuousLine)]
        public IndicatorDataSeries shrtSig { get; set; }

        [Output(OpenPriceLine, LineColor = "Aqua", Thickness = 1)]
        public IndicatorDataSeries openPrice { get; set; }

        private double stDevFcn(int i, int clcPeriod, ref IndicatorDataSeries price, double average)
        {
            var sum = 0.0;
            for (var period = 0; period < clcPeriod; period++)
                sum += Math.Pow(price[i - period] - average, 2.0);

            return Math.Sqrt(sum / clcPeriod);
        }

        private AverageTrueRange _atr;
        private IndicatorDataSeries _open, _close, _price, _sigLin;
        private MovingAverage _ma, _sigMA;
        private StandardDeviation _stDevFcn;

        private int _Per2, _Per4, haComparePeriod = 1, _barIndex = 0;
        private bool _lng, _shrt;
        protected override void Initialize()
        {
            _open = CreateDataSeries();
            _close = CreateDataSeries();
            _price = CreateDataSeries();
            _sigLin = CreateDataSeries();
            _Per2 = Convert.ToInt32(maPeriod / 2);
            _Per4 = Convert.ToInt32(maPeriod / 4);
            if (maUseHurst)
            {
                _atr = Indicators.AverageTrueRange(_Per2, maType);
                _ma = Indicators.MovingAverage(_price, _Per2, maType);
            }
            else
            {
                _atr = Indicators.AverageTrueRange(maPeriod, maType);
                _ma = Indicators.MovingAverage(_price, maPeriod, maType);
            }
            if (sigMAUse)
                _sigMA = Indicators.MovingAverage(_sigLin, sigMAPeriod, sigMAType);

            if (stDevLinesShow)
                _stDevFcn = Indicators.StandardDeviation(maMiddle, maPeriod, maType);

            _lng = false;
            _shrt = false;
        }

        TimeSpan _maxDiff = new TimeSpan(30000000);
        private void markLong(int i)
        {

            if (Double.IsNaN(lngSig[i - 1]) && _barIndex != i && IsLastBar)// && ((Server.Time - Bars.Last(0).OpenTime) < _maxDiff))
            {
                _barIndex = i;
                var _mbox = MessageBox.Show(DateTime.Now.TimeOfDay.ToString().Substring(0,8) + "\n" + "Long\n" + Chart.SymbolName, "Long mode on " + Chart.SymbolName, MessageBoxButton.OK, MessageBoxImage.Information), MessageBoxResult.OK);
                Print(_mbox);
                if (_mbox == MessageBoxResult.OK)
                   Chart.TryChangeTimeFrameAndSymbol(Chart.TimeFrame,Chart.SymbolName);
            }
            if (Double.IsNaN(lngSig[i - 1]))
                lngSig[i - 1] = avgPrice[i - 1];
            lngSig[i] = avgPrice[i];
            _lng = true;
            _shrt = false;

        }
        private void markShort(int i)
        {
            if (Double.IsNaN(shrtSig[i - 1]) && _barIndex != i && IsLastBar)// && ((Server.Time - Bars.Last(0).OpenTime) < _maxDiff))
            {
                _barIndex = i;
                var _mbox = MessageBox.Show(DateTime.Now.TimeOfDay.ToString().Substring(0,8) + "\n" + "Short\n" + Chart.SymbolName, "Short mode on " + Chart.SymbolName, MessageBoxButton.OK, MessageBoxImage.Information), MessageBoxResult.OK);
                Print(_mbox);
                if (_mbox == MessageBoxResult.OK)
                   Chart.TryChangeTimeFrameAndSymbol(Chart.TimeFrame,Chart.SymbolName);
            }
            if (Double.IsNaN(shrtSig[i - 1]))
                shrtSig[i - 1] = avgPrice[i - 1];
            shrtSig[i] = avgPrice[i];
            _lng = false;
            _shrt = true;
        }
        private void unmarkLong(int i)
        {
            lngSig[i] = Double.NaN;
            _lng = false;
        }
        private void unmarkShort(int i)
        {
            shrtSig[i] = Double.NaN;
            _shrt = false;
        }
        public override void Calculate(int i)
        {
            _price[i] = priceData(src, i);
            _sigLin[i] = signalLine(haSigType, i);
            lngSig[i] = Double.NaN;
            shrtSig[i] = Double.NaN;
            if (maUseHurst)
            {
                double ma = _ma.Result[i - _Per4];
                if (double.IsNaN(ma))
                    ma = _price[i];

                maTop[i] = ma + maMultiplier * _atr.Result[i];
                maBottom[i] = ma - maMultiplier * _atr.Result[i];
                maMiddle[i] = (maTop[i] + maBottom[i]) / 2.0;
            }
            else
            {
                maMiddle[i] = _ma.Result[i];
                maTop[i] = maMiddle[i] + maMultiplier * _atr.Result[i];
                maBottom[i] = maMiddle[i] - maMultiplier * _atr.Result[i];
            }
            if (stDevLinesShow)
            {
                stDevTop[i] = maMiddle[i] + stDevMultiplier * stDevFcn(i, maPeriod, ref _price, maMiddle[i]);
                stDevBottom[i] = maMiddle[i] - stDevMultiplier * stDevFcn(i, maPeriod, ref _price, maMiddle[i]);
            }
            //Heikin Ashi
            if (haCloudDraw)
            {
                openPrice[i] = signalLine(signalType.HeikenAshiOpen, i);
                closePrice[i] = signalLine(signalType.OHLC4, i);
            }
            if (sigMAUse)
                avgPrice[i] = _sigMA.Result[i];
            else
                avgPrice[i] = _sigLin[i];


            switch (haSigBoundary)
            {
                case SigSrc.Middle:
                default:
                    if (avgPrice[i] > maMiddle[i])
                    {
                        markLong(i);
                    }
                    if (avgPrice[i] < maMiddle[i])
                    {
                        markShort(i);
                    }
                    break;
                case SigSrc.Bands:
                    if ((avgPrice[i] > maBottom[i] && avgPrice[i - 1] < maBottom[i - 1]) || _lng)
                    {
                        markLong(i);
                    }
                    if ((avgPrice[i] < maTop[i] && avgPrice[i - 1] > maTop[i - 1]) || _shrt)
                    {
                        markShort(i);
                    }
                    if ((avgPrice[i] < maBottom[i] && avgPrice[i - 1] > maBottom[i - 1]) && _lng)
                        unmarkLong(i);
                    if ((avgPrice[i] > maTop[i] && avgPrice[i - 1] < maTop[i - 1]) && _shrt)
                        unmarkShort(i);
                    break;
                case SigSrc.Mirrored_Bands:
                    if ((avgPrice[i] > maTop[i] && avgPrice[i - 1] < maTop[i - 1]) || _lng)
                    {
                        markLong(i);
                    }
                    if ((avgPrice[i] < maBottom[i] && avgPrice[i - 1] > maBottom[i - 1]) || _shrt)
                    {
                        markShort(i);
                    }
                    if ((avgPrice[i] < maTop[i] && avgPrice[i - 1] > maTop[i - 1]) && _lng)
                        unmarkLong(i);
                    if ((avgPrice[i] > maBottom[i] && avgPrice[i - 1] < maBottom[i - 1]) && _shrt)
                        unmarkShort(i);
                    break;
                case SigSrc.Middle_To_Bands:
                    if ((avgPrice[i] > maMiddle[i] && avgPrice[i - 1] < maMiddle[i - 1]) || _lng)
                    {
                        markLong(i);
                    }
                    if ((avgPrice[i] < maMiddle[i] && avgPrice[i - 1] > maMiddle[i - 1]) || _shrt)
                    {
                        markShort(i);
                    }
                    if ((avgPrice[i] < maTop[i] && avgPrice[i - 1] > maTop[i - 1]) && _lng)
                        unmarkLong(i);
                    if ((avgPrice[i] > maBottom[i] && avgPrice[i - 1] < maBottom[i - 1]) && _shrt)
                        unmarkShort(i);
                    break;
                case SigSrc.Band_without_neutral:
                    if ((avgPrice[i] > maBottom[i] && avgPrice[i - 1] < maBottom[i - 1]) || _lng)
                    {
                        markLong(i);
                    }
                    if ((avgPrice[i] < maTop[i] && avgPrice[i - 1] > maTop[i - 1]) || _shrt)
                    {
                        markShort(i);
                    }
                    break;
            }
        }

    }

}

how the signals are generated is dealt with inside of switch (haSigBoundary) and the functions:

private void markLong(int i)
        {

            if (Double.IsNaN(lngSig[i - 1]) && _barIndex != i && IsLastBar)// && ((Server.Time - Bars.Last(0).OpenTime) < _maxDiff))
            {
                _barIndex = i;
                var _mbox = MessageBox.Show(DateTime.Now.TimeOfDay.ToString().Substring(0,8) + "\n" + "Long\n" + Chart.SymbolName, "Long mode on " + Chart.SymbolName, MessageBoxButton.OK, MessageBoxImage.Information), MessageBoxResult.OK);
                Print(_mbox);
                if (_mbox == MessageBoxResult.OK)
                    Chart.TryChangeTimeFrameAndSymbol(Chart.TimeFrame,Chart.SymbolName);
            }
            if (Double.IsNaN(lngSig[i - 1]))
                lngSig[i - 1] = avgPrice[i - 1];
            lngSig[i] = avgPrice[i];
            _lng = true;
            _shrt = false;

        }
        private void markShort(int i)
        {
            if (Double.IsNaN(shrtSig[i - 1]) && _barIndex != i && IsLastBar)// && ((Server.Time - Bars.Last(0).OpenTime) < _maxDiff))
            {
                _barIndex = i;
                var _mbox = MessageBox.Show(DateTime.Now.TimeOfDay.ToString().Substring(0,8) + "\n" + "Short\n" + Chart.SymbolName, "Short mode on " + Chart.SymbolName, MessageBoxButton.OK, MessageBoxImage.Information), MessageBoxResult.OK);
                Print(_mbox);
                if (_mbox == MessageBoxResult.OK)
                   Chart.TryChangeTimeFrameAndSymbol(Chart.TimeFrame,Chart.SymbolName);
            }
            if (Double.IsNaN(shrtSig[i - 1]))
                shrtSig[i - 1] = avgPrice[i - 1];
            shrtSig[i] = avgPrice[i];
            _lng = false;
            _shrt = true;
        }

are respoonsible for coloring the signal line.

To reproduce:

  1. Attach indicator to multiple charts in the same program window (best will be with small time frame like 1minute or even 10 - 20 ticks, depending on volatility)
  2. Wait for crossing of signal line with channel middle (with default settings)
  3.  The messagebox should come. Click ok.

After clicking ok I expect to be taken to the chart that generate the signal in the box. I couldn't find any function in CTrader's help that would what I am asking for.


@lukaszpe

lukaszpe
29 May 2024, 17:09 ( Updated at: 30 May 2024, 05:39 )

RE: CTrader responsivity

PanagiotisCharalampous said: 

Dear traders,

Thank you for reporting this issue. Could you please send us some troubleshooting information when this happens? Please paste a link to this discussion inside the text box before you submit it.

Best regards,

Panagiotis


 

Hello PanagiotisCharalampous!

I have sent two reports.

For testing purposes I have ran MT5 with same custom indicators as cTrader and must say, that the lag of cTrader is very big. On m1 chart (MT5 doeas not have tick charts)  delay after timeframe change was about 20 seconds. Next 30 -40 seconds have passed till the indicators were visible again.

 

One more thing - I've managed to download cTrader 4.1, but I am unable to login due to suspended broker. How to get around that?

Best regards,
Łukasz


@lukaszpe

lukaszpe
17 May 2024, 05:53 ( Updated at: 17 May 2024, 06:26 )

Porting to Linux

First - I am not a programmer, just linux fan and user.

Only because of CTrader I had to abandon Linux.

Then, as far as I know, .NET is multiplatform, so porting should be feasible.

Then there is problem of WPF - I know it's windows only, but maybe, just maybe, an interface written using QT or wxWidgets would be some middle ground and would then ensure portability without too much hassle :)

 

Edit:
Maybe DEVs find this interesting:
https://ccifra.github.io/PortingWPFAppsToLinux/Overview.html


@lukaszpe