Topics
Replies
firemyst
30 Aug 2020, 12:28
Have you looked at the online guides @Spotware have posted?
https://help.ctrader.com/ctrader-automate/guides/trading_api
As for me, I went the cTrader route because it uses C#, which to me is easier because I already knew it. :-)
MT5 will definitely have more support and more options available though because that seems to be the standard in the industry MetaTrader.
If you plan to do any other kind of programming other than for bots/indicators (eg, writing your own Windows applications or whatever), then you should learn C#; otherwise it's up to you.
@firemyst
firemyst
26 Aug 2020, 14:24
This is relatively easy.
See code example below. You'll obviously have to make adjustments for it to fit in your code.
//you need to set this up as a parameter
StopBotWhenLossesFallBelow
double _runningTotalsGainLoss;
string _positionLabel;
private void Positions_Closed(PositionClosedEventArgs args)
{
//Only run this method if it's this instance that closed.
Position p1 = args.Position;
if (p1.SymbolName == Symbol.Name && p1.Label == _positionLabel)
{
//Now get the historical trade stuff.
HistoricalTrade ht = History.FindLast(p1.Label, p1.SymbolName, p1.TradeType);
//Running Totals
_runningTotalsGainLoss += p1.NetProfit;
Print("PC20: Running total for \"{0}\": {1}", p1.Label, String.Format("{0:$#,###.00}", _runningTotalsGainLoss));
if (_runningTotalsGainLoss < StopBotWhenLossesFallBelow)
{
Print("WARNING! Running total {0} has fallen below StopBotWhenLossesFallBelow {1} threshold! Stopping bot for \"{2}\"!", String.Format("{0:$#,###.00}", _runningTotalsGainLoss), String.Format("{0:$#,###.00}", StopBotWhenLossesFallBelow), p1.Label);
Stop();
}
}
}
@firemyst
firemyst
17 Aug 2020, 12:43
Serialize it to JSON, save the JSON to a text file.
Then when you restart and restart your bot/indicator, in the OnStart or Initialize methods, you can read the json back in and convert it back to a 2-dimensional array.
Example code:
//In the OnStart method:
// read saved file into a string and deserialize JSON to a type
RobotInfoClass ric = null;
if (System.IO.File.Exists(_savedFilePath))
{
ric = JsonConvert.DeserializeObject<RobotInfoClass>(System.IO.File.ReadAllText(_savedFilePath));
System.IO.File.Delete(_savedFilePath); //clean up since we no longer need it
}
///////////////////////////////////////
//In the OnStop method:
using (System.IO.StreamWriter sw = new System.IO.StreamWriter(_savedFilePath))
{
using (JsonWriter writer = new JsonTextWriter(sw))
{
RobotInfoClass ric = new RobotInfoClass();
ric._positionEntryPricePoints = _positionEntryPricePoints;
ric._positionEntryPriceTimes = _positionEntryPriceTimes;
ric._breakEvenPoints = _breakEvenPoints;
ric._increasePositionSizePoints = _increasePositionSizePoints;
//blah blah blah
ric._savedTime = DateTime.Now;
JsonSerializer serializer = new JsonSerializer();
serializer.Formatting = Formatting.Indented;
serializer.Serialize(writer, ric);
}
}
@firemyst
firemyst
17 Aug 2020, 12:35
It can be found here:
https://ctrader.com/algos/indicators/show/555
Enjoy.
@firemyst
firemyst
17 Aug 2020, 12:21
( Updated at: 21 Dec 2023, 09:22 )
HI Stephan:
I find this easiest to do is code up your reference DLL in the "documents \ calgo \ sources" folder.
When it compiles there:
Then in cTrader in "Automate", select the Indicator/bot you want, and from the 3 vertical dots, select the option to "Manage references":
Then you should find it under the "Libraries" side menu. If it's not there, click the "browse" button in the top right of the window and add it in.
Lastly, launch your visual studio project and viola, it'll be included.
I've had too many issues if I try and go the other way -- adding the reference from within VS without doing it through cTrader.
Hope this helps!
@firemyst
firemyst
15 Aug 2020, 17:05
RE:
luca.tocchi said:
hi I need to print "ok"
print ("ok");
when the price is 60 pips above the current price
thanks
Get Symbol.Bid or Symbol.Ask price (whichever one you want to measure from) and then add 60 pips:
Symbol.Bid + (60 * Symbol.PipSize)
Symbol.Ask + (60 * Symbol.Pipsize)
@firemyst
firemyst
15 Aug 2020, 17:03
RE:
tradermatrix said:
Hi
I have built a robot with several signals independent of each other, with a different label per signal.
for example :
RobotID_A1
RobotID_A2
RobotID_A3
RobotID_A4
so 4 positions are possible together
I would like to limit to 2 open positions (the robot chooses the 2 best signals depending on the market)
but how to proceed with different labels.
cordially.
Your question doesn't make sense and isn't clear.
What do you want to happen?
@firemyst
firemyst
15 Aug 2020, 14:07
RE: RE: Platform updates
Symposium said:
Firemyst... Are you serious?...... 15 Indicators on any chart is your issue!..... Not Spotware's..... They have added a delete button to the Indicators popup panel....
<Left click>, <Right click>.... Indicator Gone!..... Makes removal of any unwanted Indicators simple. A great update to the Platform. The only other Platform (Retail) even on the same page as Ctrader is TradingView's
TWB
TWB: you missed the point. The number of indicators is irrelevant. It's the number of clicks users have to go through now for indicators cTrader doesn't allow you to click on to remove, that provides valuable information or functionality cTrader lacks.
Let's say you have just two indicators. Or better yet, let's just say one. Use the example one I linked to above.
Add it to your chart.
Now see how you can delete it without going through an indicator's menu.
I rest my case.
There are numerous indicators out there like this people use.
It now takes more time for users to accomplish the same action than previously.
That's not good UI design principles.
PS: if you think Trading View is the only other app, you obviously haven't looked at Pro Real Time or ThinkTrader. :-)
@firemyst
firemyst
14 Aug 2020, 12:09
RE:
PanagiotisCharalampous said:
Hi firemyst,
You can edit/delete an indicator if you just right click on it inside the chart.
Best Regards,
Panagiotis
Hi @Panagiotis:
As a follow up, you can't do this with every indicator, which makes it even worse.
For example, here's one it can't be done with:
https://ctrader.com/algos/indicators/show/2209
Add it to your chart, and see if you can "right-click" to edit the properties or delete it.
Now imagine you have that on your chart with a few other indicators like PSAR and BollingerBands.
You can't do anything with unless you go through double the amount of mouse clicks introduced in v3.8 as opposed to v3.7.
It's frustrating the end user experience.
@firemyst
firemyst
14 Aug 2020, 08:44
RE:
PanagiotisCharalampous said:
Hi firemyst,
You can edit/delete an indicator if you just right click on it inside the chart.
Best Regards,
Panagiotis
Yes, but it still involves more clicks than it use to from the side menu. For example, to delete an indicator, I have to right click on each one, and click delete. Then move mouse, right click on another one, clicking delete, etc.
From the menu, I used to be able to just go right down the list and click "x". Half the time that wouldn't even involve moving the mouse to click the next tiny "x".
I appreciate what the team tried to do, but I think it's simpler and easier for the user (with less clicks) to separate the "indicators" and "drawings" objects into their own menus instead of being combined.
Especially for those of us (like myself) who typically don't have any drawings on a chart, it's just more unnecessary clicks users have to go through.
@firemyst
firemyst
13 Aug 2020, 09:20
RE: my code worked perfectly until ...
samuel.jus.cornelio said:
My code was working perfectly until I added a trailing stop and now nothing else works. Could someone tell me how I can solve this problem????
Thankss
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 bot : Robot { [Parameter(DefaultValue = 0.0)] public double Parameter { get; set; } [Parameter("Source")] public DataSeries Source { get; set; } [Parameter("Periods", DefaultValue = 14)] public int Periods { get; set; } [Parameter("Stop Loss (pips)", DefaultValue = 20, MinValue = 1)] public int StopLoss { get; set; } [Parameter("Volume", DefaultValue = 10000, MinValue = 1000)] public int Volume { get; set; } [Parameter("Take_Profit", DefaultValue = 45, MinValue = 10)] public int TakeProfit { get; set; } [Parameter("Begin Trading Hour", DefaultValue = 5.0)] public double Begin { get; set; } [Parameter("Ending Trading Hour", DefaultValue = 19.0)] public double Ending { get; set; } [Parameter("Trigger When Gaining", DefaultValue = 50)] public double TriggerWhenGaining { get; set; } [Parameter("Trailing Stop Loss Distance", DefaultValue = 1)] public double TrailingStopLossDistance { get; set; } [Parameter("Step (pips)", DefaultValue = 10)] public double Step { get; set; } [Parameter("Buy")] public bool Buy { get; set; } private double _highestGain; private bool _isTrailing; private DateTime startTime; private DateTime endTime; public RelativeStrengthIndex _rsi; private ExponentialMovingAverage _Ema1; protected override void OnStart() { } protected override void OnTick() { { startTime = Server.Time.Date.AddHours(Begin); endTime = Server.Time.Date.AddHours(Ending); if (Trade.IsExecuting) return; bool tradeTime = false; if (Begin < Ending) tradeTime = Server.Time.Hour >= Begin && Server.Time.Hour < Ending; if (Ending < Begin) tradeTime = Server.Time.Hour >= Begin || Server.Time.Hour <= Ending; if (!tradeTime) return; } _rsi = Indicators.RelativeStrengthIndex(Bars.ClosePrices, 48); _Ema1 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 6); { if (_rsi.Result.LastValue < 45) if (_Ema1.Result.LastValue == Symbol.Ask) ExecuteMarketOrder(TradeType.Sell, Symbol, Volume, "bot", StopLoss, TakeProfit); } { if (_rsi.Result.LastValue > 55) if (_Ema1.Result.LastValue == Symbol.Bid) ExecuteMarketOrder(TradeType.Buy, Symbol, Volume, "bot", StopLoss, TakeProfit); var position = Positions.Find("SampleTrailing"); if (position == null) { Stop(); return; } //If the trigger is reached, the robot starts trailing if (position.Pips >= TriggerWhenGaining) { //Based on the position's direction, we calculate the new stop loss price and we modify the position if (position.TradeType == TradeType.Buy) { var newSLprice = Symbol.Ask - (Symbol.PipSize * TrailingStopLossDistance); if (newSLprice > position.StopLoss) { ModifyPosition(position, newSLprice, null); } } else { var newSLprice = Symbol.Bid + (Symbol.PipSize * TrailingStopLossDistance); if (newSLprice < position.StopLoss) { ModifyPosition(position, newSLprice, null); } } TriggerWhenGaining += Step; } } } protected override void OnStop() { // Put your deinitialization logic here } } }
Whether or not this is the issue, your code will fail and not move the SL if the Symbol.Spread is greater than the Trailing stop distance specified.
For example, with your parameters I see you have a default value of "1" for trailing stop loss distance.
If the spread is 1.1 pips of more, how can you trail a stop loss by 1 pip from the Ask price? You'd be inside the spread, and thus be knocked out of your position (if it even lets you set that).
So in your code you also need to check that
Symbol.Ask - (Symbol.PipSize * TrailingStopLossDistance)
is also > Symbol.Spread distance between the Ask and Bid prices.
Basically, put a check in there that it's also lower than the bid price.
Example:
if (newSLprice > position.StopLoss && newSLprice < Symbol.Bid)
Similarly:
if (newSLprice < position.StopLoss && newSLprice > Symbol.Ask)
@firemyst
firemyst
13 Aug 2020, 07:11
RE: Stop Loss at previous days low or previous days high
samuelbreezey said:
Hi Guys
I am trying to get my stop loss on a execute at market to be @ the previous days low. My code does'nt seem to work :( may be something simple...
Help needed please.
Try posting some code so people can see what you're doing wrong..
@firemyst
firemyst
13 Aug 2020, 07:10
RE:
samuel.jus.cornelio said:
Hello everyone, I'm on my next project now and I need a little help. I'm wondering how exactly I would encode an action that recognizes whether the bar has touched an indicator or not. I'm trying to code an EMA and I need to know if the current price is touching the EMA Thanks for an answer,
This may involve rounding depending on what you consider "touching".
For example, using the PSAR. It's current value could be 1.4587357697 but the current "bid" or "ask" price could be 1.45873.
Is that touching or not?
You also have to determine if you consider if it should be the "bid" or "ask" (or perhaps both) values that touch the price.
@firemyst
firemyst
13 Aug 2020, 07:05
( Updated at: 21 Dec 2023, 09:22 )
RE:
Nabhanyusaf said:
It would be great if the indicator could be visualized on a separate timeframe like one indicator on one customized timeframe instead of being on every timeframe. like in MT4
They can be in a sense, but you have to code it yourself.
For example, on this M2 chart, I have 2 sets of 55 EMAs (the big colorful lines), 2 SuperTrends, and 2 sets of PSARs
The blue PSARs, dashed ST line, and dark blue 55 line is on the M5 timeframe; the white PSARs, whiteish road, and solid ST line is the M2 timeframe.
@firemyst
firemyst
03 Aug 2020, 06:35
RE:
samuel.jus.cornelio said:
Please, how can I use an indicator array for a bot. For example, an array with several RSI contained. I am trying and not succeeding, if anyone can help I will be grateful
Here's a very simple example using MovingAverages instead:
//class declaration
MovingAverage[] _maArray;
//In OnStart (cBot) or Initialize (indicator)
if (_maArray != null)
{
//Clear out old data everytime we start so GC can collect
Array.Clear(_maArray, 0, _maArray.Length);
_maArray = null;
}
_maArray = new MovingAverage[theNumberOfMAObjectsYouWantToHave];
for (int x=0; x < _maArray.Length; x++)
{
_maArray[x] = Indicators.MovingAverage(Bars.ClosePrices, thePeriodToUse, theMATypeToUse);
}
@firemyst
firemyst
30 Aug 2020, 12:43
Example code for quick tip:
Hope this helps :-)
@firemyst