Topics

Forum Topics not found

Replies

amusleh
01 Feb 2022, 07:47

Hi,

Copying a cBot doesn't give you any benefit at all, each running instance of a cBot runs fully separated from all other cBots running instances.


@amusleh

amusleh
31 Jan 2022, 12:55 ( Updated at: 31 Jan 2022, 12:57 )

RE:

kemenist said:

Yes exactly, those we're methods and classes I've been trying to use, it's just that I can't seem to get the ByteString payload to be correctly formatted.

Do you have any tips to get me on the right path? I'm thinking there would need to be some sort of StreamWriter involved?

Thanks!

Hi,

All Google Protobuf .NET objects implement the IMessage interface, which has a ToByteString method, please check the MessageFactory class code.

OpenAPI.NET OpenClient has several overloads of SendMessage method, please check each and use the one that you want to based on your condition.


@amusleh

amusleh
31 Jan 2022, 12:45 ( Updated at: 31 Jan 2022, 12:46 )

Hi,

Open API uses the cTrader's proxy cloud, for more please check: https://spotware.github.io/open-api-docs/protocol-buffers/#endpoints

And: cTrader Proxy Cloud | Solving Last Mile Latency | Spotware Systems Ltd


@amusleh

amusleh
31 Jan 2022, 12:42

Hi,

If you are using OpenAPI.NET then you can use the SendMessage method overload that gets a ProtoMessage: OpenAPI.Net/OpenClient.cs at c39e7c973089a8e13ba00390a4fb2316c4efa8b8 · spotware/OpenAPI.Net (github.com)

There is also the MessageFactory static helper class that you can use: OpenAPI.Net/MessageFactory.cs at c39e7c973089a8e13ba00390a4fb2316c4efa8b8 · spotware/OpenAPI.Net (github.com)


@amusleh

amusleh
31 Jan 2022, 12:38

RE: RE: RE:

SummerSalt said:

Hello

When, I try to use the ClosePosition(positionToClose, volumeAmountInUnits) to close positions, the positions close at the wrong pip levels. I have tried many different combinations involving modfying the entryprice and stoploss which resulted in the right quantity (the percentage of the position that I want to close) of the position being closed but the the pip levels are always wrong. Moreover, the SecondCloseLevel  always closes at the same pip level as the FirstCloseLevel (Which is wrong as well).

E.g: 

 protected override void OnTick()
        {
           CloseLevels();
        }

        private void CloseLevels()
        {
            foreach (var position in Positions)
            {
                if (position.Label == InstanceName)
                {
                    if (position.Pips >= FirstLevelClosePips)
                    {
                        ClosePosition(position, FirstLevelCloseAmountInPercentage);
                    }

                    if (position.Pips >= SecondLevelClosePips)
                    {
                        ClosePosition(position, SecondLevelClosePips);
                    }

                }
            }

        }

 

Thanks for your time.

Hi,

Did you tested the code I posted? or your own code?

The ClosePosition method closes your position whenever you call it, so if the number of Pips aren't correct then the code for checking the position Pips has some issue not the ClosePosition method.


@amusleh

amusleh
31 Jan 2022, 09:47

RE: RE:

firemyst said:

amusleh said:

Hi,

No, you can't, there is no way to re-initialize an indicator programmatically.

Please create a thread under suggestions section for this feature if you want to.

THanks amusleh ,

Just to confirm because maybe we're using different terms, I don't want to reinitialize the indicator per-se -- I just want to be able to display the indicator settings window programmatically. The user could close it without changing anything.

I don't think re-initializing occurs unless a user actually changes a parameter or setting in the pop-up config window before closing it or clicking "okay"?

 

Hi,

Sorry, you are right, the indicator is re-initialized only if user change some parameters or load more historical data.

Regarding showing the parameters window programmatically, there is no way to do it right now.


@amusleh

amusleh
31 Jan 2022, 08:13

Hi,

I just tested on an IC Market demo account quote session, it works fine.

We don't ban users, maybe you made several sessions at the same time, that's why your sessions gets disconnected because only one active sessions is allowed.


@amusleh

