Topics
Forum Topics not found
Replies
amusleh
21 Apr 2021, 08:40
Hi,
It works fine, try this sample:
using cAlgo.API;
using System;
using System.Globalization;
namespace cAlgo.Robots
{
/// <summary>
/// This sample bot shows how to place different types of pending orders
/// </summary>
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class PendingOrderPlacingSample : Robot
{
[Parameter("Type", DefaultValue = PendingOrderType.Limit)]
public PendingOrderType OrderType { get; set; }
[Parameter("Direction", DefaultValue = TradeType.Buy)]
public TradeType OrderTradeType { get; set; }
[Parameter("Volume (Lots)", DefaultValue = 0.01)]
public double VolumeInLots { get; set; }
[Parameter("Distance (Pips)", DefaultValue = 20, MinValue = 1)]
public double DistanceInPips { get; set; }
[Parameter("Stop (Pips)", DefaultValue = 10, MinValue = 0)]
public double StopInPips { get; set; }
[Parameter("Target (Pips)", DefaultValue = 10, MinValue = 0)]
public double TargetInPips { get; set; }
[Parameter("Limit Range (Pips)", DefaultValue = 10, MinValue = 1)]
public double LimitRangeInPips { get; set; }
[Parameter("Expiry", DefaultValue = "00:00:00")]
public string Expiry { get; set; }
[Parameter("Label")]
public string Label { get; set; }
[Parameter("Comment")]
public string Comment { get; set; }
[Parameter("Trailing Stop", DefaultValue = false)]
public bool HasTrailingStop { get; set; }
[Parameter("Stop Loss Method", DefaultValue = StopTriggerMethod.Trade)]
public StopTriggerMethod StopLossTriggerMethod { get; set; }
[Parameter("Stop Order Method", DefaultValue = StopTriggerMethod.Trade)]
public StopTriggerMethod StopOrderTriggerMethod { get; set; }
[Parameter("Async", DefaultValue = false)]
public bool IsAsync { get; set; }
protected override void OnStart()
{
var volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots);
DistanceInPips *= Symbol.PipSize;
var stopLoss = StopInPips == 0 ? null : (double?)StopInPips;
var takeProfit = TargetInPips == 0 ? null : (double?)TargetInPips;
TimeSpan expiry;
if (!TimeSpan.TryParse(Expiry, CultureInfo.InvariantCulture, out expiry))
{
Print("Invalid expiry");
Stop();
}
var expiryTime = expiry != TimeSpan.FromSeconds(0) ? (DateTime?)Server.Time.Add(expiry) : null;
TradeResult result = null;
switch (OrderType)
{
case PendingOrderType.Limit:
var limitPrice = OrderTradeType == TradeType.Buy ? Symbol.Ask - DistanceInPips : Symbol.Ask + DistanceInPips;
if (IsAsync)
PlaceLimitOrderAsync(OrderTradeType, SymbolName, volumeInUnits, limitPrice, Label, stopLoss, takeProfit, expiryTime, Comment, HasTrailingStop, StopLossTriggerMethod, OnCompleted);
else
result = PlaceLimitOrder(OrderTradeType, SymbolName, volumeInUnits, limitPrice, Label, stopLoss, takeProfit, expiryTime, Comment, HasTrailingStop, StopLossTriggerMethod);
break;
case PendingOrderType.Stop:
var stopPrice = OrderTradeType == TradeType.Buy ? Symbol.Ask + DistanceInPips : Symbol.Ask - DistanceInPips;
if (IsAsync)
PlaceStopOrderAsync(OrderTradeType, SymbolName, volumeInUnits, stopPrice, Label, stopLoss, takeProfit, expiryTime, Comment, HasTrailingStop, StopLossTriggerMethod, StopOrderTriggerMethod, OnCompleted);
else
result = PlaceStopOrder(OrderTradeType, SymbolName, volumeInUnits, stopPrice, Label, stopLoss, takeProfit, expiryTime, Comment, HasTrailingStop, StopLossTriggerMethod, StopOrderTriggerMethod);
break;
case PendingOrderType.StopLimit:
var stopLimitPrice = OrderTradeType == TradeType.Buy ? Symbol.Ask + DistanceInPips : Symbol.Ask - DistanceInPips;
if (IsAsync)
PlaceStopLimitOrderAsync(OrderTradeType, SymbolName, volumeInUnits, stopLimitPrice, LimitRangeInPips, Label, stopLoss, takeProfit, expiryTime, Comment, HasTrailingStop, StopLossTriggerMethod, StopOrderTriggerMethod, OnCompleted);
else
result = PlaceStopLimitOrder(OrderTradeType, SymbolName, volumeInUnits, stopLimitPrice, LimitRangeInPips, Label, stopLoss, takeProfit, expiryTime, Comment, HasTrailingStop, StopLossTriggerMethod, StopOrderTriggerMethod);
break;
default:
Print("Invalid order type");
throw new ArgumentOutOfRangeException("OrderType");
}
if (!IsAsync) OnCompleted(result);
}
private void OnCompleted(TradeResult result)
{
if (!result.IsSuccessful) Print("Error: ", result.Error);
Stop();
}
}
}
There is two stop trigger method parameters, one for stop loss order and another for stop order itself.
@amusleh
amusleh
21 Apr 2021, 08:30
( Updated at: 21 Dec 2023, 09:22 )
RE: RE:
tekASH said:
amusleh said:
Hi,
You have to install the library on every indicator/cBot you want to use it on, not on Visual Studio.
The nuget packages are installed on your cBot/indicator projects, so if you created a new one then you have to install it n your new indicator/cBot.
1. mate, look...I clicked Edit the Bot in VS as you explain in Installation...then installed Alert.API (library?) thing from Nuget...after that..I added those small codes in cTrader (Automate) to my existing bot. I built it successfully.
I turn on the Bot pressing Play...it is active but Alerts window is not opening up..where is it. now what?
Libraries are in the Bot
2. btw, is this correct?
Please do this:
0. Create a new indicator
1. Install Alert library on it via Nuget
2. After that re-build your indicator from Visual Studio, not from cTrader automate, Right click on your solution name select Rebuild
3. Then copy the sample indicator code and paste it on your new indicator code file, rebuild
4. Attach it on a one minute chart, wait for indicator show popup condition to meet, and you will see the popup will appear
If it still doesn't work, post your full indicator code here.
@amusleh
amusleh
20 Apr 2021, 18:44
RE: RE:
tekASH said:
amusleh said:
Hi,
You don't have to set the configuration parameters, those are optional.
First you have to install the Alert popup library via Nuget on your indicator/cBot project, the installation tutorial is on Github Wiki.
Once you installed you have to add the "using cAlgo.API.Alert" on top of your indicator/cBot code file, then you will be able to call the "ShowPopup".
If you read the Wiki you will find the answer for your questions.
so...I did Installation steps again..then added "using cAlgo.API.Alert" then added
Notifications.ShowPopup(); it did build it successfully...but now after turning on the Bot...that Settings window of Alerts doesnt show up? Does it need to show up or where I access it? Cause I need to configure Telegram alerts.
Hi,
To open settings click on "Settings" icon at the title bar of Alert popup window.
@amusleh
amusleh
20 Apr 2021, 16:49
Hi,
There are lots of ways to do what you are after, one simple option is to use Linq:
using cAlgo.API;
using System;
using System.Globalization;
using System.Linq;
namespace cAlgo
{
[Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class TodayHighestClose : Indicator
{
private TimeSpan _startTime, _endTime;
[Parameter("Start Time", DefaultValue = "06:00:00")]
public string StartTime { get; set; }
[Parameter("End Time", DefaultValue = "10:00:00")]
public string EndTime { get; set; }
protected override void Initialize()
{
if (!TimeSpan.TryParse(StartTime, CultureInfo.InvariantCulture, out _startTime))
{
Print("Invalid Start Time");
}
if (!TimeSpan.TryParse(EndTime, CultureInfo.InvariantCulture, out _endTime))
{
Print("Invalid End Time");
}
var highestClosePriceOfToday = Bars.Where(iBar => iBar.OpenTime.Date == Server.Time.Date && iBar.OpenTime.TimeOfDay >= _startTime && iBar.OpenTime.TimeOfDay <= _endTime).Max(iBar => iBar.Close);
Print(highestClosePriceOfToday);
}
public override void Calculate(int index)
{
}
}
}
@amusleh
amusleh
20 Apr 2021, 16:40
Hi,
You don't have to set the configuration parameters, those are optional.
First you have to install the Alert popup library via Nuget on your indicator/cBot project, the installation tutorial is on Github Wiki.
Once you installed you have to add the "using cAlgo.API.Alert" on top of your indicator/cBot code file, then you will be able to call the "ShowPopup".
If you read the Wiki you will find the answer for your questions.
@amusleh
amusleh
20 Apr 2021, 15:53
( Updated at: 20 Apr 2021, 15:54 )
Hi,
To show the popup window you have to call the "Notifications.ShowPopup" method from your indicator or cBot code.
For settings after the popup showed up click on settings icon at the title bar.
All of this is well explained in Wikis, please read, take a look on full indicator/cBot samples.
@amusleh
amusleh
19 Apr 2021, 13:38
Hi,
The LoadMoreHistory method doesn't work during back test, to solve your issue you have to check how many bars are available in Bars, and whenever the amount of bars reached your desired number you can execute your code, you can use the IsBacktesting property to run that code only when you are back testing.
@amusleh
amusleh
19 Apr 2021, 11:36
Hi,
Please post a job request or ask one of our consultants to develop your cBot for you.
@amusleh
amusleh
19 Apr 2021, 10:41
You should check the Bars number:
using cAlgo.API;
using cAlgo.API.Internals;
using System;
using System.Linq;
using System.Net;
using System.Text;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
public class MLBot : Robot
{
private const string Name = "MLBot";
[Parameter("Base Url", DefaultValue = "http://localhost:5000/predict")]
public string BaseUrl { get; set; }
[Parameter("Batch Size", MinValue = 1, DefaultValue = 128)]
public int BatchSize { get; set; }
[Parameter("Window Size", MinValue = 1, DefaultValue = 256)]
public int WindowSize { get; set; }
[Parameter("MA Periods", MinValue = 1, DefaultValue = 14)]
public int MAPeriods { get; set; }
[Parameter("Pips", MinValue = 1, DefaultValue = 8)]
public int Pips { get; set; }
[Parameter("Prediction Size", MinValue = 1, DefaultValue = 4)]
public int PredSize { get; set; }
[Parameter("Volume", Group = "Standard", DefaultValue = 20000)]
public double Volume { get; set; }
[Parameter("Max Spread Limit (Pips)", Group = "Standard", DefaultValue = 1.5)]
public double MaxSpreadLimitInPips { get; set; }
private WebClient _webClient;
private double _maxSpreadLimitAbsolute = 0;
private string _baseUrlParam;
private string GetUrl()
{
StringBuilder sb = new StringBuilder(_baseUrlParam);
sb.Append("/");
sb.Append(Time.ToString("yyyyMMddHHmmss"));
sb.Append("/");
for (int i = WindowSize + MAPeriods - 1; i >= 0; i--)
{
if (Bars.Count > i)
{
sb.Append(((Bars.Last(i).High + Bars.Last(i).Low) / 2).ToString());
}
sb.Append(",");
}
sb.Length = sb.Length - 1;
// removing the last comma
return sb.ToString();
}
private TradeType? GetMLPrediction()
{
string url = GetUrl();
string tradeType = _webClient.DownloadString(url);
switch (tradeType)
{
case "1":
return TradeType.Buy;
case "-1":
return TradeType.Sell;
case "0":
return null;
default:
throw new InvalidOperationException("Not an expected return from the ML: " + (tradeType ?? "(null)"));
}
}
protected override void OnStart()
{
_webClient = new WebClient();
_maxSpreadLimitAbsolute = MaxSpreadLimitInPips * Symbol.PipSize;
_baseUrlParam = BaseUrl + "/" + Symbol.Name.ToLower() + "/" + BatchSize + "/" + WindowSize + "/" + MAPeriods + "/" + (Symbol.PipSize * Pips) + "/" + PredSize;
}
protected override void OnBar()
{
// Prevents running this in production
if (!IsBacktesting)
{
return;
}
if ((Ask - Bid) > _maxSpreadLimitAbsolute)
{
return;
}
if (Positions.FindAll(Name, SymbolName).Any())
{
return;
}
TradeType? tradeType = GetMLPrediction();
if (tradeType == null)
{
return;
}
ExecuteMarketOrder(tradeType.Value, Symbol.Name, Volume, Name, Pips, Pips);
}
}
}
@amusleh
amusleh
18 Apr 2021, 09:21
This line is the issue:
sb.Append(((Bars.Last(i).High + Bars.Last(i).Low) / 2).ToString());
It throws argument out of range because you don't check the number of available values inside bars collection.
You have to check if there is that many bars or not via Bars Count property before trying to access a value via an index or last method.
And for working with URIs I recommend you to use .NET UriBuilder instead of StringBuilder.
To debug your indicator/cBot use Print method or attach Visual Studio debugger and set break points.
@amusleh
amusleh
17 Apr 2021, 10:12
Hi,
This sample might help you:
using cAlgo.API;
using cAlgo.API.Indicators;
namespace cAlgo.Robots
{
/// <summary>
/// This sample cBot shows how to use the Relative Strength Index indicator
/// </summary>
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class RelativeStrengthIndexSample : Robot
{
private double _volumeInUnits;
private RelativeStrengthIndex _relativeStrengthIndex;
[Parameter("Volume (Lots)", DefaultValue = 0.01)]
public double VolumeInLots { get; set; }
[Parameter("Stop Loss (Pips)", DefaultValue = 10)]
public double StopLossInPips { get; set; }
[Parameter("Take Profit (Pips)", DefaultValue = 10)]
public double TakeProfitInPips { get; set; }
[Parameter("Label", DefaultValue = "Sample")]
public string Label { get; set; }
public Position[] BotPositions
{
get
{
return Positions.FindAll(Label);
}
}
protected override void OnStart()
{
_volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots);
_relativeStrengthIndex = Indicators.RelativeStrengthIndex(Bars.ClosePrices, 20);
}
protected override void OnBar()
{
if (_relativeStrengthIndex.Result.Last(1) > 70 && _relativeStrengthIndex.Result.Last(2) < 70)
{
ClosePositions(TradeType.Buy);
ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips);
}
else if (_relativeStrengthIndex.Result.Last(1) < 20 && _relativeStrengthIndex.Result.Last(2) > 20)
{
ClosePositions(TradeType.Sell);
ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLossInPips, TakeProfitInPips);
}
}
private void ClosePositions(TradeType tradeType)
{
foreach (var position in BotPositions)
{
if (position.TradeType != tradeType) continue;
ClosePosition(position);
}
}
}
}
Please start learning C# basics and read cTrader automate API references, if you don't have time then post a job request or ask one of our consultants to develop your cBot/indicator for you.
@amusleh
amusleh
13 Apr 2021, 09:59
I'm not defensive, I'm trying to explain how the Automate API works.
As I said OnTick has precedence and we are not going to change this behavior.
Why you are trying to link OnTick with PendingOrders Filled event? there is no link between these two and nor with other methods like OnBar or OnTimer.
Right now all cBot methods are called sequentially by one thread, in future we might change this and use multiple threads to call different methods at the same time.
Code your cBot in a way that it doesn't rely on the sequence that these methods will be called, because in future it can change.
PendingOrders Filled event is where you get the position for triggered Pending Order, but in what sequence it will be called is not guaranteed and we call it as soon as possible.
If its very important for you, then you can create you own observable collections of pending orders and positions, use OnTick and Pending Orders events to keep your collections up to date based on your preference, you can create a library with your own classes and use it on your bots.
@amusleh
amusleh
13 Apr 2021, 09:46
Hi,
Right now there is no way to change a chart time frame while a cBot instance is running on that chart.
We have plans to allow changing the time frame but we can't give you any ETA for that, I recommend you to open a thread for this feature request on forum suggestions section.
@amusleh
amusleh
11 Apr 2021, 13:57
Just remove the Exit method from your cBot, and use the ExecuteMarketOrder overload that gets stop loss and take profit in Pips parameters:
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 ThreeSessionsMaTypeSlowBiasWithExit : Robot
{
[Parameter("London Start", DefaultValue = 2)]
public double StartTime { get; set; }
[Parameter("London Stop", DefaultValue = 4)]
public double StopTime { get; set; }
[Parameter("New York Start", DefaultValue = 8)]
public double StartTime2 { get; set; }
[Parameter("New York Stop", DefaultValue = 10)]
public double StopTime2 { get; set; }
[Parameter("Asia Start", DefaultValue = 19)]
public double StartTime3 { get; set; }
[Parameter("Asia Stop", DefaultValue = 21)]
public double StopTime3 { get; set; }
[Parameter("Source")]
public DataSeries SourceSeries { get; set; }
[Parameter("MA Type")]
public MovingAverageType MAType { get; set; }
[Parameter("Label", DefaultValue = "MAType")]
public string Label { get; set; }
[Parameter("Bias Period", DefaultValue = 233)]
public int BiasPeriod { get; set; }
[Parameter("Medium Period", DefaultValue = 55)]
public int MediumPeriod { get; set; }
[Parameter("Fast Period", DefaultValue = 21)]
public int FastPeriod { get; set; }
[Parameter("Stop Loss", DefaultValue = 20)]
public int StopLoss { get; set; }
[Parameter("Take Profit", DefaultValue = 40)]
public int TakeProfit { get; set; }
[Parameter("Quantity (Lots)", DefaultValue = 1, MinValue = 0.01, Step = 0.01)]
public double Quantity { get; set; }
private double _volumeInUnits;
private MovingAverage slowMa;
private MovingAverage mediumMa;
private MovingAverage fastMa;
private DateTime _startTime;
private DateTime _stopTime;
private DateTime _startTime2;
private DateTime _stopTime2;
private DateTime _startTime3;
private DateTime _stopTime3;
protected override void OnStart()
{
fastMa = Indicators.MovingAverage(SourceSeries, FastPeriod, MAType);
mediumMa = Indicators.MovingAverage(SourceSeries, MediumPeriod, MAType);
slowMa = Indicators.MovingAverage(SourceSeries, BiasPeriod, MAType);
_volumeInUnits = Symbol.QuantityToVolumeInUnits(Quantity);
_startTime = Server.Time.Date.AddHours(StartTime);
_stopTime = Server.Time.Date.AddHours(StopTime);
_startTime2 = Server.Time.Date.AddHours(StartTime2);
_stopTime2 = Server.Time.Date.AddHours(StopTime2);
_startTime3 = Server.Time.Date.AddHours(StartTime3);
_stopTime3 = Server.Time.Date.AddHours(StopTime3);
}
protected override void OnBar()
{
int index = Bars.Count - 1;
Entry(index);
}
private void Entry(int index)
{
var currentHours = Server.Time.TimeOfDay.TotalHours;
bool istimecorrect = currentHours > StartTime && currentHours < StopTime;
var currentHours2 = Server.Time.TimeOfDay.TotalHours;
bool istimecorrect2 = currentHours2 > StartTime2 && currentHours < StopTime2;
var currentHours3 = Server.Time.TimeOfDay.TotalHours;
bool istimecorrect3 = currentHours3 > StartTime3 && currentHours3 < StopTime3;
if (!istimecorrect & !istimecorrect2 & !istimecorrect3)
return;
// Buy Only
if (Bars.ClosePrices[index] > slowMa.Result[index])
{
// if fast crosses medium upward
if (fastMa.Result[index] > mediumMa.Result[index] && fastMa.Result[index - 1] < mediumMa.Result[index - 1])
{
ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLoss, TakeProfit);
}
}
// Sell only
else if (Bars.ClosePrices[index] < slowMa.Result[index])
{
// if fast crosses medium downward
if (fastMa.Result[index] < mediumMa.Result[index] && fastMa.Result[index - 1] > mediumMa.Result[index - 1])
{
ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLoss, TakeProfit);
}
}
}
}
}
Instead of asking this type of questions in forum you have to read the API references or check sample cBot codes.
@amusleh
amusleh
21 Apr 2021, 13:50
RE: RE:
mcho911 said:
Hi,
What do you mean? I just tried two buy and sell stop limit orders with opposite trigger method and it got triggered without any problem.
@amusleh