Topics

Forum Topics not found

Replies

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

amusleh
16 May 2022, 09:59

RE: Can't establish new connection with old proxies

budda_dan2020 said:

Hi Amusleh,

we've got same problem. 

already established connections are still working, but we tried to restart the app and couldn't connection wit old proxy address.

Is it not better for clients that you enable to establish new connection with OLD and new proxies?

Because we have 20 apps and to change all these apps make us not really happy.

Some apps are working with real money and hundreds followers are copying our accounts.

Kind regards

Hi,

We will update you when the issue resolved, our previous proxies should work fine for now once the issue has been resolved.


@amusleh

amusleh
16 May 2022, 09:57 ( Updated at: 16 May 2022, 09:58 )

Hi,

There are several issues on your code, and you have to remember that Fractals are lagging indicator, and you have to access it's x previous values based on the period to passed to it.

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
    {
        private double _volumeInUnits;
        private Fractals _fractals;
        private SimpleMovingAverage _sma;

        [Parameter(DefaultValue = 20)]
        public int Period { get; set; }

        [Parameter("Source")]
        public DataSeries Source { get; set; }

        [Parameter("Volume (Lots)", DefaultValue = 0.5)]
        public double VolumeInLots { get; set; }

        [Parameter("Stop Loss (Pips)", DefaultValue = 20)]
        public double StopLossInPips { get; set; }

        [Parameter("Take Profit (Pips)", DefaultValue = 60)]
        public double TakeProfitInPips { get; set; }

        [Parameter("Label", DefaultValue = "Sample")]
        public string Label { get; set; }

        private Position[] BotPositions
        {
            get { return Positions.FindAll(Label); }
        }

        protected override void OnStart()
        {
            _sma = Indicators.SimpleMovingAverage(Source, Period);
            _volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots);
            _fractals = Indicators.Fractals(5);
        }

        protected override void OnBar()
        {
            double close = Bars.ClosePrices.Last(1);

            double sma = _sma.Result.Last(1);

            double upfr = _fractals.UpFractal.Last(5);
            double dwfr = _fractals.DownFractal.Last(5);

            if (upfr < close)
            {
                ClosePositions(TradeType.Sell);

                if (sma < close && Positions.Count == 0)
                {
                    ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips);
                }
            }
            else if (dwfr > close)
            {
                ClosePositions(TradeType.Buy);

                if (sma > close && Positions.Count == 0)
                {
                    ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips);
                }
            }
        }

        private void ClosePositions(TradeType tradeType)
        {
            foreach (var position in BotPositions)
            {
                if (position.TradeType != tradeType)
                    continue;
                ClosePosition(position);
            }
        }
    }
}

 


@amusleh

amusleh
16 May 2022, 09:36

Hi,

The index is the current chart bars index, not the index of time frame that you loaded.

You have to change the index to the loaded time frame bars index first then use it, try this:

using cAlgo.API;

namespace cAlgo
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None, TimeZone = TimeZones.EAfricaStandardTime)]
    public class Spring : Indicator
    {
        [Output("Up Fractal", Color = Colors.Red, PlotType = PlotType.Points, Thickness = 5)]
        public IndicatorDataSeries UpFractal { get; set; }

        [Output("Down Fractal", Color = Colors.Blue, PlotType = PlotType.Points, Thickness = 5)]
        public IndicatorDataSeries DownFractal { get; set; }

        private Bars HSeries;

        protected override void Initialize()
        {
            HSeries = MarketData.GetBars(TimeFrame.Hour4);
        }

        public override void Calculate(int index)
        {
            if (index == 1)
                return;

            DrawUpFractal(index);
            DrawDownFractal(index);
        }

        private void DrawUpFractal(int index)
        {
            var hSeriesIndex = HSeries.OpenTimes.GetIndexByTime(Bars.OpenTimes[index]);

            int middleIndex = hSeriesIndex - 2;
            double middleValue = HSeries.ClosePrices[middleIndex];

            bool up = false;

            for (int i = 1; i < HSeries.ClosePrices.Count - 1; i++)
            {
                if (HSeries.ClosePrices[middleIndex] > HSeries.ClosePrices[middleIndex - 1] && HSeries.ClosePrices[middleIndex] > HSeries.ClosePrices[middleIndex + 1])
                {
                    up = true;
                    break;
                }
            }

            if (up)
                UpFractal[index] = middleValue;
        }

        private void DrawDownFractal(int index)
        {
            var hSeriesIndex = HSeries.OpenTimes.GetIndexByTime(Bars.OpenTimes[index]);

            int middleIndex = hSeriesIndex - 2;
            double middleValue = HSeries.ClosePrices[middleIndex];
            bool down = false;

            for (int i = 1; i < HSeries.ClosePrices.Count - 1; i++)
            {
                if (HSeries.ClosePrices[middleIndex] < HSeries.ClosePrices[middleIndex - 1] && HSeries.ClosePrices[middleIndex] < HSeries.ClosePrices[middleIndex + 1])
                {
                    down = true;
                    break;
                }
            }
            if (down)
                DownFractal[index] = middleValue;
        }
    }
}

 


@amusleh