amusleh
31 Jan 2022, 08:07

Hi,

There is a minimum stop loss and take profit distance for each symbol, please the symbol model docs: https://spotware.github.io/open-api-docs/models/#protooasymbol

If the stop loss distance is less that that minimum distance then the stop loss placement will fail, you have to check those properties of symbols before placing a stop loss or take profit.


@amusleh

amusleh
31 Jan 2022, 08:04 ( Updated at: 21 Dec 2023, 09:22 )

RE: RE:

TheNiatpac said:

Hi Musleh,

I've just tested the code. Please advise.

 

Hi,

There is no such issue on my posted code, most probably you made some changes on it, the error says that the variable "icon" does not exist.

 


@amusleh

amusleh
31 Jan 2022, 08:01

Hi,

No, you can't, there is no way to re-initialize an indicator programmatically.

Please create a thread under suggestions section for this feature if you want to.


@amusleh

amusleh
31 Jan 2022, 07:59

RE: RE: RE: Refer price/indicator values on different Range chart

Marin0ss said:

Thanks! Got me further. I can now get the values from a custom Indicator; but I can't seem to refer to a different RangeBar chart with the standard build in Indicators (for e.g. Supertrend).

Could you help me out a bit here?

So, the DSS values I get back correct; ST values are from the TF the Bot is running on; so that is also fine.

But When I add Ra500 to the ST500 line, like below, it fails and mentioned an overload as only wants to see 2 arguments.

ST500 = Indicators.Supertrend(Ra500, 10, 3.0);

(If I change the indicator to for example a Moving Average like: ST500 = Indicators.MovingAverage(Ra500.ClosePrices, 10, MovingAverageType.Exponential);, no error messages displayed. So seems issue with Supertrend, or I misconfigure it..)

I also got it working if I download the custom Supertrend indicator that can be found in the Algorithms section, but I rather use the standard one located in cTrader.

Ps. I add the code to OnStart, so I can test this in the weekend, as we cannot Backtest RangeBar data..

Thanks in advance!

//#reference: ..\Indicators\DSS Bressert.algo
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 RangeBarMTFtest : Robot
    {
        private DSSBressert DSS;

        private Supertrend ST;
        private Supertrend ST500;

        private Bars Ra500;

        protected override void OnStart()
        {
            Ra500 = MarketData.GetBars(TimeFrame.Range500);

            DSS = Indicators.GetIndicator<DSSBressert>(Ra500, 13, 8, 8);

            ST = Indicators.Supertrend(10, 3.0);

            ST500 = Indicators.Supertrend(Ra500, 10, 3.0);

 

Hi,

The built-in super trend indicator doesn't support multiple time frames, you can only use if for the current time frame.

If you want to use super trend on another time frame then you have to develop a custom version by yourself, you can find some examples on site if you search.


@amusleh

amusleh
28 Jan 2022, 12:05

RE: RE:

firemyst said:

Thanks amusleh ,

1) but that means we have what -- a total of 9 locations we can put controls on using the Horizontal/Vertical align parameters? Eg, Halign left valign top; halign right valign middle; etc etc.

2) Otherwise, when you say, "allow user change the location of controls by using indicator/cBot parameters", how do you mean? What parameters would you suggest? The Horizonal/Vertical align as in #1 above? Or something else?

3) And I noticed there appears to be no way to query the chart to see what controls are on the chart like we can query to find what "chart objects" are on the chart?

 

 

Hi,

1. No, you can use grids or any other panels, like canvas.

2. Yes, I mean the alignment properties.

3. For now there is no way to query chart controls, you can only add or remove them.

 You can open a thread under suggestions section for your point #3 if you want to.


@amusleh

amusleh
28 Jan 2022, 12:02

Hi,

