Topics

Forum Topics not found

Replies

amusleh
01 Nov 2021, 08:26

Hi,

Please read this tutorial: How to Calculate Margin for Forex Trades (valutrades.com)

You have to convert the required margin from symbol base currency to your account currency.

For CFDs you can't get the base currency with automate API, that's the problem, but for Forex the base currency is the first currency on symbol pair.


@amusleh

amusleh
01 Nov 2021, 08:20

Hi,

You can use try/catch to catch an exception and then do anything you want to.


@amusleh

amusleh
01 Nov 2021, 08:19

Hi,

Try this:

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class NewcBot : Robot
    {
        private ExponentialMovingAverage _ema;

        protected override void OnStart()
        {
            _ema = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 200);
        }

        protected override void OnBar()
        {
            if (Bars.ClosePrices.Last(1) > _ema.Result.Last(1))
            {
                // Buy
            }
            else if (Bars.ClosePrices.Last(1) < _ema.Result.Last(1))
            {
                // Sell
            }
        }
    }
}

 


@amusleh

amusleh
01 Nov 2021, 08:16

Hi,

Your questions is not clear at all, not just this one but also your other questions on your other threads.

Please stop spamming the forum and instead try to find a better way to explain your issue.


@amusleh

amusleh
29 Oct 2021, 08:55

Hi,

You can use Symbol VolumeInUnitsMin property to get minimum allowed volume in units for a symbol.


@amusleh

amusleh
29 Oct 2021, 08:52

Hi,

You can easily change Lots to Units, use Symo QuantityToVolumeInUnits method.


@amusleh

amusleh
29 Oct 2021, 08:50

Hi,

Please learn basics of C# before developing indicators/cBot.

For date and time you can use C# DateTime, DateTimeOffset, and TimeSpan types.

To get time from user via a parameter you can use string for parameter type and then parse it to any of the above mentioned types.


@amusleh

amusleh
27 Oct 2021, 11:56

Hi,

The original position ID is on the comment of opposite position, so you can match them by using the opposite position comment and the original position ID.

To get original position ID from opposite position you can split its comment with "_", the second value will be ID, then parse the ID with long.Parse and then you can compare it with original position ID for matching.

            foreach (var pos in positionsCopy)
            {
				// if position comment is empty then skip it
				if (string.IsNullOrWhiteSpace(pos.Comment)) continue;
				
				var commentSplit = pos.Comment.Split('_');
				
				if (commentSplit.Length < 2) continue;
				
				var originalPositionIdString = commentSplit[1];
				
				long originalPositionId;
				
				if (!long.TryParse(originalPositionIdString, out originalPositionId)) continue;
				
				var originalPosition = Positions.FirstOrDefault(position => position.Id == originalPositionId);
				
				if (originalPosition == null) continue;
				
				// Now you have the original position on originalPosition variable
            }

 


@amusleh

amusleh
27 Oct 2021, 08:30 ( Updated at: 27 Oct 2021, 08:31 )

Hi,

No, you can't get the angle from API, but you can calculate it if you want to:

        private double GetAngle(ChartTrendLine trendLine)
        {
            var x1 = Bars.OpenTimes.GetIndexByTime(trendLine.Time1);
            var x2= Bars.OpenTimes.GetIndexByTime(trendLine.Time2);

            double xDiff = x2 - x1;
            var yDiff = trendLine.Y2 - trendLine.Y1;

            return Math.Atan2(yDiff, xDiff) * 180.0 / Math.PI;
        }

The above method will return the angle of a trend line in Degree, it will not work properly if your trend line is drawn in future time, because it uses bar indices for x axis.

If you to get the angle from API then please open a thread on forum suggestions section.


@amusleh

amusleh
27 Oct 2021, 08:20

Hi,

The code I posted opens an opposite position for each of your bot positions based on given condition.

What do you mean by lots of positions? do you want to set a maximum position number?

If you can tell us what exactly you want to implement on your cBot then I will be able to help you.


@amusleh

amusleh
26 Oct 2021, 09:22 ( Updated at: 26 Oct 2021, 09:23 )

