Topics

Forum Topics not found

Replies

amusleh
19 May 2022, 09:29

Hi,

To use an indicator on a different time frame you have to first pass that time frame bars series as source to indicator and then use that time frame index values to access the indicator output values, here is an example for MACD:

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

namespace cAlgo
{
    [Indicator(AccessRights = AccessRights.None)]
    public class MACDMTF : Indicator
    {
        private MacdCrossOver _macd;
        private Bars _bars;

        [Parameter("Selected Time Frame")]
        public TimeFrame SelectedTimeFrame { get; set; }

        [Parameter("Long Cycle", DefaultValue = 26)]
        public int LongCycle { get; set; }

        [Parameter("Short Cycle", DefaultValue = 12)]
        public int ShortCycle { get; set; }

        [Parameter("Signal Periods", DefaultValue = 9)]
        public int SignalPeriods { get; set; }

        [Output("Histogram", LineColor = "Yellow", IsHistogram = true, PlotType = PlotType.Histogram, Thickness = 2)]
        public IndicatorDataSeries Histogram { get; set; }

        [Output("MACD", LineColor = "Blue", PlotType = PlotType.Line, Thickness = 1)]
        public IndicatorDataSeries MACD { get; set; }

        [Output("Signal", LineColor = "Red", PlotType = PlotType.Line, Thickness = 1)]
        public IndicatorDataSeries Signal { get; set; }

        protected override void Initialize()
        {
            _bars = MarketData.GetBars(SelectedTimeFrame);

            _macd = Indicators.MacdCrossOver(_bars.ClosePrices, LongCycle, ShortCycle, SignalPeriods);
        }

        public override void Calculate(int index)
        {
            var timeFrameIndex = _bars.OpenTimes.GetIndexByTime(Bars.OpenTimes[index]);

            Histogram[index] = _macd.Histogram[timeFrameIndex];
            MACD[index] = _macd.MACD[timeFrameIndex];
            Signal[index] = _macd.Signal[timeFrameIndex];
        }
    }
}

 


@amusleh

amusleh
19 May 2022, 08:35

Hi,

Please post a job request or contact one of our consultant companies.


@amusleh

amusleh
18 May 2022, 11:19

Hi,

Does it happen constantly? or only sometimes?

We tried to reproduce this but we were not able to, please provide below data so we will be able to reproduce this issue:

  • cBot code
  • cTrader Version
  • Back test period (start/end time), time frame, data source type
  • Broker name

@amusleh

amusleh
18 May 2022, 10:24

Hi,

It's a Visual studio extension, not related to cTrader at all.

I searched on Visual Studio market place for this extension and it looks like it's an old extension that only supports Visual Studio 2015.

There are alternatives for it: Search results - snippet | Visual Studio , Visual Studio Marketplace


@amusleh

amusleh
18 May 2022, 10:20

Hi,

After discussing this with our team we found that it's not a bug but the expected behavior, when you reverse a position platform opens an opposite direction position with double the volume of original position, if this doubled volume was larger than symbol maximum allowed volume then you will receive an error message and the operation will fail.

In your case as you are using Automate API, you can manually first close the position and then open a new position with same exact volume, this will avoid the issue you are facing.


@amusleh

amusleh
18 May 2022, 10:15

Hi,

Not sure what do you mean by support support asynchronous eventsevents, in your example you have to wait for 3rd event to happen then execute your logic.

Asynchronous means doing other things while waiting for the result of something that is already executed/happened.


@amusleh

amusleh
18 May 2022, 10:12

Hi,

Please read the Open API documentation "Account Authentication" page: Account Authentication - cTrader Open API (spotware.github.io)


@amusleh

amusleh
18 May 2022, 10:10

Hi,

You to check if there is enough room by using Symbol bid/ask price levels, I see you use Position pips property, be sure your TP is large enough.

And use Symbol.PipSize * x instead of 1 / 4.


@amusleh

amusleh
17 May 2022, 14:42 ( Updated at: 17 May 2022, 14:48 )

Hi,

It's because your order request volume is higher than symbol maximum allowed volume, in your case the reverse order request volume is 100 while the symbol maximum allowed volume is 50.

It's a bug, thanks for reporting.


@amusleh

amusleh
17 May 2022, 11:11

RE: RE:

ncel01 said:

amusleh said:

Hi,