Here is a multi symbol example:

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class PartialCloseSample : Robot
    {
        private double _initialEquity;

        [Parameter("Equity Increase Amount", DefaultValue = 100)]
        public double EquityIncreaseAmount { get; set; }

        protected override void OnStart()
        {
            _initialEquity = Account.Equity;

            foreach (var group in Positions.GroupBy(position => position.SymbolName))
            {
                var positionSymbol = Symbols.GetSymbol(group.Key);

                positionSymbol.Tick -= PositionSymbol_Tick;
            }

            Positions.Opened += Positions_Opened;
            Positions.Closed += Positions_Closed;
        }

        private void Positions_Closed(PositionClosedEventArgs obj)
        {
            // If there are other positions from same symbol then don't remove the symbol Tick event handler
            if (Positions.Any(position => position.SymbolName.Equals(obj.Position.SymbolName, StringComparison.Ordinal)))
            {
                return;
            }

            // If there is no other position from the closed position symbol then remove the Tick event handler
            var positionSymbol = Symbols.GetSymbol(obj.Position.SymbolName);

            positionSymbol.Tick -= PositionSymbol_Tick;
        }

        private void Positions_Opened(PositionOpenedEventArgs obj)
        {
            // If there are other positions from same symbol then don't add the symbol Tick event handler
            // Because we already have one
            if (Positions.Count(position => position.SymbolName.Equals(obj.Position.SymbolName, StringComparison.Ordinal)) > 1)
            {
                return;
            }

            // Add position symbol tick event handler
            var positionSymbol = Symbols.GetSymbol(obj.Position.SymbolName);

            positionSymbol.Tick += PositionSymbol_Tick;
        }

        private void PositionSymbol_Tick(SymbolTickEventArgs obj)
        {
            if (Account.Equity - _initialEquity >= EquityIncreaseAmount)
            {
                Stop();
            }
        }
    }
}

@amusleh

amusleh
28 Jan 2022, 08:42

Hi,

Your cBot/indicator doesn't know about other indicator/cBots controls, so you can't align your controls based on other indicators/cBots controls that are present on the chart.

The only option is to allow user change the location of controls by using indicator/cBot parameters, so he will be able to set the location somewhere that is free from other controls.


@amusleh

amusleh
28 Jan 2022, 08:36

RE:

SummerSalt said:

Thank you very much amusleh! I was not expecting so help. I have another question in regards to creating the close position levels. If for example I wanted to generate a market order OnBar, I use the ExecuteMarketOrder syntax, how then can I generate the LevelClosePips OnBar or OnTimed event. Is there a syntax for this? Thanks again for your time.

Hi,

Can you please make your question more clear?


@amusleh

amusleh
28 Jan 2022, 08:35

Hi,

It will if you at least saved the work space once while cBot was running.

You can test this behavior by ending the cTrader task from Task Manager, while your cBot is running and then open it again.

 


@amusleh

amusleh
28 Jan 2022, 08:31

Hi,

Here is an example:

using cAlgo.API;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class DrawIcon : Robot
    {
        private double _initialEquity;

        [Parameter("Equity Increase Amount", DefaultValue = 100)]
        public double EquityIncreaseAmount { get; set; }

        protected override void OnStart()
        {
            _initialEquity = Account.Equity;
        }

        protected override void OnTick()
        {
            if (Account.Equity - _initialEquity >= EquityIncreaseAmount)
            {
                Stop();
            }
        }
    }
}

It works properly only if your cBot trades the current chart symbol, if it trades multiple symbols then you have to use all symbols Tick events and check equity every time a symbol tick is received.


@amusleh

amusleh
28 Jan 2022, 08:27

Hi,

You can set the object IsInteractive flag to True:

using cAlgo.API;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class DrawIcon : Robot
    {

        protected override void OnStart()
        {
            string sMessage = "Long " + Bars.LastBar.OpenTime;
            var icon = Chart.DrawIcon(sMessage, ChartIconType.UpArrow, Bars.LastBar.OpenTime, Bars.LastBar.Low * 0.999, Color.FromHex("#DDE7E7E7"));

            icon.IsInteractive = true;
            icon.IsLocked = true;
        }

        protected override void OnTick() {}

        protected override void OnStop() {}
    }
}

The IsLocked is an additional optional step which disables moving of object, but you can turn it on/off from object settings.


@amusleh

amusleh
27 Jan 2022, 08:56

Hi,

You can post a job request or ask one of our consultants to develop it for you.


