Topics
Replies
firemyst
24 Sep 2021, 03:41
( Updated at: 21 Dec 2023, 09:22 )
RE:
ome9emmy said:
Good day CTrader developers can we get a breakeven button while using the manual strategy backtesting. And also multi chart mode to switch between two different timeframe. ????❤️
THe latter you already have:
Just click the different time frame to change the chart.
The former -- you don't explain what you want. OKay. You want a button labelled "break even". So what do you expect it to do? What do you want it to do and when?
You're very vague, and need to be more specific when posting questions/requests.
@firemyst
firemyst
24 Sep 2021, 03:37
( Updated at: 21 Dec 2023, 09:22 )
RE:
vmtxd07 said:
Hi all.
I'm seeing the code in Automate of ctrader. I don't know how to get value of the Source after choose etc, Open or Close or High ...
I know DataSeries Source will return Source of bar will using as the data input.
Thanks !
[Parameter("Source")] public DataSeries Source { get; set; }
What "value" are you trying to get?
1) The actual decimal value of the SMA? If so, then create your indicator similar to as follows:
Indicators.MovingAverage(DataSource source, int periods, MovingAverageType maType)
and get its value every time you need it.
2) the value of the type of source selected? Then you can use @Panagiotis' suggestion by creating your own enum:
public enum MASource_Options
{
High,
Low,
Open,
Close
}
and using that as the parameter type:
[Parameter("Source", DefaultValue = MASource_Options.Close)]
public MASource_Options SMASource { get; set; }
@firemyst
firemyst
22 Sep 2021, 10:17
RE: RE: RE: RE: RE:
waym77 said:
firemyst said:
Have you tried passing in the MA objects in the "constructor" to your TradingPanel inner class?
You'll have to create the Constructor with the appropriate parameters.
Hi there, forgive me, I am not very familiar with constructor arguments.
Would it look something like below?
public TradingPanel(MovingAverage TrendMA, Robot robot, Symbol symbol, double defaultPrice, double defaultFrag, double defaultLots, double defaultRisk, double defaultStopLossPips, double defaultTakeProfitPips) { TrendMA = Indicators.MovingAverage(Bars.ClosePrices, TrendPeriods, MovingAverageType.Exponential); _robot = robot; _symbol = symbol; AddChild(CreateTradingPanel(defaultPrice, defaultFrag, defaultLots, defaultRisk, defaultStopLossPips, defaultTakeProfitPips)); }
I understand I'll also have to create new parameters for values like TrendPeriods in this class.
Thanks,
For your constructor, you would just have something similar to the following:
//In your other outer class, create the MA object as you normally would in the OnStart method;
//then after all the MA's are created, put in your
var tradingPanel = new TradingPanel(TrendMA, this, Symbol, ...);
//Now alter your TradingPanel class similar to the following.
public class TradingPanel : CustomControl
{
private MovingAverage _trendMA;
//All classes I believe have to have the default constructor
public TradingPanel() {}
public TrandingPanel(MovingAverage TrendMA, Robot r, Symbol s, ... )
{
_trendMA = TrendMA;
_robot = r;
_symbol = s;
// etc etc etc
}
}
If you can't get the above to work or it doesn't recognize the MovingAverage object declaration in the TradingPanel class, then that class probably can't reference the MovingAverage object, and you may have to ask @Panagiotis to lend his expert knowledge.
@firemyst
firemyst
22 Sep 2021, 04:41
RE:
riccardo.buttari said:
From my indicator, calling MarketData.GetSeries with a symbol other than the current one,
I get only the last 2000 most recent bars (even if I scroll the chart further back) and this does not allow me to perform backtests.
Is there a way to get more bars or set a start date?
Thanks
Try what's on this thread:
@firemyst
firemyst
22 Sep 2021, 04:39
RE:
hamsider said:
Hello, I try to to draw trend lines like from Day start to current index (0), Week start to current index (0) and Month start to current index (0). Any help how to get the index of Day start, Index of Week start and Index of Month Start.
Ref:Here the trend line is from session start to session end.
Thank you.
Look at this thread:
@firemyst
firemyst
22 Sep 2021, 04:38
RE:
PanagiotisCharalampous said:
Hi yaghouti,
At the moment commission information is not available in cTrader Automate API. Spread is not really relevant to this calculation since it is embedded in the actual price.
Best Regards,
Panagiotis
Join us on Telegram and Facebook
What about this? Although you can only obtain it _after_ a position is opened:
@firemyst
firemyst
21 Sep 2021, 03:38
RE:
ctid4633759 said:
Hi,
I am trying to create a simple calculation wherein a downtrend, a distance is measured as HighPrices.LastValue - Price, and in an uptrend the distance is Price - LowPrices.LastValue.
Without Math.Round, I get a very long decimal. With it, I get 0.
See attached code, any advice? Thanks.
using System; using cAlgo.API; using cAlgo.API.Internals; using cAlgo.API.Indicators; using cAlgo.Indicators; namespace cAlgo { [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class SLDisplay : Indicator { [Parameter("MA Type", Group = "MA", DefaultValue = MovingAverageType.Simple)] public MovingAverageType MaType { get; set; } [Parameter("Vertical Alignment", DefaultValue = VerticalAlignment.Bottom)] public VerticalAlignment slvAlignment { get; set; } [Parameter("Horizontal Alignment", DefaultValue = HorizontalAlignment.Center)] public HorizontalAlignment slhAlignment { get; set; } private ChartStaticText details; private string _sl; MovingAverage FastMa; MovingAverage SlowMa; MovingAverage TrendMa; protected override void Initialize() { details = Chart.DrawStaticText("idtext_white", string.Empty, this.slvAlignment, this.slhAlignment, Color.White); FastMa = Indicators.MovingAverage(Bars.ClosePrices, 9, MaType); SlowMa = Indicators.MovingAverage(Bars.ClosePrices, 21, MaType); TrendMa = Indicators.MovingAverage(Bars.ClosePrices, 50, MaType); } public override void Calculate(int index) { _sl = GetSL(); details.Text = "SL: " + _sl; details.Color = Color.White; } private string GetSL() { var trend = Bars.ClosePrices.LastValue > TrendMa.Result.LastValue ? true : false; var fast = FastMa.Result.LastValue > SlowMa.Result.LastValue ? true : false; var price = (Symbol.Ask + Symbol.Bid) / 2; var distance = 0.0; var buyorsell = trend && fast ? true : false; if (buyorsell) { distance = (price - Bars.LowPrices.LastValue) * Symbol.PipSize; } if (!buyorsell) { distance = (Bars.HighPrices.LastValue - price) * Symbol.PipSize; } if (distance < 0.1) { return "N/A"; } else return Math.Round(distance, 1).ToString(); //return distance.ToString(); } } }
One suggestion in your code. If you want your code to be dynamic and always round to the number of places based on the symbol you're watching, I would do:
Math.Round(distance, Symbol.Digits)
instead. So for example, if you're trading the EURUSD, it'll round to 4 digits; if trading any JPY pairs, it'll round to 2 digits; if trading the DOW or DAX, it'll round to 1 digit, etc etc.
That aside, you should read this on how to format decimal string numbers in C#:
@firemyst
firemyst
21 Sep 2021, 03:30
RE:
waym77 said:
Hi all,
I'm having trouble using an indicator in a separate class from the Robot (Main) class.
In the Robot class, I have the parameters and declarations for using an EMA, but since that class is separate from the other public class in which I wish to use the EMA Result, I get an error saying ''Error CS0103: The name 'TrendMA' does not exist in the current context".
I understand that this is because the EMA is local to the Main Robot class, though I'm having trouble calling the indicator into the class where I want to use it.
The short of my question is then: how can I call and declare an indicator in a class that is not the Main Robot class?
Please excuse my lack of code sample, the source for this bot is long, although I can provide it on request.
Thanks,
In short, without seeing any sample code posted of yours:
1) you need to "reference" the class. In the cTrader Automate section when you view your bot's source code, click on the triple-dot menu to manage references and make sure it's included
2) reference your TrendMA indicator similar to the following:
TrendMA _ma = Indicators.GetIndicator<TrendMA>(the list of parameters required);
@firemyst
firemyst
07 Sep 2021, 03:07
( Updated at: 07 Sep 2021, 03:28 )
RE: RE: RE:
hao.han said:
Hi firemyst,
Thanks a lot for your reply. I had thought of this idea and my only concern was the synchronicity because different symbols will be experiencing ticks at different times. At extreme times, a FX symbol may have no ticks for many seconds or even minute+. During such periods, an "on tick" event would not be triggered - thus leading to some cbots closing and some not. But having thought about it a bit more, perhaps this is not such a huge problem if some cbots are shut down slightly behind others. thanks again!
Okay. So what? :-)
instead of having each bot instance close its own position, in all onTick methods, close ALL positions regardsless.
//Checks the equity of the account
if (Account.Equity <= someValue)
{
//If we have any positions open, close them
foreach (Position p in Positions)
p.Close();
Stop(); //Stop this bot instance
}
else
{
//keep going and do whatever
}
//////////////////////////
//Another example: if you want, keep the positions in profit going with a TSL
//so you can keep building up your equity
//Checks the equity of the account
if (Account.Equity <= someValue)
{
//If we have any positions open, close them
foreach (Position p in Positions)
{
//but for those already in profit, set a TSL so we can keep reaping pay day
if (p.Pips > 5)
{
//Move to at least break even before doing so if our
//current SL isn't already past the break even point
if (p.TradeType == TradeType.Buy && p.StopLoss.GetValueOrDefault() < p.EntryPrice)
p.ModifyStopLossPrice(p.EntryPrice);
else if (p.TradeType == TradeType.Sell && p.StopLoss.GetValueOrDefault() > p.EntryPrice)
p.ModifyStopLossPrice(p.EntryPrice);
p.ModifyTrailingStop(true);
}
else
p.Close();
}
Stop(); //Stop this bot instance
}
else
{
//keep going and do whatever
}
//////// blah blah blah :-)
@firemyst
firemyst
06 Sep 2021, 16:01
RE:
hao.han said:
Hi, I was someone could help me with some suggestions on how to solve this problem:
High level issue: I have a portfolio of trading cBots running (so 2 or more). How can I halt all trading if account equity falls below X, akin to an "account/portfolio stop loss", until instructed otherwise.
Elaboration: I do not necessarily care exactly how the effect of the stop loss achieved. For example, there may be a variable in a cBot that acts like a switch to say if trades can/cannot be executed. Or something that automatically switches off all cBots (after first closing all positions). But most importantly, simply "closing all positions" is not sufficient as I want to prevent all cBots from opening further trades until instructed otherwise (which can be either manual or by code - such as "wait Y hours, then allow trades again").
I read briefly in another forum about potentially using "named pipes", but my programming skills are not amazing, and this seems like quite a difficult way to achieve the desired effect.
Any thoughts/suggestions would be greatly appreciated (an example would be amazing also).
Thank you
IN each bot, in the OnTick method, just check the equity of your account:
//Get your position if any
Position p = Positions.Find(someLabel, Symbol.Name);
//Checks the equity of the account
if (Account.Equity <= someValue)
{
//If we have a position open, close it
if (p != null)
p.Close();
Stop(); //Stop this bot instance
}
else
{
//keep going and do whatever
}
@firemyst
firemyst
30 Aug 2021, 17:54
RE:
amosmsiwa said:
In trying to keep the programming code as clean as possible, can the CRL indentify these as identical statements or not?
if ((_macdH.Histogram.LastValue > _macdH.Signal.LastValue) && (_macdH.Histogram.LastValue - _macdH.Signal.LastValue > 0))
{
if ((_stochO.PercentK.LastValue > _stochO.PercentD.LastValue) || (_stochO.PercentK.LastValue > 50))
{
if ((_rsi.Result.LastValue > 51) && (_pSar.Result.LastValue < MarketSeries.Close.LastValue))
{
Print("BUY...." + this.Symbol);
}
}
if ((_macdH.Histogram.LastValue > _macdH.Signal.LastValue) && (_macdH.Histogram.LastValue - _macdH.Signal.LastValue > 0)) &&((_stochO.PercentK.LastValue > _stochO.PercentD.LastValue) || (_stochO.PercentK.LastValue > 50))(_rsi.Result.LastValue > 51) && (_pSar.Result.LastValue < MarketSeries.Close.LastValue))
{
Print("BUY...." + this.Symbol);
}
This should work for you:
if (
((_macdH.Histogram.LastValue > _macdH.Signal.LastValue) && (_macdH.Histogram.LastValue - _macdH.Signal.LastValue > 0))
&&
((_stochO.PercentK.LastValue > _stochO.PercentD.LastValue) || (_stochO.PercentK.LastValue > 50))
&&
((_rsi.Result.LastValue > 51) && (_pSar.Result.LastValue < MarketSeries.Close.LastValue))
)
{
Print("BUY...." + this.Symbol);
}
However, your original code may be better in the long run because it's already formatted for extra flexibility. For instance, if you're trying to understand why certain trades aren't happening, you would probably want to do something like this:
if ((_macdH.Histogram.LastValue > _macdH.Signal.LastValue) && (_macdH.Histogram.LastValue - _macdH.Signal.LastValue > 0))
{
if ((_stochO.PercentK.LastValue > _stochO.PercentD.LastValue) || (_stochO.PercentK.LastValue > 50))
{
if ((_rsi.Result.LastValue > 51) && (_pSar.Result.LastValue < MarketSeries.Close.LastValue))
{
Print("BUY...." + this.Symbol);
}
else if (_rsi.Result.LastValue <= 51)
{
Print("RSI last value {0} is not > 51", _rsi.Result.LastValue);
}
else if (_pSar.Result.LastValue >= MarketSeries.Close.LastValue)
{
Print("PSAR last value {0} >= MarketServers Close LastValue {1}", _pSar.Result.LastValue, MarketSeries.Close.LastValue);
}
}
else if (_stochO.PercentK.LastValue <= 50)
{
Print("Stoch %K last value {0} is <= 50", _stochO.PercentK.LastValue);
}
//
// ... etc etc etc ...
//
}
else if ( ... )
{
//
// ... etc etc etc ...
//
}
Then you can review the logs and fully grasp what is or isn't happening and why.
@firemyst
firemyst
30 Aug 2021, 17:29
RE:
ctid2032775 said:
Dear all,
maybe I am doing something wrong and someone of you can point me into the right direction...
My cBot runs an integrated optimization process OnStart and on specific circumstances (e. g. MDD increasing) that takes a lot of CPU and memory - i. e. quite "resource hungry". After this process is successfully finished the cBot is switched into "Trading" mode and starts trading OnBar.
At the beginning of the optimization process I want to print a static text (e. g. "Optimizing - EURUSD") and before start trading I want to print another static text (e. g. "Trading - EURUSD - Par1 = xxx - Par2 = yyy"; Par1 and Par2 are the results of the optimization) to the chart.
The small "beauty mistake" now is that the optimizing text is not output to the chart - is there a way to "force" the output even while the cBot is quite busy?
Many thanks in advance and best regards,
Christian
I would write the information out to the log because not all text/drawings on the chart are supported during back-testing as far as I'm aware.
Eg, if (IsBacktesting) { ... print your text to the log... } else { drawstatictext on chart }
@firemyst
firemyst
29 Aug 2021, 12:25
RE:
Nickachino said:
Hi,
I m trying to use 2 EMAs from a custom multi timeframe indicators. I get an error when I call the indicator in my cBot.
This is the indicator code:
using System;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
namespace cAlgo.Indicators
{
[Indicator(IsOverlay = true, TimeZone = TimeZones.UTC)]
public class MyMTFEMA : Indicator
{
[Parameter(DefaultValue = 8)]
public int EMAPeriods1 { get; set; }
[Parameter(DefaultValue = 21)]
public int EMAPeriods2 { get; set; }
[Parameter("EMA Timeframe1", DefaultValue = "Hour")]
public TimeFrame EMATimeframe1 { get; set; }
[Parameter("EMA Timeframe2", DefaultValue = "Hour")]
public TimeFrame EMATimeframe2 { get; set; }
[Output("EMA1", Color = Colors.Blue)]
public IndicatorDataSeries EMA1 { get; set; }
[Output("EMA2", Color = Colors.Red)]
public IndicatorDataSeries EMA2 { get; set; }
private MarketSeries series1;
private MarketSeries series2;
private ExponentialMovingAverage Ema1;
private ExponentialMovingAverage Ema2;
protected override void Initialize()
{
series1 = MarketData.GetSeries(EMATimeframe1);
series2 = MarketData.GetSeries(EMATimeframe2);
Ema1 = Indicators.ExponentialMovingAverage(series1.Close, EMAPeriods1);
Ema2 = Indicators.ExponentialMovingAverage(series2.Close, EMAPeriods2);
}
public override void Calculate(int index)
{
var index1 = GetIndexByDate(series1, MarketSeries.OpenTime[index]);
if (index1 != -1)
{
EMA1[index] = Ema1.Result[index1];
}
var index2 = GetIndexByDate(series2, MarketSeries.OpenTime[index]);
if (index2 != -1)
{
EMA2[index] = Ema2.Result[index2];
}
}
private int GetIndexByDate(MarketSeries series, DateTime time)
{
for (int i = series.Close.Count - 1; i > 0; i--)
{
if (time == series.OpenTime[i])
return i;
}
return -1;
}
}
}The I call it like this:
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 SIMPLEandPROFITABLEForexScalping : Robot
{
[Parameter("Risk %", DefaultValue = 0.02)]
public double RiskPct { get; set; }
[Parameter("EMA1 period", DefaultValue = 8)]
public int EMA1Period { get; set; }
[Parameter("EMA2 period", DefaultValue = 13)]
public int EMA2Period { get; set; }
[Parameter("EMA3 period", DefaultValue = 21)]
public int EMA3Period { get; set; }
private MovingAverage EMA1;
private MovingAverage EMA2;
private MovingAverage EMA3;
private MyMTFEMA MTFEMA;
protected override void OnStart()
{
// Put your initialization logic here
EMA1 = Indicators.MovingAverage(Bars.ClosePrices, EMA1Period, MovingAverageType.Exponential);
EMA2 = Indicators.MovingAverage(Bars.ClosePrices, EMA2Period, MovingAverageType.Exponential);
EMA3 = Indicators.MovingAverage(Bars.ClosePrices, EMA3Period, MovingAverageType.Exponential);
MTFEMA = Indicators.GetIndicator<MyMTFEMA>(8, 21, "Hour", "Hour");
}However I get an error when trying to run the cBot with this message:
31/12/2019 02:00:00.000 | Backtesting started
31/12/2019 02:00:00.000 | Crashed in OnStart with AlgoActivationException: Can not set "Hour" as a value for "EMATimeframe1" parameter
31/12/2019 02:00:00.000 | Backtesting was stopped
I have tried various ways to change the way I call the parameters using the 8, 21 and two "Hour" options but still get an error.
Any assistance would be appreciated.
Of course it's crashing there. You're passing in "Hour" as a string. The parameter is specifically for a TimeFrame object.
So you have to pass the timeframe similar to:
MTFEMA = Indicators.GetIndicator<MyMTFEMA>(8, 21, TimeFrame.Hour, TimeFrame.Hour);
@firemyst
firemyst
29 Aug 2021, 12:21
RE:
herculesone said:
Hello there!
I would like some help to make an indicator, which is fairly simple but does not show as I want it.
I would like to show the closing prices of different timeframes on the same chart. However, I am unable to make the chart match the output I want to show.
Here is the code:
using System;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
using cAlgo.Indicators;
namespace cAlgo
{
[Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class Closes_4hr_D_W_M_Q_Y : Indicator
{
[Output("4 Hour", LineColor = "Green", PlotType = PlotType.Points, Thickness = 2)]
public IndicatorDataSeries Hour4 { get; set; }
[Output("Daily", LineColor = "Black", PlotType = PlotType.Line, LineStyle = LineStyle.Solid, Thickness = 2)]
public IndicatorDataSeries Daily { get; set; }
[Output("Weekly", LineColor = "Red", PlotType = PlotType.Line, LineStyle = LineStyle.Solid, Thickness = 2)]
public IndicatorDataSeries Weekly { get; set; }
[Output("Monthly", LineColor = "Navy", PlotType = PlotType.Line, LineStyle = LineStyle.Solid, Thickness = 2)]
public IndicatorDataSeries Monthly { get; set; }
public Bars _daily, _4h, _weekly, _month;protected override void Initialize()
{
_4h = MarketData.GetBars(TimeFrame.Hour4);
_daily = MarketData.GetBars(TimeFrame.Daily);
_weekly = MarketData.GetBars(TimeFrame.Weekly);
_month = MarketData.GetBars(TimeFrame.Monthly);
}
public override void Calculate(int index)
{
Hour4[index] = _4h.ClosePrices[index];
Daily[index] = _daily.ClosePrices[index];
Weekly[index] = _weekly.ClosePrices[index];
Monthly[index] = _month.ClosePrices[index];
}
}
}
I would expect that on a 1 hour chart, the Daily output would show as a straight line until the next day, when there would be another straight line etc. Instead, the indicators paint further back as if they are attached to another chart.
It is like the "index" applies to the chart I am calling and not the "index" of the applicable chart, which does make sense in a way but I want to work around it and cannot figure out how.
In essence when I call "index" of a 1 hour chart, the price on the daily chart of the same index should be the same until all the hours are complete.
Any help is appreciated, thank you!
The index of the current chart won't be the same as the index on the other timeframe charts.That's why you're having the issue. For all the timeframes, you're getting the current index on the chart you're viewing. Since there's significantly more bars on the H4 chart than there are in the D1 chart for the day, you're going to have multiple incorrect readings.
For instance, when viewing the H4 chart, you need to get the corresponding index on the D, W, and M charts.
//Example code to get the correct Daily index on the H4 chart in the Calculate method.
//This code assumes you'll always be looking at the H4 chart.
int altIndexD1 = _daily.OpenTimes.GetIndexByTime(Bars.OpenTimes[index]);
@firemyst
firemyst
24 May 2021, 16:58
RE:
PanagiotisCharalampous said:
Hi firemyst,
Check Chart.Drag and Chart.ObjectsUpdated events.
Best Regards,
Panagiotis
Thanks for that.
Another question. I have the following sample code -- see my question in the commented code:
using System;
using System.Collections.Generic;
using cAlgo.API;
using cAlgo.API.Indicators;
namespace cAlgo.Indicators
{
[Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
public class Test : Indicator
{
private ChartHorizontalLine _chl;
private double _value;
protected override void Initialize()
{
_value = MarketData.GetBars(Chart.TimeFrame, Symbol.Name).ClosePrices.LastValue;
_chl = Chart.DrawHorizontalLine("test line", _value, Color.Goldenrod, 2, LineStyle.Solid);
_chl.IsInteractive = true;
Chart.ObjectsUpdated += LineUpdated;
}
public override void Calculate(int index)
{
}
//When I drag the horizontal line created on the chart, why does this method get called numerous times?
//Every time I drag the line, if I set a breakpoint on the opening curly brace, this method gets hit for each
//object on the chart.
//Is there a way to to reduce this so it only gets called for horizontal line objects?
private void LineUpdated(ChartObjectsUpdatedEventArgs args)
{
ChartHorizontalLine obj = (ChartHorizontalLine)args.Chart.FindObject("test line");
if (obj != null && obj.Y != _value)
{
_value = obj.Y;
Chart.DrawStaticText("value", _value.ToString(), VerticalAlignment.Top, HorizontalAlignment.Right, Color.Goldenrod);
}
}
}
}
@firemyst
firemyst
27 Sep 2021, 08:54
Use "Chart.DrawText" and put in your "level" parameter for the "double y" parameter.
Eg:
Chart.DrawText("line_2_text", "here is my text I want to draw", theBarIndex, level, Color.Red);
@firemyst