A closed position is a deal/trade, you have to use either Positions.Closed event or History collection, the deal has both entry time and close time.

Hi amusleh,

Thanks for your reply. It's working now! ????

One more question:

Is there a way to filter out from History collection the partial close trades only?

Thank you!

Hi,

No, you can't filter historical trades by type of their close.


@amusleh

amusleh
17 May 2022, 11:08

Hi,

Server.Time and Server.TimeInUtc give you the back test time.


@amusleh

amusleh
16 May 2022, 14:23

Hi,

The warning message is there for notifying the user that the way h is using API is not correct, and the API calls should be made only from cBot/Indicator main thread not other threads.

For anyone who face same warning, we recommend you to use the BeginInvokeOnMainThread when you are using API members from other thread, that's the right way, otherwise you can face deadlocks or race condition.

Automate API is not thread safe, it should be only accessed via cBot/Indicator main thread, when you are using multiple threads dispatch the calls to API members to main cBot/Indicator thread for avoiding any inconsistency.

You can use decorator pattern, create a derived class from Robot or Indicator base classes, override all members to dispatch the calls to main thread by using BeginInvokeOnMainThread method.


@amusleh

amusleh
16 May 2022, 11:47

RE: RE: RE: RE: RE: Indicator data series from external data

bonedrak said:

The last part is what I’m wondering about. Using the data to populate an indicator data series. How do you do that. 

Hi,

Once you read the data from a file or any other source, deserialize it to appropriate types, then insert it on an indicator data series.

Use the bars open times GetIndexByTime method to find the appropriate index for each value of the data, the data must be time stamped.


@amusleh

amusleh
16 May 2022, 11:18

RE: RE: RE: Indicator data series from external data

bonedrak said:

amusleh said:

bonedrak said:

Hi xabbu

 

did you ever find a solution to this 

 

thanks

anthony 

 

 

Hi,

Solution for which issue? Reading CSV file?

For creating an indicator data series from external source, either csv or json. 
 

Thanks

anthony 

Hi,

You can easily do that by reading the file, de-serializing it to an object, and then using them to populate an indicator data series.

For reading files: How to read from a text file - C# Programming Guide | Microsoft Docs

For CSV files use CsvHelper: A .NET library for reading and writing CSV files. Extremely fast, flexible, and easy to use. | CsvHelper (joshclose.github.io)

For JSON use System.Text.Json (cTrader 4.2 >): How to serialize and deserialize JSON using C# - .NET | Microsoft Docs


@amusleh

amusleh
16 May 2022, 11:09

Hi,

For now there is no such feature in cTrader automate API, you can open a thread under suggestions section for this feature.


@amusleh

amusleh
16 May 2022, 10:44 ( Updated at: 16 May 2022, 10:45 )

Hi,

I'm not exactly sure what warning you are facing, this works fine for me:

using System;
using cAlgo.API;
using System.Threading;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
    public class WinFormsTest : Robot
    {
        protected override void OnStart()
        {
            try
            {
                var thread = new Thread(() => System.Windows.Forms.Application.Run(new TestForm(this)))
                {
                    IsBackground = true
                };

                thread.SetApartmentState(ApartmentState.STA);
                thread.Start();
            }
            catch (Exception ex)
            {
                Print(ex);
            }
        }

        protected override void OnStop()
        {
            System.Windows.Forms.Application.Exit();
        }
    }
}

Regarding some events not working properly, in version 4.2 any API call must be executed from the main cBot/Indicator thread, you can't call a cBot/Indicator method/property from another thread, dispatch the call to main thread by using BeginInvokeOnMainThread method.

Please read our new guide for WinForms: WinForms - cTrader Automate API Documentation (spotware.github.io)


@amusleh

amusleh
16 May 2022, 10:35

RE: Indicator data series from external data

bonedrak said:

Hi xabbu

 

did you ever find a solution to this 

 

thanks

anthony 

 

 

Hi,

Solution for which issue? Reading CSV file?


@amusleh

amusleh
16 May 2022, 10:30

Hi,

