Topics
Forum Topics not found
Replies
amusleh
02 Jul 2021, 10:35
Hi,
Change your OnTick method to:
protected override void OnTick()
{
var position = Positions.Find(Label, SymbolName);
if (position == null) return;
var entryPrice = position.EntryPrice;
var distance1 = Symbol.Bid - entryPrice;
var distance2 = entryPrice - Symbol.Ask;
if (distance1 >= Trigger * Symbol.PipSize)
{
ModifyPosition(position, entryPrice, position.TakeProfit);
Print("Stop Loss to Break Even set for position {0}", position.Id);
Stop();
}
if (distance2 >= Trigger * Symbol.PipSize)
{
ModifyPosition(position, entryPrice, position.TakeProfit);
Print("Stop Loss to Break Even set for position {0}", position.Id);
Stop();
}
}
Position.Find can return null, and if you don't check for null it will throw null reference exception and the rest of your code will not execute.
@amusleh
amusleh
01 Jul 2021, 11:37
Hi,
I don't see any issue on your code, it should work fine if there is any position that has less than 10 gross profit, it might not working because the OnTick method is called only for chart symbol ticks, not all position ticks, if you want to manage multiple symbols positions then try this:
protected override void OnStart()
{
foreach (var symbol in Symbols.GetSymbols())
{
symbol.Tick += SymbolTick;
}
}
private void SymbolTick(SymbolTickEventArgs obj)
{
foreach (var position in Positions)
{
if (position.SymbolName.Equals(obj.SymbolName, StringComparison.OrdinalIgnoreCase) && position.GrossProfit <= -10)
{
ClosePosition(position);
Stop();
}
}
}
@amusleh
amusleh
01 Jul 2021, 11:31
Hi,
Your cBot code had few bugs that were causing it to crash, I fixed it but there is still no trade because your entry logic is very strict:
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
namespace FirstBot
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
public class cAlgo : Robot
{
private double _volumeInUnits;
[Parameter("Label", DefaultValue = "Sample")]
public string Label { get; set; }
[Parameter("Volume (Lots)", DefaultValue = 0.01)]
public double VolumeInLots { get; set; }
[Parameter(DefaultValue = 100, MinValue = 1)]
public int StopLoss { get; set; }
[Parameter(DefaultValue = 150, MinValue = 1)]
public int TakeProfit { get; set; }
[Parameter("MACD LongCycle", DefaultValue = 26, MinValue = 1)]
public int LongCycle { get; set; }
[Parameter("MACD ShortCycle", DefaultValue = 12, MinValue = 1)]
public int ShortCycle { get; set; }
[Parameter("MACD Period", DefaultValue = 9, MinValue = 1)]
public int MACDPeriod { get; set; }
[Parameter("MA Type", DefaultValue = 6)]
public MovingAverageType MaType { get; set; }
[Parameter("K Periods", DefaultValue = 9)]
public int KPeriods { get; set; }
[Parameter("D Periods", DefaultValue = 9)]
public int DPeriods { get; set; }
[Parameter("K Slowing", DefaultValue = 3)]
public int K_Slowing { get; set; }
[Parameter("Price")]
public DataSeries Price { get; set; }
[Parameter("MA Bias", DefaultValue = 50)]
public int MA_Bias { get; set; }
public static TimeFrame Minute15;
private MacdCrossOver _MACD;
private StochasticOscillator _SOC;
private ExponentialMovingAverage _MA_50;
private bool MACDBuy;
private bool MACDSell;
private bool SOCBuy;
private bool SOCSell;
private bool MA_BiasBuy;
private bool MA_BiasSell;
protected override void OnStart()
{
_volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots);
MACDBuy = false;
MACDSell = false;
SOCBuy = false;
SOCSell = false;
MA_BiasBuy = false;
MA_BiasSell = false;
_MACD = Indicators.MacdCrossOver(LongCycle, ShortCycle, MACDPeriod);
_SOC = Indicators.StochasticOscillator(KPeriods, K_Slowing, DPeriods, MaType);
_MA_50 = Indicators.ExponentialMovingAverage(Price, MA_Bias);
}
protected override void OnBar()
{
var ActiveBuy = Positions.Find(Label, SymbolName, TradeType.Buy);
var ActiveSell = Positions.Find(Label, SymbolName, TradeType.Sell);
// MACD cross
if (_MACD.MACD.Last(1) < _MACD.Signal.Last(1) && _MACD.MACD.Last(0) > _MACD.Signal.Last(0) && _MACD.Signal.Last(0) < 0)
{
MACDBuy = true;
}
else if (_MACD.MACD.Last(1) > _MACD.Signal.Last(1) && _MACD.MACD.Last(0) < _MACD.Signal.Last(0) && _MACD.Signal.Last(0) > 0)
{
MACDSell = true;
}
// Stochastic cross
if (_SOC.PercentK.HasCrossedAbove(_SOC.PercentD, 0) && _SOC.PercentK.Last(1) <= 20)
{
if (_SOC.PercentK.Last(1) > 80)
{
SOCBuy = true;
}
}
else if (_SOC.PercentK.HasCrossedBelow(_SOC.PercentD, 0) && _SOC.PercentK.Last(1) >= 80)
{
if (_SOC.PercentK.Last(1) < 20)
{
SOCSell = true;
}
}
// Moving Average Bias
if (Symbol.Bid > _MA_50.Result.LastValue)
{
MA_BiasBuy = true;
}
else if (Symbol.Bid > _MA_50.Result.LastValue)
{
MA_BiasSell = true;
}
if (MACDBuy == true && SOCBuy == true && MA_BiasBuy == true && ActiveBuy == null)
{
if (ActiveSell != null)
{
ClosePosition(ActiveSell);
}
ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, StopLoss, TakeProfit);
}
if (MACDSell == true && SOCSell == true && MA_BiasSell == true && ActiveSell == null)
{
if (ActiveBuy != null)
{
ClosePosition(ActiveBuy);
}
ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, StopLoss, TakeProfit);
}
}
}
}
If you remove some of the entry conditions you will see trades on back test, also please don't user the Last(0) or LastValue on your cBot, it gives you the latest not closed value of a data series, which can be non deterministic, instead use Last(1) and Last(2).
If you couldn't figure out how to develop the cBot based on your requirements you can post a job request or ask one of our consultants to do it for you.
@amusleh
amusleh
01 Jul 2021, 11:06
Hi,
Try this:
using cAlgo.API;
using System.Linq;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class HeavyweightBot : Robot
{
[Parameter("Instance Name", DefaultValue = "001")]
public string InstanceName { get; set; }
[Parameter(DefaultValue = 0.0)]
public double Parameter { get; set; }
//Selecting Indicator
private ConvertedIndicator heavy;
protected override void OnStart()
{
Print("Hello World!");
//Load Indicators on startup
heavy = Indicators.GetIndicator<ConvertedIndicator>(14, 3);
}
protected override void OnBar()
{
//Trade Amounts
var TradeAmount = 1000;
//Zero line cross example
var HeavyUp = heavy.ExtMapBuffer2_AlgoOutputDataSeries.Last(1);
var PrevHeavyUp = heavy.ExtMapBuffer2_AlgoOutputDataSeries.Last(2);
var HeavyDown = heavy.ExtMapBuffer1_AlgoOutputDataSeries.Last(1);
var PrevHeavyDown = heavy.ExtMapBuffer1_AlgoOutputDataSeries.Last(2);
var Flat = heavy.ExtMapBuffer3_AlgoOutputDataSeries.Last(2);
//Check for trade signal
if (HeavyUp > PrevHeavyDown && !IsPositionOpenByType(TradeType.Buy))
{
ExecuteMarketOrder(TradeType.Buy, SymbolName, TradeAmount, InstanceName, 20, 20);
}
else if (HeavyDown < PrevHeavyUp && !IsPositionOpenByType(TradeType.Sell))
{
ExecuteMarketOrder(TradeType.Sell, SymbolName, TradeAmount, InstanceName, 20, 20);
}
}
protected override void OnStop()
{
Print("Cya Later!");
}
private bool IsPositionOpenByType(TradeType type)
{
return Positions.FindAll(InstanceName, SymbolName, type).Length > 0;
}
}
}
@amusleh
amusleh
28 Jun 2021, 11:46
Hi,
Your question is not related to cTrader Automate API, you have to Google these types of questions or post your question on Stackoverflow.
Your object and Json have invalid format, try this:
using cAlgo.API;
using Newtonsoft.Json;
using System;
namespace cAlgo
{
[Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
public class JsonDeserializeTest : Indicator
{
private string _json = @"{
success: true,
data:
{
id: 14,
orderId: 21,
productId: 20,
userId: 1,
licenseKey: 'RS-KH-0G-6B-FD-A7-CS-W7',
expiresAt: '2021-07-26 00:00:00'
}
}";
protected override void Initialize()
{
var licence = JsonConvert.DeserializeObject<Licence>(_json);
Print(licence.Data.ExpiresAt);
}
public override void Calculate(int index)
{
}
}
public class Licence
{
public string Success { get; set; }
public Data Data { get; set; }
}
public class Data
{
public int Id { get; set; }
public int OrderId { get; set; }
public int ProductId { get; set; }
public int UserId { get; set; }
public string LicenseKey { get; set; }
public DateTime ExpiresAt { get; set; }
}
}
It works fine on my system, I removed some of your data object properties for brevity.
@amusleh
amusleh
25 Jun 2021, 17:22
Hi,
Yes, you can use CheckBox and RadioButton chart controls, there are some examples on API references, please check the links.
@amusleh
amusleh
23 Jun 2021, 16:50
Hi,
Use IndicatorArea instead of Chart for drawing:
IndicatorArea.DrawStaticText("text", indicator_output, VerticalAlignment.Center, HorizontalAlignment.Center, Color.Black);
@amusleh
amusleh
23 Jun 2021, 16:48
RE: RE:
Hi,
The problem is you are creating two new chart controls on each tick, and you plot the new ones on top of old ones, please use the below code instead:
using cAlgo.API;
using cAlgo.API.Internals;
using System;
namespace cAlgo.Indicators
{
[Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
public class DrawSpread : Indicator
{
private TextBlock _spreadTextBox, _candleTextBox;
[Parameter("Spread Color", DefaultValue = "Yellow")]
public string SpreadColor { get; set; }
[Parameter("Candle Color", DefaultValue = "White")]
public string CandleColor { get; set; }
protected override void Initialize()
{
_spreadTextBox = new TextBlock
{
BackgroundColor = Color.Red,
ForegroundColor = Color.White,
Padding = "8, 4",
VerticalAlignment = VerticalAlignment.Top,
HorizontalAlignment = HorizontalAlignment.Left,
Margin = "5, 40, 0, 0",
Width = 100,
};
Chart.AddControl(_spreadTextBox);
_candleTextBox = new TextBlock
{
BackgroundColor = Color.Blue,
ForegroundColor = Color.White,
Padding = "8, 4",
VerticalAlignment = VerticalAlignment.Top,
HorizontalAlignment = HorizontalAlignment.Left,
Margin = "5, 65, 0, 0",
Width = 100,
};
Chart.AddControl(_candleTextBox);
}
public override void Calculate(int index)
{
if (IsLastBar)
DisplayOnChart();
}
private void DisplayOnChart()
{
var close = Bars.ClosePrices.Last(0);
var open = Bars.OpenPrices.Last(0);
double size;
if (close < open)
{
size = Math.Round((open - close) / Symbol.PipSize, 2);
}
else
{
size = Math.Round((close - open) / Symbol.PipSize, 2);
}
_spreadTextBox.Text = string.Format("Spread: {0:f2}", Symbol.Spread / Symbol.PipSize);
_candleTextBox.Text = string.Format("Candle: {0}", size);
}
}
}
@amusleh
amusleh
22 Jun 2021, 19:57
RE:
khoshroomahdi said:
i know that. but i want dynamic time zone. when user change time zone in ctradr indicator should change.
Hi,
You can use the Application.UserTimeOffset to get the user Time zone offset, and if user change the time zone you can use the Application.UserTimeOffsetChanged event to get user new time zone offset.
Check the example code of Application on API references.
@amusleh
amusleh
22 Jun 2021, 17:38
RE: RE: RE: RE: Gratitude
falkyw said:
But, I intended to open a new buy or sell position after closing 3 candles.
Specifically on the renko chart.This mod would be for closing the position, right?
The above code is for closing a position after three bars, not for opening a new one.
Please read the API references and you will be able to do it, or post a job request.
@amusleh
amusleh
21 Jun 2021, 19:45
( Updated at: 21 Jun 2021, 19:47 )
Hi,
Right now we don't any library for Python or C++, we only have a .NET library.
We will develop more libraries and we will have one for Python in upcoming months.
Open API uses Google Protocol Buffers protocol, its Language agnostic and you can interact with it easily, please check Open API documentation for more detail.
@amusleh
amusleh
21 Jun 2021, 14:51
RE: RE:
jumel.donatien said:
Hi amusleh,
I have another question: When I launch the robot, the form opens and if I want to change the action of the Buy Button (for example) to draw text on chart, it doesn't work.. I think, it's because when the form is launched, the chart is not activated..
Do you have a solution?
Here is the code changed in MainForm.cs:
private void BtnBuy_Click(object sender, System.EventArgs e)
{
_robot.ExecuteMarketOrder(TradeType.Buy, _robot.SymbolName, _robot.Symbol.VolumeInUnitsMin);_robot.ChartObjects.DrawText("Sample Text", "Sample Text", StaticPosition.Center);
}Thank you in advance!
Hi,
Invoke it on robot main thread:
private void BtnBuy_Click(object sender, System.EventArgs e)
{
_robot.ExecuteMarketOrder(TradeType.Buy, _robot.SymbolName, _robot.Symbol.VolumeInUnitsMin);
_robot.BeginInvokeOnMainThread(() => _robot.Chart.DrawStaticText("Sample Text", "Sample Text", VerticalAlignment.Bottom, API.HorizontalAlignment.Center, Color.Red));
}
@amusleh
amusleh
18 Jun 2021, 20:23
Hi, Its an issue, thanks for reporting, we will fix it in future versions, in meantime you can use the Automate API references.
@amusleh
amusleh
18 Jun 2021, 20:21
Hi,
When you post code please use the editor "Insert Code Snippet" option.
Regarding your issue, you can ask one of our consultants to modify your cBot code or post a job request.
@amusleh
amusleh
18 Jun 2021, 20:19
RE: RE: Gratitude
falkyw said:
amusleh said:
Hi,
You can open a buy/sell market order by using ExecuteMarketOrder method, and you can pass the stop loss/take profit in Pips.
The order will be executed based on symbol bid/ask price, check the code examples of Position.
You can use OnBar method on a Renko chart to execute your orders per bar, or use the OnTick method to count the Pips by your self.
Thank you for answering Amusleh
Can I execute a new order after the closing of 3 candles on the renko chart of pips? (without third party indicators)
What would be the coding for this?
Hi,
Yes, you can do it, you just have to count the number of bars and if three bars were passed close the position, ex:
using cAlgo.API;
using System;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class NewcBot : Robot
{
protected override void OnBar()
{
var index = Bars.Count - 1;
foreach (var position in Positions)
{
// if position symbol is not same as our chart symbol we skip over it
if (!position.SymbolName.Equals(SymbolName, StringComparison.OrdinalIgnoreCase)) continue;
// We get the bar Index of position entry time
var positionEntryBarIndex = Bars.OpenTimes.GetIndexByTime(position.EntryTime);
// If 3 or more bars passed since position entry time then we close it
if (index - positionEntryBarIndex >= 3)
{
ClosePosition(position);
}
}
}
}
}
@amusleh
amusleh
18 Jun 2021, 20:11
Hi,
cTrader Automate API gives you two option for drawing on charts:
- Chart Controls
- Chart Objects
The first one is static and doesn't depend on your chart price and time axis, the second one is more dynamic and you can position it based on chart price and time axis.
For your case I thing you should use ChartText not chart controls.
To allow user to interact with your chart object (change font size, color,...) set its IsInteractive property to True.
First call the Chart.DrawText and save the returning ChartText object on a variable, then set its IsInteractive property to True:
// You can also use time instead of BarIndex
var chartText = Chart.DrawText("Text", "My text", barIndex, price, color);
chartText.IsInteractive = True;
// If you want to lock the object position and only allow user to change // text properties set its IsLocked to True
chartText.IsLocked = True;
Checkout the ChartText example on API references and if you need a more advanced sample check the Pattern Drawing indicator code.
@amusleh
amusleh
18 Jun 2021, 16:57
( Updated at: 18 Jun 2021, 16:58 )
Hi,
You should not use Print method inside property setter method, this works fine:
using cAlgo.API;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class Baseline : Robot
{
[Parameter("Risk (%)", DefaultValue = 2.0, MinValue = 1.0, MaxValue = 5.0, Step = 1.0, Group = "Risk Management")]
public double RiskPercentage
{
get
{
return riskPercentage;
}
set
{
riskPercentage = SetRisk(value);
}
}
private double riskPercentage;
protected override void OnStart()
{
RiskPercentage = 4.0;
}
protected override void OnBar()
{
}
protected override void OnTick()
{
}
private double SetRisk(double value)
{
return value;
}
}
}
And Strategy is null when you access it inside setter method, that can also cause this issue, because OnStart is not called yet.
@amusleh
amusleh
16 Jun 2021, 11:53
( Updated at: 16 Jun 2021, 11:55 )
Hi,
You can open a buy/sell market order by using ExecuteMarketOrder method, and you can pass the stop loss/take profit in Pips.
The order will be executed based on symbol bid/ask price, check the code examples of Position.
You can use OnBar method on a Renko chart to execute your orders per bar, or use the OnTick method to count the Pips by your self.
@amusleh
amusleh
02 Jul 2021, 18:42
Hi,
You can use Position.Pips property to get the amount of Pips of a position, you don't have to calculate it by yourself:
Please read the API references and take a look on examples.
@amusleh