Hi,

Try this:

        private double GetMax(DateTime startTime, DateTime endTime)
        {
            var startBarIndex = Bars.OpenTimes.GetIndexByTime(startTime);
            var endBarIndex = Bars.OpenTimes.GetIndexByTime(endTime);

            var max = double.MinValue;

            for (var barIndex = startBarIndex; barIndex <= endBarIndex; barIndex++)
            {
                max = Math.Max(Bars.HighPrices[barIndex], max);
            }

            return max;
        }

        private double GetMin(DateTime startTime, DateTime endTime)
        {
            var startBarIndex = Bars.OpenTimes.GetIndexByTime(startTime);
            var endBarIndex = Bars.OpenTimes.GetIndexByTime(endTime);

            var min = double.MaxValue;

            for (var barIndex = startBarIndex; barIndex <= endBarIndex; barIndex++)
            {
                min = Math.Min(Bars.LowPrices[barIndex], min);
            }

            return min;
        }

This should work on all chart types as long as the data is available on your chart in between start and end time.


@amusleh

amusleh
26 Oct 2021, 09:15

Hi,

You should use OnTick not OnBar, and the issue with your code is that you are opening multiple opposite positions for a single position, try this:

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class NewcBot : Robot
    {
        protected override void OnTick()
        {
            CreateOpposite();
        }

        private void CreateOpposite()
        {
            var positionsCopy = Positions.ToArray();

            foreach (var pos in positionsCopy)
            {
                var comment = string.Format("Opposite_{0}", pos.Id);

                if (Positions.Any(position => string.Equals(position.Comment, comment, StringComparison.OrdinalIgnoreCase)))
                {
                    continue;
                }

                var sym = pos.SymbolName;
                var type = pos.TradeType;
                var cmd = pos.Comment;
                var ov = pos.VolumeInUnits;
                double atr = ATR[sym].Result.LastValue;

                if (type == TradeType.Buy && pos.Pips <= -5 * atr)
                {
                    ExecuteMarketOrder(TradeType.Sell, sym, ov, "EA", 0, 0, comment);
                }
                if (type == TradeType.Sell && pos.Pips <= -5 * atr)
                {
                    ExecuteMarketOrder(TradeType.Buy, sym, ov, "EA", 0, 0, comment);
                }
            }
        }
    }
}

I use comment to prevent opening multiple opposite positions for a single position, each position will have only one opposite position.


@amusleh

amusleh
25 Oct 2021, 12:56

RE: RE:

yuval.ein said:

I will but what is the meaning of error  number 62086147?

 

Hi,

Please submit troubleshoot report next time this error occurred with forum thread link.


@amusleh

amusleh
25 Oct 2021, 11:47

Hi,

No, you can't change the position label or comment once you set it.

If it was possible then you couldn't rely on it.


@amusleh

amusleh
25 Oct 2021, 09:53

Hi,

MarketSeries is obsolete, you should use Bars: cAlgo API Reference - Bars Interface (ctrader.com)

To get lowest price in last 20 bars you can use Bars.LowPrices.Minimum(20).


@amusleh

amusleh
25 Oct 2021, 09:51

RE: RE:

velu130486 said:

Hi Ahmad,

Thanks for your reply. Actually my request is to double the volume on every 4th position count not based on time.

Because sometimes my bot create more than 4 - 6 positions within a hour depends on moving average signal. So the volume is increased on each and every position which I would like to control it, so I would like to increase the volume only on 4,8,12,16 position for both buy and sell positions etc.,

Thanks and Regards

R. Vadivelan

amusleh said:

Hi,

You can use timer, set the interval to 4 hours and double the volume whenever the timer elapsed:

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.EasternStandardTime, AccessRights = AccessRights.None)]
    public class HighVolumeHours : Robot
    {
        private double _volume;

        protected override void OnStart()
        {
            // Here we set the initial volume to symbol minimum volume
            _volume = Symbol.VolumeInUnitsMin;

            // Here we start the timer and we set the interval to 4 hours
            Timer.Start(TimeSpan.FromHours(4));
        }

        protected override void OnTimer()
        {
            // double the volume whenever OnTimer is called
            _volume *= 2;

            // Stop the timer if we reached the symbol maximum volume
            if (_volume >= Symbol.VolumeInUnitsMax)
            {
                _volume = Symbol.VolumeInUnitsMax;

                Timer.Stop();
            }
        }
    }
}

 

 