Try this:

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

        private AverageTrueRange atr;
        private IchimokuKinkoHyo ichimoku;
        private ExponentialMovingAverage slowMa;
        private ExponentialMovingAverage fastMa;
        private ExponentialMovingAverage mediumMa;
        private Position position;
        private int longPositions = 0;

        private int shortPositions = 0;

        [Parameter("Short Trades", DefaultValue = 2, MinValue = 0)]
        public int MaxShortTrades { get; set; }

        [Parameter("Long Trades", DefaultValue = 2, MinValue = 0)]
        public int MaxLongTrades { get; set; }

        protected override void OnStart()
        {
            // Load indicators on start up
            atr = Indicators.AverageTrueRange(20, MovingAverageType.Exponential);
            ichimoku = Indicators.IchimokuKinkoHyo(9, 26, 52);
            fastMa = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 20);
            mediumMa = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 50);
            slowMa = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 100);
        }

        protected override void OnBar()
        {
            if (Positions.FindAll("BOT").Any()) return;

            // Calculate Trade Amount based on ATR
            var PrevATR = Math.Round(atr.Result.Last(1) / Symbol.PipSize);
            var TradeAmount = (Account.Equity * 0.02) / (1.5 * PrevATR * Symbol.PipValue);
            TradeAmount = Symbol.NormalizeVolumeInUnits(TradeAmount, RoundingMode.Down);

            // EMA Crossovers and Ichimoku

            var ema_20 = fastMa.Result.Last(0);
            var ema_50 = mediumMa.Result.Last(0);
            var ema_100 = slowMa.Result.Last(0);
            var tenkan = ichimoku.TenkanSen;
            var kijun = ichimoku.KijunSen;
            var senkouA = ichimoku.SenkouSpanA;
            var senkouB = ichimoku.SenkouSpanB;
            var chikou = ichimoku.ChikouSpan;
            var cloudUpper = Math.Max(senkouA.Last(26), senkouB.Last(26));
            var cloudLower = Math.Min(senkouA.Last(26), senkouB.Last(26));
            var price = Bars.ClosePrices.Last(0);
            var shortPositionsCount = Positions.Count(p => p.TradeType == TradeType.Sell);
            var longPositionsCount = Positions.Count(p => p.TradeType == TradeType.Buy);

            if (longPositions < MaxLongTrades & ema_20 > ema_50 & ema_50 > ema_100 & price > cloudUpper)
            {
                ExecuteMarketOrder(TradeType.Buy, SymbolName, TradeAmount, "BOT", 1.5 * PrevATR, PrevATR);
            }
            else if (shortPositions < MaxShortTrades & ema_20 < ema_50 & ema_50 < ema_100 & price < cloudLower)
            {
                ExecuteMarketOrder(TradeType.Sell, SymbolName, TradeAmount, "BOT", 1.5 * PrevATR, PrevATR);
            }
        }

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

 


@amusleh

amusleh
16 May 2022, 10:22

RE: RE:

steel.export said:

Dear Mr. Ahmed,

Thanks for posting the above Sample cBot that can be used by Referencing an Indicator, and it opens a buy position on start of green line and a sell position on start of red line, it closes the buy position on start of red line and the sell position on start of green line.

Kindly also advice how to Add Parameters such as Volume/Lot Size,  ATR Period, and  ATR Multiplier to this cBot, if we are Referencing it with SuperTrend Indicator.

Thanks & Best Regards,

Altaf

Hi,

I recommend you to read the cTrader automate API user guide.


@amusleh

amusleh
16 May 2022, 10:20

Hi,

Try Ctrl button instead of Alt:

using cAlgo.API;

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class NewIndicator : Indicator
    {
        private ChartStaticText tx_Rsch;

        protected override void Initialize()
        {
            tx_Rsch = Chart.DrawStaticText("Debugging", "Start Debugging..", VerticalAlignment.Bottom, HorizontalAlignment.Center, Color.FromHex("AAEEDDCC"));
            Chart.MouseMove += Chart_MouseMove;
            Chart.MouseLeave += Chart_MouseLeave;
        }

        public override void Calculate(int index)
        {
        }

        private void Chart_MouseMove(ChartMouseEventArgs obj)
        {
            tx_Rsch.Text = obj.CtrlKey ? string.Format("X: {0}  Y: {1}", obj.MouseX, obj.MouseY) : string.Empty;
        }

        private void Chart_MouseLeave(ChartMouseEventArgs obj)
        {
            tx_Rsch.Text = string.Empty;
        }
    }
}

Alt pauses the indicator event loop until you click somewhere or press another keyboard key.


@amusleh