@amusleh

amusleh
27 Jan 2022, 08:55

Hi,

You can use the ClosePosition method overload that accepts an additional volume parameter with position:

ClosePosition(positionToClose, volumeAmountInUnits);

Here is a full example:

using System;
using System.Linq;
using cAlgo.API;
using System.Collections.Generic;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class PartialCloseSample : Robot
    {
        private readonly List<long> _firstLevelClosedPositions = new List<long>();
        private readonly List<long> _secondLevelClosedPositions = new List<long>();

        [Parameter("Close %", DefaultValue = 20, Group = "First Level")]
        public double FirstLevelCloseAmountInPercentage { get; set; }

        [Parameter("Pips", DefaultValue = 20, Group = "First Level")]
        public double FirstLevelClosePips { get; set; }

        [Parameter("Close %", DefaultValue = 20, Group = "Second Level")]
        public double SecondLevelCloseAmountInPercentage { get; set; }

        [Parameter("Pips", DefaultValue = 35, Group = "Second Level")]
        public double SecondLevelClosePips { get; set; }

        protected override void OnStart()
        {
            FirstLevelCloseAmountInPercentage /= 100;
            SecondLevelCloseAmountInPercentage /= 100;

            Positions.Opened += Positions_Opened;
            Positions.Closed += Positions_Closed;
        }

        private void Positions_Closed(PositionClosedEventArgs obj)
        {
            // In case position closed fully clean it's enteries from ID collections
            if (Positions.Any(position => position.Id == obj.Position.Id) == false)
            {
                if (_firstLevelClosedPositions.Contains(obj.Position.Id))
                {
                    _firstLevelClosedPositions.Remove(obj.Position.Id);
                }

                if (_secondLevelClosedPositions.Contains(obj.Position.Id))
                {
                    _secondLevelClosedPositions.Remove(obj.Position.Id);
                }
            }

            // If there are other positions from same symbol then don't remove the symbol Tick event handler
            if (Positions.Any(position => position.SymbolName.Equals(obj.Position.SymbolName, StringComparison.Ordinal)))
            {
                return;
            }

            // If there is no other position from the closed position symbol then remove the Tick event handler
            var positionSymbol = Symbols.GetSymbol(obj.Position.SymbolName);

            positionSymbol.Tick -= PositionSymbol_Tick;
        }

        private void Positions_Opened(PositionOpenedEventArgs obj)
        {
            // If there are other positions from same symbol then don't add the symbol Tick event handler
            // Because we already have one
            if (Positions.Count(position => position.SymbolName.Equals(obj.Position.SymbolName, StringComparison.Ordinal)) > 1)
            {
                return;
            }

            // Add position symbol tick event handler
            var positionSymbol = Symbols.GetSymbol(obj.Position.SymbolName);

            positionSymbol.Tick += PositionSymbol_Tick;
        }

        private void PositionSymbol_Tick(SymbolTickEventArgs obj)
        {
            var symbolPositions = Positions.Where(position => position.SymbolName.Equals(obj.SymbolName, StringComparison.Ordinal)).ToArray();

            foreach (var position in symbolPositions)
            {
                if (_firstLevelClosedPositions.Contains(position.Id) == false && position.Pips >= FirstLevelClosePips)
                {
                    ClosePositionByVolumePercenatage(position, FirstLevelCloseAmountInPercentage);

                    _firstLevelClosedPositions.Add(position.Id);
                }
                else if (_secondLevelClosedPositions.Contains(position.Id) == false && position.Pips >= SecondLevelClosePips)
                {
                    ClosePositionByVolumePercenatage(position, SecondLevelCloseAmountInPercentage);

                    _secondLevelClosedPositions.Add(position.Id);
                }
            }
        }

        private void ClosePositionByVolumePercenatage(Position position, double volumePercent)
        {
            var symbol = Symbols.GetSymbol(position.SymbolName);

            var volumeToClose = symbol.NormalizeVolumeInUnits(position.VolumeInUnits * volumePercent);

            ClosePosition(position, volumeToClose);
        }
    }
}

 


@amusleh