Hi,

You can do that by using position label to differentiate your cBot positions from other positions, then use Positions collection to count the number of your cBot open positions.

Then you can multiply the number of positions to volume or any other number you want to, for example if your cBot had 4 open positions you can multiply the volume by 2.


@amusleh

amusleh
25 Oct 2021, 09:48

Hi,

Please create a suggestion for this and then our team will add the data series parameters.

And as I said on my previous post, you can easily develop a custom version of these indicators that will be able to get a data series parameter.


@amusleh

amusleh
25 Oct 2021, 09:45

Hi,

No, right now its not possible, you can't get your broker symbol categories from automate API.

You can open a thread on forum suggestions section for this feature.

If you want to categorize symbols by your self and then access the categories you can use watchlists from automate API.


@amusleh

amusleh
25 Oct 2021, 09:42

RE: RE: RE: RE:

yuval.ein said:

Hello

I have failed converting my code from a single to multi symbol. Perhaps you can attach a code sample of how you converted one of cTrader cBot samples (such as Sample Aligator, Sample Bears Power etc.) from single to multi symbol. An important note: The code must support running on a back test as well the same way (meaning one chart will run several symbols).

Thanks

 

Hi,

Here is the sample martingale cBot that works on two symbols, you must provide the symbol names:

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

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class SampleMartingalecBot : Robot
    {
        [Parameter("Initial Quantity (Lots)", Group = "Volume", DefaultValue = 1, MinValue = 0.01, Step = 0.01)]
        public double InitialQuantity { get; set; }

        [Parameter("Stop Loss", Group = "Protection", DefaultValue = 40)]
        public int StopLoss { get; set; }

        [Parameter("Take Profit", Group = "Protection", DefaultValue = 40)]
        public int TakeProfit { get; set; }

        [Parameter("First Symbol", Group = "Symbols")]
        public string FirstSymbolName { get; set; }

        [Parameter("Second Symbol", Group = "Symbols")]
        public string SecondSymbolName { get; set; }

        private Random random = new Random();

        protected override void OnStart()
        {
            Positions.Closed += OnPositionsClosed;

            var firstSymbol = Symbols.GetSymbol(FirstSymbolName);

            ExecuteOrder(InitialQuantity, firstSymbol, GetRandomTradeType());

            var secondSymbol = Symbols.GetSymbol(SecondSymbolName);

            ExecuteOrder(InitialQuantity, secondSymbol, GetRandomTradeType());
        }

        private void ExecuteOrder(double quantity, Symbol symbol, TradeType tradeType)
        {
            var volumeInUnits = symbol.QuantityToVolumeInUnits(quantity);
            var result = ExecuteMarketOrder(tradeType, symbol.Name, volumeInUnits, "Martingale", StopLoss, TakeProfit);

            if (result.Error == ErrorCode.NoMoney)
                Stop();
        }

        private void OnPositionsClosed(PositionClosedEventArgs args)
        {
            Print("Closed");

            var position = args.Position;

            if (position.Label != "Martingale") return;

            var symbol = Symbols.GetSymbol(args.Position.SymbolName);

            if (position.GrossProfit > 0)
            {
                ExecuteOrder(InitialQuantity, symbol, GetRandomTradeType());
            }
            else
            {
                ExecuteOrder(position.Quantity * 2, symbol, position.TradeType);
            }
        }

        private TradeType GetRandomTradeType()
        {
            return random.Next(2) == 0 ? TradeType.Buy : TradeType.Sell;
        }
    }
}

 


@amusleh

amusleh
22 Oct 2021, 09:25

Hi,

We can't give you any ETA for now.


@amusleh