Topics
Replies
firemyst
05 Mar 2024, 03:11
( Updated at: 05 Mar 2024, 06:44 )
It's not running on every tick; it's running every bar. The index you're printing confirms it.
When you first load a chart in cTrader, it loads previous bars, and runs through the calculations on those, and that's exactly what's happening here, unless it gets to the latest bar.
Sort the log by the date/time DESCENDING instead of ASCENDING and you'll see with the most recent data it only executes once per bar.
@firemyst
firemyst
05 Mar 2024, 03:06
( Updated at: 05 Mar 2024, 06:44 )
RE: RE: RE: Is it better to call the indicator or write the indicator yourself?
PanagiotisCharalampous said:
In principle no, as long as the implementations are identical. However, since there are always specifics in each case, this needs to be checked on a case by case basis.
Out of curiosity, are the native built in cTrader indicators written in .Net as well? Or another language like C++
@firemyst
firemyst
05 Mar 2024, 02:57
( Updated at: 05 Mar 2024, 06:44 )
Try reading Spotware's documentation and Google:
https://help.ctrader.com/ctrader-automate/compiling/#parameters
@firemyst
firemyst
03 Mar 2024, 03:30
RE: Is it better to call the indicator or write the indicator yourself?
PanagiotisCharalampous said:
Hi there,
Unfortunately I cannot understand the question and I guess many other readers. Could you please rephrase and provide some examples of what you are doing?
Best regards,
Panagiotis
I think what the OP is asking is if he's writing either a bot or a custom indicator that references a common indicator like the EMA, does the code execute faster if he references the native indicator in cTrader, or codes his own EMA within the custom indicator/bot he's writing.
Since nano-seconds can make a difference, he's essentially wonder if anyone's done any bench marks to see which way is faster.
That's how I read it.
@firemyst
firemyst
25 Feb 2024, 12:39
RE: RE: Historical Data for Range charts
roan.is said:
firemyst said:
This is probably dependent on your broker.
Why not open your cTrader, put on a big range like 100 pips per bar, and see how far back it goes?
Thanks for your reply. Unfortunately, I don't have access to cTrader at the moment (no computer), hence my question. But I'll certainly do a check as soon as I can.
When you change bar sizes, just keep scrolling left to bring in more historical data. See how far the rabbit hole goes.
@firemyst
firemyst
22 Feb 2024, 02:24
( Updated at: 22 Feb 2024, 07:46 )
Duplicate. Original one is here:
https://ctrader.com/forum/cbot-support/42928
@firemyst
firemyst
21 Feb 2024, 11:45
RE: Protect orders/positions against manual modifications
ncel01 said:
Unintentional manual modifications.
Semantics. Unintentional by you or someone else. Either way, with how the charts are structured and the location of controls, it takes a lot to do something ‘unintentional’ while looking at the charts with a position you're in – someone has to physically move, point, and click a mouse button, especially if you've removed all the hot key shortcuts. That's a lot for being unintentional while trading on a live account.
And besides moving the SL/TP, I don't know what else you could easily reverse/reset if something ‘unintentional’ is done.
@firemyst
firemyst
21 Feb 2024, 08:30
RE: RE: Protect orders/positions against manual modifications
ncel01 said:
firemyst said:
Yes it can. You'll have to implement checks. There's no way currently to prevent a user from manually modify an order (SL/TP), but you can always keep track of the last value your bot moved it too and then revert back to those values if they were updated.
Other modifications like increasing/decreasing the position size and such will be a bit more tricky because you'll first have to start by asking yourself… if someone manually decreased your position size, would you really want to increase it back to where it was?
That's exactly about check and revert as I mentioned above.
I think the most effective way was to have an option on cTrader settings for the active account.
Allow manual trading for the account? Y/N
In addition, this would also save all the effort to code an (not so effective) alternative.
The first question to possibly ask is if you're trading via automation, who would be adjusting the trades manually? If it's not you, and you're running the bots, then maybe the easiest approach would just be to ask whoever else has access to actually not trade anything.
@firemyst
firemyst
21 Feb 2024, 01:38
RE: RE: Amount to trade depending on stop loss
oliver.r.m.92 said:
I have rewritten the code and used your part of code but now I have a new problem, in the log it shows this message: Crashed in OnBar with ArgumentOutOfRangeException: Specified argument was out of the range of valid values. Parameter name: volume. Actual value was: NaN.
The new code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
public class MACDcBot : Robot
{
private bool isPositionOpen;
private MacdCrossOver _MACD;
private MovingAverage EMA;
private const string label = "Trade ON";
private double stopLossPrice;
//MA
[Parameter("Source", Group = "Moving Average")]
public DataSeries SourceSeries { get; set; }
[Parameter("MA Type", Group = "Moving Average")]
public MovingAverageType MAType { get; set; }
[Parameter("MA Periods", Group = "Moving Average", DefaultValue = 200)]
public int MAPeriods { get; set; }
//MACD
[Parameter("Period", DefaultValue = 9)]
public int Period { get; set; }
[Parameter("Long Cycle", DefaultValue = 26)]
public int LongCycle { get; set; }
[Parameter("Short Cycle", DefaultValue = 12)]
public int ShortCycle { get; set; }
[Parameter("Signal-line crossover true:if Signal-line crossover false: Zero crossover", DefaultValue = true)]
public bool IsSignalLineCrossover { get; set; }
protected override void OnStart()
{
_MACD = Indicators.MacdCrossOver(LongCycle, ShortCycle, Period);
EMA = Indicators.MovingAverage(SourceSeries, MAPeriods, MAType);
isPositionOpen = false;
Positions.Closed += OnPositionsClosed;
}
protected override void OnBar()
{
if (Positions.Count > 0)
{
var position = Positions.LastOrDefault();
if (position != null)
{
if (position.TradeType == TradeType.Buy)
stopLossPrice = EMA.Result.LastValue - Symbol.PipSize * 2; // 2 pips por debajo de la SMA de 200
else if (position.TradeType == TradeType.Sell)
stopLossPrice = EMA.Result.LastValue + Symbol.PipSize * 2; // 2 pips por encima de la SMA de 200
double takeProfitPrice = position.EntryPrice + (position.EntryPrice - stopLossPrice) * 1.5;
ModifyPosition(position, stopLossPrice, takeProfitPrice);
}
}
// Calcula el tamaño de posición basado en el riesgo
var maxAmountRisked = Account.Equity * (1 / 100);
var positionSize = Symbol.NormalizeVolumeInUnits(maxAmountRisked / (stopLossPrice * Symbol.PipValue), RoundingMode.Down);
if (IsSignalLineCrossover)
{
if (!isPositionOpen && _MACD.Histogram.LastValue > 0 && _MACD.Signal.LastValue < 0 && _MACD.MACD.Last(3) < _MACD.Signal.Last(3) && _MACD.MACD.Last(2) > _MACD.Signal.Last(2) && Bars.HighPrices.Last(1) > EMA.Result.Last(3))
{
ExecuteMarketOrder(TradeType.Buy, SymbolName, positionSize, label);
isPositionOpen = true;
}
if (!isPositionOpen && _MACD.Histogram.LastValue < 0 && _MACD.Signal.LastValue > 0 && _MACD.MACD.Last(3) > _MACD.Signal.Last(3) && _MACD.MACD.Last(2) < _MACD.Signal.Last(2) && Bars.LowPrices.Last(1) < EMA.Result.Last(3))
{
ExecuteMarketOrder(TradeType.Sell, SymbolName, positionSize, label);
isPositionOpen = true;
}
}
}
private void OnPositionsClosed(PositionClosedEventArgs args)
{
isPositionOpen = false;
}
}
}
Of course it throws an error. Look at your code in OnBar.
Look at the code you ALWAYS execute regardless if you're in a position or not.
Where do you set stopLossPrice (I bolded it in the code above) if you don't have any positions? You're trying to do a calculation using it when you're not setting it.
I also suggest you starting learning how to use Print statements in your code to print values to the log. THen if you put print statements everywhere, you also know where your code is crashing.
@firemyst
firemyst
21 Feb 2024, 01:25
I don't understand what you're saying. Read that sentence outloud to yourself, especially the italics part:
“You can see here although in the code the close of bar 2 should be greater than or equal to the open of bar 3 but in this pic its tell yet the Bot still took the trade .”
In the screen capture you provided, the close of 2 bars back is greater than the close of the 3rd bar back from the current bar.
@firemyst
firemyst
21 Feb 2024, 01:16
Yes it can. You'll have to implement checks. There's no way currently to prevent a user from manually modify an order (SL/TP), but you can always keep track of the last value your bot moved it too and then revert back to those values if they were updated.
Other modifications like increasing/decreasing the position size and such will be a bit more tricky because you'll first have to start by asking yourself… if someone manually decreased your position size, would you really want to increase it back to where it was?
@firemyst
firemyst
15 Feb 2024, 03:53
I'm not sure how you could account for that? Would be interesting to know if it can be done.
For instance, do you know what the lag time will be between the time your bot places an order, when the server receives your order, and when it's actually executed?
You could be doing a replay at a time when the market is closed, or very slow, and thus little lag; whereas when you run your bot it may be during peak trading hours and could be lots of internet congestion.
@firemyst
firemyst
13 Feb 2024, 00:39
( Updated at: 13 Feb 2024, 00:44 )
Are you able to provide screen captures of your back-test parameters?
Also, I don't believe async trade operations are fully supported in backtest or work as expected in backtest by their very nature… eg, in backtest mode, everything is “instantaneous” as opposed to live markets where one async call may execute right away, others will have a delay, etc etc.
@firemyst
firemyst
13 Feb 2024, 00:36
What time frame are you using?
You don't say, and that's what's causing your issue.
Obviously that will make a difference. Your default lookback period is 1000. So if you're on a weekly, daily, 4-hourly, 200 Renko, 100-range, 2/3/4 hour HA, etc etc, you won't have more bars than your lookback period, so your “else” logic never gets executed.
if (index < LookbackPeriod)
{
RenkoTop[index] = double.NaN;
RenkoBottom[index] = double.NaN;
CurrentBrick[index] = double.NaN;
return;
}
// HOW DO YOU EXPECT THIS LOGIC TO EVER BE EXECUTED
// with a 1000 lookback period when you
//have less than 1000 (default lookback period) bars on the chart?
//Unless you get more than 1000 bars/candles on a chart, index
//will always be less than the lookback period except in 1 case.
double atrValue = _atr.Result[index];
_brickSize = atrValue;
if (index == LookbackPeriod)
{
RenkoTop[index] = Bars.ClosePrices[index];
RenkoBottom[index] = Bars.ClosePrices[index] - _brickSize;
_isAscending = Bars.ClosePrices[index] > Bars.ClosePrices[index - 1];
}
else
{
}
You should debug your code by putting in lots of print statements to see where it's getting to, and what parts of your logic are or are not being executed.
@firemyst
firemyst
05 Mar 2024, 07:54
RE: RE: Run code Once Per new bar
mihlali700 said:
No, it's not going through all the indexes once per bar. As I said, when you first start cTrader, it loads up all the previous bars because it has to. Otherwise,e there's no way to display previous chart data is there?
If you only want data from the latest index going forward, then in your Initialize method, get the latest index:
int latestIndex = Bars.OpenTimes.Count - 1
Then in your calculate method check if index ≥ latestIndex before doing anything.
@firemyst