Topics
Replies
firemyst
22 Sep 2019, 15:53
RE:
ryanoia@gmail.com said:
Hello,
Is there any way to prevent the cbot from executing market orders if the resulting margin level due to the opening of the said position results in a less than x % margin level, where x is a user-defined parameter?
Thanks for the assistance, if any.
You can easily check the margin levels before entering a position.
Code sample below:
if (Account.MarginLevel.HasValue && Account.MarginLevel >= minimumMarginLevelsToEnterPositions) { //place your orders here }
Otherwise, the only way I know of is immediately after executing your order successfully, check the margin levels and if it's below the threshold, close the position.
Example:
TradeResult r = ExecuteMarketOrder( .... ); if (r.IsSuccessful && Account.MarginLevel < minimumMarginLevelParameter) { //close the position and anything else you want to do }
@firemyst
firemyst
22 Sep 2019, 15:47
RE:
psz5mc@gmail.com said:
Hi
I need a method or something in API to be possible restarting a robot itself. Not when cTrader restart and only that robot can restart who initiated. When a robot decide to want a fresh start, call a RestartRobot() method that initiate the stop sequence and then cTrader start again the caller robot with the same parameters, etc.
Additionally for security reasons may need (or not) the FullAccess permission.
Thanks
SpotWare may be working on an API to allow one bot control another bot.
It's a wait and see game.
@Panagiotis may be able to elaborate further if they are.
@firemyst
firemyst
22 Sep 2019, 15:42
RE:
trader.calgo said:
Many entities, such as sockets, require execution closing methods, but indicators do not have OnStop(); It is very important to add this logic.
Have you tried surrounding your socket code with the C# using statement?
For example:
using (var socket = new Socket(/*...*/)) { // operations socket.Shutdown(SocketShutdown.Both); socket.Close(); }
The above code is expanded into the following by the compiler at compile time:
{ Socket socket = new Socket(/*...*/); try { // operations socket.Shutdown(SocketShutdown.Both); socket.Close(); } finally { if (socket != null) ((IDisposable)socket).Dispose(); } }
It will suck with each call to the calculate method as you'll have to open/close the socket each time, but at least it gives you a temporary work around if you need it.
Past values of the indicator won't be too bad; it's the latest calculate index that'll cause the problem. So other options are:
1) only open the socket if the parameter "index" for calculate has changed from the previous value
2) if you need the socket open more frequently for the current index, only open it every 5, 8, 13, or whatever calls to calculate on the current index. For example:
calculate (int index) { //_calculateCount is a global variable if ( _calculateCount % 5 == 0) { using (Socket s = new Socket....) {} } _calculateCount += 1; }
@firemyst
firemyst
22 Sep 2019, 15:27
( Updated at: 21 Dec 2023, 09:21 )
RE:
1goodtrade said:
Hi, can anyone help me to plot a Simple Moving Average on Volume in cTrader (Desktop 3.5) please?
Below is a screen shot from another charting service demonstrating what I am trying to achieve within cTrader preferably.
The volume histagram has a 20 period (variable) SMA plotted in orange - can this be done in cTrader and within the price panel (rather than a separate panel)?
Thanks to anyone that can offer some help :) Scotty.
It can be done quite easily in a display area below the main chart panel.
@firemyst
firemyst
18 Sep 2019, 17:09
RE:
tomopeov said:
2- Is it possible to close all open trades and orders once the price reaches a certain point?Thanks
This one is relatively simple to write pseudo-code (which may work) in a quick few minutes. In your OnTick method, do something similar to:
double closeThreshold = 1.02; //or whatever your price threshold is where you want to close everything if (Symbol.Ask <= closeThreshold) { CloseEverything(Symbol.Name); }
Here's the supporting function:
private void CloseEverything(string theSymbol) { foreach (Position p in Positions.FindAll(theSymbol)) //oryou could specify the "label" if you'll be labelling all your positions the same way { TradeResult r = p.Close(); if (r.IsSuccessful) { Print("Successfully closed position \"{0} {1}\" to true.", p.Id, p.Label); } else if (!r.IsSuccessful) { Print("WARNING! Could not close position \"{0} {1}\"!", p.Id, p.Label); Print("Error message: {0}", r.Error.Value); } } }
@firemyst
firemyst
10 Sep 2019, 03:38
RE:
Panagiotis Charalampous said:
Hi FireMyst,
The charts are displaying different values because you are using the wrong index. Replace line 41 to the below
Result[index] = _averageTrueRange.Result[_marketSeries.OpenTime.GetIndexByTime(MarketSeries.OpenTime[index])];Best Regards,
Panagiotis
That's awesome.
Thank you so much @Panagiotis! :-)
@firemyst
firemyst
06 Sep 2019, 16:13
RE:
alexsanramon said:
I see that you have discovered the flaw in ctrader resource management design. Thanks for the tip. Although it would only work if you know the source code of all the indicators you are going to use. The problem is most indicators by ctrader are closed.
They are closed yes. But as I said, you can easily look up their formulas.
For example, I gave you the Momentum one above.
The Keltner Channel can be calculated with the defaults as follows:
Middle Line: 20-day exponential moving average
Upper Channel Line: 20-day EMA + (2 x ATR(10))
Lower Channel Line: 20-day EMA - (2 x ATR(10))
Bollinger Bands are similar:
Middle Band = 20-day simple moving average (SMA)
Upper Band = 20-day SMA + (20-day standard deviation of price x 2)
Lower Band = 20-day SMA – (20-day standard deviation of price x 2)
Bollinger Bandwidth:
(Upper Bollinger Band - Lower Bollinger Band) / Middle Bollinger Band
Simple Moving Average:
(Price1 + Price 2 + ... + Price N) / N
etc etc.
@firemyst
firemyst
05 Sep 2019, 11:27
RE:
alexsanramon said:
If I understand you correctly, what you are saying is: instead of using GetIndicator<>, you place the calculation in the cbot code?
Exactly. Any you get from https://ctrader.com/algos/indicators
that includes the code you can put in your bot almost directly (depends on how you have your bot coded of course).
Even some that come with cTrader you can eliminate the GetIndicator<> call because the calculations are simple.
For example, the Momentum Indicator. It's calculation is just:
Momentum[index] = MarketSeries.Close[index] - MarketSeries.Close[index - Momentum_Period];
which you can easily insert into your bot code by creating your own array with however many bars back your bot will need to look. For instance, if all your bot does it look at the current value, and previous bar value, then you just need two values at any one time at most. So:
double[] Momentum = new double[] { 0, 0 }; //initialize
where Momentum[0] is the latest value (replicates "indicator.Result.Last(0)") and Momentum[1] is from 1 bar ago (replicates "indicator.Result.Last(1)").
Your single Momentum array will take up significantly less memory, never expand because it won't store more than 2 values, and will ultra fast for the CPU to deal with as opposed to the Momentum IndicatorDataSeries object which has a bigger memory footprint, is always growing with each OnBar, and takes more processing time for the CPU.
:-)
@firemyst
firemyst
03 Sep 2019, 08:37
RE:
Panagiotis Charalampous said:
Hi all,
We are aware of the issue and we will fix it the soonest.
Best Regards,
Panagiotis
Given that this has happened at least twice in the last few years according to dates on this thread alone:
1) does SpotWare have any automated testing systems in place? The "OnBar" method is a critical piece of event code unlike some obscure API call that's rarely used. And now, because of this bug which is at least 8 days old, renders a lot of bots that depend on it utterly useless.
2) does SpotWare plan to implement any sort of "critical bug contact list" that people can sign up to? 8+ days is a loooooooooong time to have such a critical issue unresolved, and developers/users of bots that depend on this piece of code should be notified instead of letting their now potentially hazardous code run without their knowing there's a critical bug. At the very least, that would be the socially responsible, "customer service", thing to do.
Thank you.
@firemyst
firemyst
02 Sep 2019, 08:44
Looks like this is an issue with cTrader.
Same issue was reported here which I didn't see earlier.
Sorry for the duplicate post:
https://ctrader.com/forum/calgo-support/3349
@firemyst
firemyst
02 Sep 2019, 08:43
Same issue happening to me.
Posted here:
https://ctrader.com/forum/calgo-support/21850
@firemyst
firemyst
27 Aug 2019, 14:27
@srubtsov, @Panagiotis:
Yes,after rereading everything, you both are right. My apologies.
Fair question though -- is it good behaviour for cTrader to ignore a SL when it falls within a spread and not even give a warning or something? Otherwise, unless there's specific checks for a stoploss after placing an order with a stoploss, the bots would never know.
Or is the behaviour srubtsov mentioned going to be released in a future version?
Thank you.
@firemyst
firemyst
27 Aug 2019, 08:59
RE: RE: RE:
srubtsov said:
FireMyst said:
I'll do you one better. Here's the source code needed to reproduce this issue. Details on what to do are in the comments.
Screen capture below too from Visual Studio showing the the breakpoints, and that it goes into the code block that the position's stoploss is zero immediately after fulfilling the order with a 1.2 pip SL.
What's happening to cause this?
Thank you.
In that case in backtesting problem is stop loss pips is less than spread. Spread is 1.6, StopLossPips is 1.2. Empty StopLoss for that is ok.
That is not so clear, currently in that case `TradeResult.IsSuccessful = true; TradeResult.ErrorCode = null`. In future versions it will be more clear, `ErrorCode` won't be null.
It doesn't matter what the spread is -- when a stop loss is set it should be set. Spread size has nothing to do with it. The spread is the difference between the bid/ask prices; a SL for a buy order is measured from below the BID; a SL for a sell order is measured from above the Ask.
Also, as with the original post, this same situation occurred when I had a stoploss of 10.4 pips.
There's a bug with cTrader and/or the server, and it needs to be fixed.
@firemyst
firemyst
20 Aug 2019, 17:59
RE:
khongkhongaaa said:
Hello cTrader team,
I programmed a robot in cTrader Automate.
But,
I don't want to sell the source code.
I only want to rent (no sell) and earn profits.
I mean:My customer can only use robot, but don't view source code. And when the expiry date, the robot will end.
Is there any idea to do that?
Is there an expiration time (end time) for the Robot?
Has anyone ever done this before?
Thank you & Happy Trading!
One of the most fool-proof ways is:
1) you have to create a robot that has full access
2) read the unique value of a windows registry key every time the bot runs. One that's installed by Windows so you know it won't be changing or get uninstalled.
3) open up a web service call to a webservice you have running somewhere
4) when your bot calls the webservice for the first time, save that unique guid and current date time
5) every day your robot is running, make another webservice call with the same unique guid and the current date time. Compare against the one saved on the server where your web service is hosted.
6) if the current date/time difference between the robot's latest time and the time saved on the webservice server is past the expirational period, have the bot stop.
This will make sure that if the user changes the local date time on the computer they're running the bot on, it won't matter. It also won't matter if they look on the computer for saved information because you're not saving it there either. You also know that the computer your bot is running on must have internet access to be able to trade.
@firemyst
firemyst
20 Aug 2019, 17:48
One option you have is to keep a running total of your robot using a C# Dictionary<string,double> object in your close event method:
//Keep the running total of losses and consecutive trade losses if (_runningTotalsGainLoss.ContainsKey(p1.Label)) _runningTotalsGainLoss[p1.Label] += p1.NetProfit; else _runningTotalsGainLoss.Add(p1.Label, p1.NetProfit);
And then do a simple check:
if (_runningTotalsGainLoss[p1.Label] < [your loss threshold parameter]) { Print("WARNING! Running total {0} has fallen below {1} threshold! Stopping bot for \"{2}\"!", String.Format("{0:$#,###.00}", _runningTotalsGainLoss[p1.Label]), String.Format("{0:$#,###.00}", [your loss threshold parameter]), p1.Label); Stop(); return; }
@firemyst
firemyst
20 Aug 2019, 17:38
I don't know if there's an API call for it, but you could always try writing the stop loss in an encoded string within the "comment" when the order is placed.
Then parse it from the historical trade info.
For instance, make your encoded string %SL:xx.x% where xx.x is the pips SL.
Then all you need do is parse the string to find it. :-)
@firemyst
firemyst
17 Aug 2019, 18:37
RE:
gutygs said:
Hi everyone!
I am new to this forum and cTrader for the matter! I come from using MQL4 but I-m now switching to cTrader for it's many features!
I'm sorry if this has been solved before. I've looked for it without any luck; I'm trying to build an array of close prices beginning from the last candle up until a term iCandle. When I call MarketSeries.Close[index] outside a for loop, the data is displayed nicely. Nonetheless, upon calling the method inside a for loop, I don't get any value back. I am also new to C# as I've been coding in Python for the last 2 years, so I'm guessing there must be something I'm doing wrong.
Any help will be much appreciated! Thank you!
Code:
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 Strategy5 : Robot { [Parameter("iCandle", DefaultValue = 7)] public int iCandle { get; set; } protected override void OnStart() { Print("initializing console"); } protected override void OnBar() { //lets print the last 7 candle closes Print("Printing the last 7 candles"); var lastIndex = MarketSeries.Close.Count - 1; string data = ""; for (int i = lastIndex; i <= lastIndex-iCandle; i--) { string strclose = MarketSeries.Close[i].ToString(); data += strclose + ", "; } Print("last prices are {0}", data); } protected override void OnStop() { // Put your deinitialization logic here } } }
Of course you won't get any values inside the for loop. Look at the conditions of your for loop.
for (int i = lastIndex; i <= lastIndex-iCandle; i--)
lastIndex is set to the last index.
i is set to this value.
So how is "i" going to be less than the "lastIndex - iCandle"?
Say lastIndex is 3000. So i starts off at 3000.
how is 3000 going to be <= (3000 - 5)?
It never will be.
So it never enters your for-loop.
And thus nothing is printed.
@firemyst
firemyst
17 Aug 2019, 18:26
You need to calculate the difference in pips between the two emas.
Here's a function that will help you:
private double DifferenceInPips(Symbol s, double firstPrice, double secondPrice, bool returnAbs) { if (returnAbs) return Math.Abs((firstPrice - secondPrice) / s.PipSize); else return (firstPrice - secondPrice) / s.PipSize; }
Then change your condition from:
if (_sma1.Result.LastValue > _sma2.Result.LastValue)
to:
if (_sma1.Result.LastValue > _sma2.Result.LastValue && DifferenceInPips(Symbol, _sma1.Result.LastValue, _sma2.Result.LastValue, false) > whatever_amount_you_want)
@firemyst
firemyst
22 Sep 2019, 15:55
RE:
eliezer_barros said:
@firemyst