Topics
Forum Topics not found
Replies
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
amusleh
26 Jan 2022, 09:25
Hi,
Here is an example that might help you:
using System.Collections.Generic;
using cAlgo.API;
namespace cAlgo
{
[Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class Buttons : Indicator
{
protected override void Initialize()
{
// Change the panel or it's proerpties based on your needs
var buttonsPanel = new StackPanel
{
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center
};
var myButtonsContainer = new MyButtonsContainer(buttonsPanel);
myButtonsContainer.AddButton(new Button { Text = "Test Button" });
Chart.AddControl(myButtonsContainer);
foreach (var button in myButtonsContainer.GetButtons())
{
// Do something with button
}
}
public override void Calculate(int index)
{
}
}
public class MyButtonsContainer : CustomControl
{
private readonly List<Button> _buttons = new List<Button>();
// You can use any Panel like StackPanel, Grid, etc...
public MyButtonsContainer(Panel panel)
{
ContentPanel = panel;
AddChild(ContentPanel);
}
public Panel ContentPanel { get; private set; }
public void AddButton(Button button)
{
// If you have something in common between buttons you can add it here
// like event handlers, styles, etc...
button.Click += Button_Click;
ContentPanel.AddChild(button);
_buttons.Add(button);
}
private void Button_Click(ButtonClickEventArgs obj)
{
obj.Button.Text = "Clicked";
}
public IEnumerable<Button> GetButtons()
{
return _buttons;
}
}
}
You can also check each examples of each control I used above on API references.
@amusleh
amusleh
25 Jan 2022, 11:23
RE: RE:
instylereality2 said:
Yes, already passing through all the material days now! Researching everything as all is new to me as well.
This is brilliant! So it is possible to parse data from all ctrader indicators I may have like Harmonics, Financial Markets pivots and all through OpenApiPy, which can hold data evaluation and order execution logic as well as the AI later on.
In the samples folder on github, I see a picture of the web page with the commands. As I haven't reached that stage myself yet, is ProtoOAAssetClassList or asset list referring to active ctrader indicators? Or assume that there is enother command for that?
A last one and thank you for the assistance, OAuth2.0, do I need that in my system as well? Please assume that at least for the start I exclusively base my code on your github for openapipy.
Thank you Amusleh
Hi,
You can't use your cTrader desktop indicators on Open API, as I said before these are two different environments.
But you can calculate your current indicators by using price data that you get from Open API.
You can get OHLC time frame bars data from Open API and calculate anything you want to from them.
The ProtoOAAssetClassList gives you your account assets list, not indicators, please check the Open API documentation for a complete list of API messages and their detail.
@amusleh
amusleh
25 Jan 2022, 10:17
Hi,
Then you don't have to use cTrader Automate API at all, you can do everything with Open API.
You can get the bars/tick data with Open API, calculate your indicators, and feed the data to your ML model.
And you can execute the trading operations with Open API, you don't automate API in whole process at all.
You can do all in Python.
You can't reference OpenApiPy from a .NET environment unless you use something like IronPython which I don't have any experience with it at all.
We have a Jupyter sample in OpenApiPy Github repository that gets bars data and uses Python sklearn package to train a machine learning model, please check it: OpenApiPy/samples/jupyter at main · spotware/OpenApiPy (github.com)
@amusleh
amusleh
25 Jan 2022, 08:22
RE: RE:
TheNiatpac said:
Thank you Amusleh, I believe this is the right way to process the code.
Well, in my practice, the following question is, there are multiple TextBlocks in a Grid or several Grids, and they all need to change ForegroundColors and Positions by the price up or down. Is there any quick way, I can change all the TextBlocks' ForegroundColor and other properties rather than one by one which makes the code extremely long?
Thanks again in advance.
amusleh said:
Hi,
I will answer each of your point:
1. Yes, it will, you should not create a new button or canvas on each tick/bar
2. It will, because any control you create will live on memory as long as you remove it from chart or remove your indicator from chart
3. You should use OnInitilaize method and only change the control properties based on your criteria.
Here is your indicator code that is properly written:
using cAlgo.API; namespace cAlgo { ... }
Hi,
You can put all the controls inside a collection like list and then change them one by one or use a parent custom control.
There is no other way except updating each control on a sequential order.
@amusleh
amusleh
25 Jan 2022, 08:21
Hi,
Why you want to use Open API on your cBot? you have all the things you need in automate API.
As I said automate API is separate from Open API, you should use one not both at the same time.
But if you want to you can use Open API inside cTrader automate API environment, you don't have to use the Python package you can do it with .NET C#.
@amusleh
amusleh
25 Jan 2022, 08:18
RE: RE:
notzen said:
amusleh said:
Hi,
You can use our Fibonacci drawing tools which is more feature rich: Fibonacci Drawing Indicator | Algorithmic Forex Trading | cTrader Community
Or the full Pattern drawing indicator: Pattern Drawing Indicator | Algorithmic Forex Trading | cTrader Community
Hi,
I try it but when i change some values or parameters the buttons disappear , it will be good to have something like the fan in tradeview .
Hi,
Which button disappear? do you mean the chart buttons? can you post a screenshot please.
@amusleh
amusleh
24 Jan 2022, 09:18
Hi,
You can use our Fibonacci drawing tools which is more feature rich: Fibonacci Drawing Indicator | Algorithmic Forex Trading | cTrader Community
Or the full Pattern drawing indicator: Pattern Drawing Indicator | Algorithmic Forex Trading | cTrader Community
@amusleh
amusleh
24 Jan 2022, 09:16
( Updated at: 25 Jan 2022, 10:18 )
Hi,
The Find and FindAll methods are only available on Positions, it's basically a shorthand version of Linq where extension method:
var myPositions = Positions.Find("myLabel");
// Is equivalent to
var myPositions = Positions.Where(position => position.Label == "myLabel");
// Note: Don't use == for string equality as it will use the current thread culture,
// instead use Equal method of string and set the type of comparison you are looking
// to do, personally I prefer to use
var myPositions = Positions.Where(position => position.Label.Equals("MyLabel", StringComparison.OrdinalIgnoreCase));
// which is both case insensitive and has much better performance
Now regarding PendingOrders, you can use Linq here too, no need for any extra helper methods:
var myOrders = PendingOrders.Where(order => order.Label.Equals("MyLabel", StringComparison.OrdinalIgnoreCase));
And don't forget to call "ToArray" at the end:
var myPositions = Positions.Where(position => position.Label.Equals("MyLabel", StringComparison.OrdinalIgnoreCase)).ToArray();
var myOrders = PendingOrders.Where(order => order.Label.Equals("MyLabel", StringComparison.OrdinalIgnoreCase)).ToArray();
Otherwise anytime you iterate over it a new allocation will be made and the Linq query will be executed several times.
The Find/FindAll methods are added only to make things little bit easier for those who have no knowledge of .NET or Linq, but I strongly recommend you to use Linq.
@amusleh
amusleh
24 Jan 2022, 09:00
Hi,
I will answer each of your point:
1. Yes, it will, you should not create a new button or canvas on each tick/bar
2. It will, because any control you create will live on memory as long as you remove it from chart or remove your indicator from chart
3. You should use OnInitilaize method and only change the control properties based on your criteria.
Here is your indicator code that is properly written:
using cAlgo.API;
namespace cAlgo
{
[Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, ScalePrecision = 2, AccessRights = AccessRights.None)]
public class BestButton : Indicator
{
private Button _button;
private Canvas _canvas;
protected override void Initialize()
{
_button = new Button
{
Text = "Button",
FontSize = 50,
Margin = "1 5 0 5",
Padding = "2 1 2 1",
Height = 115,
HorizontalAlignment = HorizontalAlignment.Left
};
_button.Click += button_Click;
Chart.AddControl(_button);
_canvas = new Canvas
{
HorizontalAlignment = HorizontalAlignment.Center,
Width = 400,
Height = 115,
Margin = 5,
Opacity = 0.1
};
Chart.AddControl(_canvas);
}
public override void Calculate(int index)
{
if (IsLastBar)
{
MsgBrd();
}
}
private void MsgBrd()
{
if (LastBarUpOrDown())
{
_button.VerticalAlignment = VerticalAlignment.Top;
_button.BackgroundColor = Color.FromHex("#4488FF88");
_button.ForegroundColor = Color.FromHex("#9988FF88");
_canvas.BackgroundColor = Color.SandyBrown;
_canvas.VerticalAlignment = VerticalAlignment.Top;
}
else
{
_button.VerticalAlignment = VerticalAlignment.Bottom;
_button.BackgroundColor = Color.FromHex("#44FF8888");
_button.ForegroundColor = Color.FromHex("#99FF8888");
_canvas.BackgroundColor = Color.DeepSkyBlue;
_canvas.VerticalAlignment = VerticalAlignment.Bottom;
}
}
private void button_Click(ButtonClickEventArgs obj)
{
_canvas.IsVisible = _canvas.IsVisible ? false : true;
}
private bool LastBarUpOrDown()
{
return Bars.Last(0).Close > Bars.Last(0).Open ? true : false;
}
}
}
@amusleh
amusleh
24 Jan 2022, 08:47
Hi,
Let me first make some things clear for you, cTrader have three different types of APIs, each serve a different purpose:
- cTrader Automate API: It's part of cTrader desktop app, you can use it to create indicators and cBots for cTrader desktop app.
- FIX API: It's the standard FIX API implementation that is available for cTrader trading accounts, you can use it to trade and get price data of your cTrader trading account, but the FIX standard is very limited and old, you can get your trading account FIX API credentials from cTrader app settings section, we have some samples on our Github that you can use.
- Open API: This is another API cTrader provides, it's not dependent on cTrader desktop/web/mobile apps and it's fully separate from the two abovementioned APIs, this is the API that you can use to create fully featured trading platforms or trading algorithms that will operate on your or any other cTrader users trading accounts. if you want to create an app or a trading algorithm outside cTrader official provided apps that will be your go to option. we have plenty of rich samples for this API on our Github for different programming languages, we have developed SDKs for this and also some third party developers made lots of contribution to develop different packages/wrappers for this cTrader API, you can check our OpenAPI.NET or OpenApiPy Github repositories.
So regarding your question, I don't recommend you to use Open API inside cTrader automate API, if you want to build a trading strategy then use cTrader automate API.
In case you want to build something more complicated and feature rich use Open API.
And use FIX API only if you know what you are doing.
OpenApiPy is a Pyhton package that allows you to use the Open API easily inside a Python app or environment, it's developed and maintained by Spotware.
If you want to use OpenApiPy please check it's documentation.
And if you are interested in Open API take a look on it's documentation.
@amusleh
amusleh
21 Jan 2022, 09:39
( Updated at: 21 Jan 2022, 09:40 )
Hi,
The ProtoOATickData timestamp is in Unix milliseconds, and it's in descending order.
You have to add the current tick time stamp to previous tick time stamp to get the time, ex in C#:
long previousTickTime = 0;
var stringBuilder = new StringBuilder();
stringBuilder.AppendLine("Tick,Time");
foreach (var tick in response.TickData)
{
previousTickTime += tick.Timestamp;
stringBuilder.AppendLine($"{tick.Tick},{DateTimeOffset.FromUnixTimeMilliseconds(previousTickTime)}");
}
System.Diagnostics.Trace.WriteLine(stringBuilder.ToString());
I sent a request for getting ticks from 20/1/2022 8:03:26 PM to 20/1/2022 9:03:26 PM, here is the response:
Tick,Time
113052,1/20/2022 9:03:25 PM +00:00
1,1/20/2022 9:03:25 PM +00:00
1,1/20/2022 9:03:24 PM +00:00
-1,1/20/2022 9:03:23 PM +00:00
-1,1/20/2022 9:03:22 PM +00:00
1,1/20/2022 9:03:22 PM +00:00
1,1/20/2022 9:03:15 PM +00:00
1,1/20/2022 9:03:15 PM +00:00
-1,1/20/2022 9:03:14 PM +00:00
1,1/20/2022 9:03:12 PM +00:00
-2,1/20/2022 9:03:11 PM +00:00
-1,1/20/2022 9:03:10 PM +00:00
1,1/20/2022 9:03:09 PM +00:00
// Omitted for brevity
4,1/20/2022 8:03:57 PM +00:00
1,1/20/2022 8:03:56 PM +00:00
2,1/20/2022 8:03:56 PM +00:00
2,1/20/2022 8:03:55 PM +00:00
-1,1/20/2022 8:03:33 PM +00:00
1,1/20/2022 8:03:30 PM +00:00
1,1/20/2022 8:03:26 PM +00:00
We will update the ProtoOATickData documentation to describe this.
@amusleh
amusleh
21 Jan 2022, 09:28
Hi,
The indicator calculate method is always called in order, whenever you attach an indicator or reload it by loading more historical data or changing its parameters the indicator calculate method is called sequentially by order for all available historical bars on your chart.
@amusleh
amusleh
20 Jan 2022, 09:17
RE: RE:
icollocollo said:
amusleh said:
Hi,
Can you provide more context and what you are after?
If you want to close a position when it reach 2 Risk:Reward, then you can use the Position Pips, if it's double the amount of stop loss in pips then close it.
You don't have to use volume to calculate it.
Reason i am trying to use Volume is because my SL varies from one to the other. And TP is a multiple of SL, say SL*5. Closing partials at SL * 2 and modifying the remaining to break even at +2 pips.
Hi,
It doesn't matter if your SLs varies or not, you can get each position current SL in pips, for example if your position current pips is 10 and your stop loss is 5 pips then it means your position is reached 2 RR, and you can close half of its volume, no need for calculating volume.
@amusleh
amusleh
19 Jan 2022, 14:59
RE: RE: RE: FIX API crash(usually after 1-20 minutes) : An existing connection was forcibly closed by the remote host
slukk200 said:
amusleh said:
slukk200 said:
Hi Amusleh,
I have registered 2 live accounts. For one(Pepperstone) it has been running for 10 hours without any problem, but for the otherone (ICMarkets) it keeps disconnecting. I have tried your console app again with the config file you provided and it disonnected after 3 minutes. (The two apps have been running parallel so I don't think this is an internet problem)
Is there someone here at Spotware who could take a look at it?
Or should I contact the broker?
Hi,
I tested again on a IC Market demo account today for 2 hours and 200 symbols, I didn't faced any issue.
If we can't replicate the issue how can we fix it? I have tested it and it works fine.
I'm Spotware community developer.
Hi Almulesh,
I have never said that the issue is on your side. I just would like to know the reason why your server closed the connection. Is there a way someone could take a look at it?
Unfortunately I recieve no incoming message about the reason why it is terminated.
It could be a hearbeat issue or something else, I don't know.
Hi,
Can you please tell us which proxy/host/port you are using and the disconnection timestamped logs?
@amusleh
amusleh
28 Jan 2022, 08:27
Hi,
You can set the object IsInteractive flag to True:
The IsLocked is an additional optional step which disables moving of object, but you can turn it on/off from object settings.
@amusleh