Topics
Forum Topics not found
Replies
amusleh
14 Mar 2022, 08:50
RE: RE: RE: can this be used for indicators as well as cbots?
bonedrak said:
amusleh said:
bonedrak said:
is this possible using "private void RenkoSeries_OnBar(object sender, OhlcBar newBar, OhlcBar oldBar)" instead of "calculate(int index)"
Hi,
You should use RenkoSeries OnBar only in backtesting environment and the Calculate method on live mode.
I want to use a custom indicator in backtesting a cbot, but it wont allow me because it says the time frames are different, for the cbot (which uses your renko bars) and the indicator (which uses "calculate(int index)"). So my question is, can an indicator be built that uses your library and renko bars? or will it only work on cbots?
Hi,
You can't feed a custom indicator the Renko generated bars, it's not possible.
The solution is to create a class for your indicator inside cBot project, pass it the Renko generated bars data and then call it's OnBar method whenever you receive a bar from Renko library.
It's little complicated but it's possible.
@amusleh
amusleh
14 Mar 2022, 08:43
Hi,
What do you mean by executing market order and buy £10 per point?
For profit/loss calculation you can use symbol Pip/Tick value.
A symbol tick/Pip value gives you one tick/Pip of symbol monetary value in account currency.
If you want to set a £50 stop loss and your account currency is GBP then you can divide 50 to symbol pip value and use the result as stop loss in Pips.
@amusleh
amusleh
14 Mar 2022, 08:34
( Updated at: 14 Mar 2022, 08:35 )
Hi,
It's possible, you can load multiple symbols Bars inside your cBot on backtest and use them.
You can use a symbol Tick event or it's Bars BarOpened event.
cAlgo API Reference - Symbol Interface (ctrader.com)
cAlgo API Reference - Bars Interface (ctrader.com)
@amusleh
amusleh
14 Mar 2022, 08:32
RE: how to send messages to telegram channel?
meeting.chegini said:
I want to send messages to a telegram channel
How can I do this?
Thanks
Hi,
You have to add the Telegram bot as an admin on your channel and then you will be able to get a chat ID with it that you can use it to send messages.
Here is a tutorial: Telegram · afhacker/ctrader-alert_popup Wiki (github.com)
@amusleh
amusleh
14 Mar 2022, 08:29
RE: can this be used for indicators as well as cbots?
bonedrak said:
is this possible using "private void RenkoSeries_OnBar(object sender, OhlcBar newBar, OhlcBar oldBar)" instead of "calculate(int index)"
Hi,
You should use RenkoSeries OnBar only in backtesting environment and the Calculate method on live mode.
@amusleh
amusleh
11 Mar 2022, 08:07
RE: RE: RE:
ys2310 said:
Hi amusleh,
I'm trying the following code and the index is -1
DateTime dt = Server.Time.AddMinutes(-128160);
int index = MarketData.GetBars(TimeFrame.Minute).OpenTimes.GetIndexByTime(dt);
Print("{0} {1}", index, MarketData.GetBars(TimeFrame.Minute).ClosePrices[index]);if I instead use the code below the index has a value.
DateTime dt = Server.Time.AddMinutes(-1);
int index = MarketData.GetBars(TimeFrame.Minute).OpenTimes.GetIndexByTime(dt);
Print("{0} {1}", index, MarketData.GetBars(TimeFrame.Minute).ClosePrices[index]);Is this because I'm referring way back in the past and there is no data with it?
How can I work around this problem? I want to get a correct value with the specified date and time.
Best regards,
It returns -1 if there is no matching bar, to solve this issue you can load more bars by calling Bars LoadMoreHistory method.
@amusleh
amusleh
11 Mar 2022, 08:06
RE: RE:
66281850 said:
PanagiotisCharalampous said:
Dear 66281850,
Unfortunately there is no such option at the moment
FishProvider,
We offer higher limits to our clients.
Best Regards,
Panagiotis
Are there plans to provide such an API in the future?
I think it is technically possible to combine multiple closing orders into one request。
Hi,
No, we don't have any plan to increase the current limits for now.
If your application trading volume is high enough we can increase the limit.
But for most apps the current limit is enough.
@amusleh
amusleh
10 Mar 2022, 14:49
Hi,
Our FIX server never sends back something like:
FIX.4.4:demo.ctrader.3449248->CSERVER:SessionTrade
If server is not responding to your message then most probably your message checksum is invalid.
Please try our Python FIX package: spotware/cTraderFixPy: A Python package for interacting with cTrader FIX API. (github.com)
It's not released yet, but you can install it from TestPyPi:
Once you installed it try to use the Console sample which is inside it's repository.
@amusleh
amusleh
10 Mar 2022, 10:26
Hi,
If you want to get the lowest/minimum value x bars back you can use this method:
using System;
using cAlgo.API;
namespace cAlgo
{
[Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class NewIndicator : Indicator
{
protected override void Initialize()
{
// Initialize and create nested indicators
}
public override void Calculate(int index)
{
// To get index on a cBot use
// var index = Bars.Count - 1;
// low of 20 previous bars
var low = Minimum(Bars.LowPrices, index - 20, index);
Print(low);
}
/// <summary>
/// Returns the minimum value between start and end (inclusive) index in a dataseries
/// </summary>
/// <param name="dataSeries"></param>
/// <param name="startIndex">Start index (Ex: 1)</param>
/// <param name="endIndex">End index (Ex: 10)</param>
/// <returns>double</returns>
private double Minimum(DataSeries dataSeries, int startIndex, int endIndex)
{
var min = double.PositiveInfinity;
for (var i = startIndex; i <= endIndex; i++)
{
min = Math.Min(dataSeries[i], min);
}
return min;
}
}
}
@amusleh
amusleh
10 Mar 2022, 10:21
Hi,
Try 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 NYOpen : Robot
{
[Parameter("Entry Time (Hours)", DefaultValue = 14)]
public double EntryTime { get; set; }
[Parameter("Entry", DefaultValue = 5)]
public int Entry { get; set; }
[Parameter("Quantity (Lots)", Group = "Volume", DefaultValue = 1, MinValue = 0.01, Step = 0.01)]
public double Quantity { get; set; }
[Parameter("Stop Loss (Pips)", DefaultValue = 20)]
public int SL { get; set; }
[Parameter("Take Profit (Pips)", DefaultValue = 10)]
public int TP { get; set; }
protected override void OnStart()
{
Timer.Start(TimeSpan.FromHours(1));
}
protected override void OnTimer()
{
if (Server.Time.TimeOfDay.Hours != EntryTime) return;
PlaceStopLimitOrder(TradeType.Buy, SymbolName, VolumeInUnits, Symbol.Ask + (Entry * Symbol.PipSize), 0.0, "NY Open", SL, TP, Server.Time.AddHours(12));
PlaceStopLimitOrder(TradeType.Sell, SymbolName, VolumeInUnits, Symbol.Bid - (Entry * Symbol.PipSize), 0.0, "NY Open", SL, TP, Server.Time.AddHours(12));
}
protected override void OnTick()
{
//Close Trades
}
private double VolumeInUnits
{
get { return Symbol.QuantityToVolumeInUnits(Quantity); }
}
protected override void OnStop()
{
// Put your deinitialization logic here
}
}
}
@amusleh
amusleh
10 Mar 2022, 10:16
Hi,
Try 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.FullAccess)]
public class AFFS : Robot
{
[Parameter("Name", DefaultValue = "AFFS")]
public string _name { get; set; }
[Parameter("Start Hour", DefaultValue = 6.0)]
public double _starttime { get; set; }
[Parameter("Stop Hour", DefaultValue = 18.0)]
public double _stoptime { get; set; }
[Parameter("Max Lots", DefaultValue = 100.0, MinValue = 0.01, MaxValue = 1000.0)]
public double _maxlots { get; set; }
[Parameter("Starting Risk (%)", DefaultValue = 1.0, MinValue = 0.01, MaxValue = 100.0)]
public double _startingrisk { get; set; }
[Parameter("Risk Step (%)", DefaultValue = 1.0, MinValue = 0.01, MaxValue = 100.0)]
public double _riskstep { get; set; }
[Parameter("Take Profit", DefaultValue = 5.0, MinValue = 0.1, MaxValue = 100.0)]
public double _takeprofit { get; set; }
[Parameter("Stop Loss", DefaultValue = 10.0, MinValue = 0.1, MaxValue = 100.0)]
public double _stoploss { get; set; }
[Parameter("Safety (Pips)", DefaultValue = 3.0, MinValue = 0.1, MaxValue = 100.0)]
public double _safety { get; set; }
[Parameter("High/Low Timeframe", DefaultValue = "Daily")]
public TimeFrame _hltf { get; set; }
private Bars _hlbars;
private double _bullprice, _bearprice, _previoushigh, _previouslow, _maxunits, _activerisk;
private bool _todaybuy, _todaysell;
protected override void OnStart()
{
_hlbars = MarketData.GetBars(_hltf);
_safety *= Symbol.PipSize;
}
protected override void OnBar()
{
var _currenthours = Server.Time.TimeOfDay.TotalHours;
bool _tradetime = _starttime < _stoptime ? _currenthours > _starttime && _currenthours < _stoptime : _currenthours < _stoptime || _currenthours > _starttime;
_activerisk = GetRisk();
var _volume = GetVolume();
_maxunits = Symbol.QuantityToVolumeInUnits(_maxlots);
if (_volume > _maxunits)
{
_volume = _maxunits;
}
_previoushigh = _hlbars.HighPrices.Last(1);
_previouslow = _hlbars.LowPrices.Last(1);
_bullprice = Symbol.Ask + _safety;
_bearprice = Symbol.Bid - _safety;
if (_tradetime && !_todaybuy)
{
if (_bullprice > _previoushigh)
{
ExecuteMarketOrder(TradeType.Buy, Symbol.Name, _volume, _name, _stoploss, _takeprofit);
_todaybuy = true;
}
}
if (!_tradetime && _todaybuy)
{
_todaybuy = false;
}
if (_tradetime && !_todaysell)
{
if (_bearprice < _previouslow)
{
ExecuteMarketOrder(TradeType.Sell, Symbol.Name, _volume, _name, _stoploss, _takeprofit);
_todaysell = true;
}
}
if (!_tradetime && _todaysell)
{
_todaysell = false;
}
}
private double GetRisk()
{
double _result = 0.0;
double _maxrisk = 10.0;
var _lastposition = History.FindLast(_name);
bool _win = _lastposition != null && _lastposition.NetProfit > 0.0 ? true : false;
if (_win && _activerisk < _maxrisk)
{
_result = _activerisk + _riskstep;
}
else if (!_win)
{
_result = _startingrisk;
}
return _result;
}
private double GetVolume()
{
double costPerPip = (double)((int)(Symbol.PipValue * 10000000)) / 100;
double baseNumber = Account.Balance;
double sizeInLots = Math.Round((baseNumber * _activerisk / 100) / (_stoploss * costPerPip), 2);
var result = Symbol.QuantityToVolumeInUnits(sizeInLots);
if (result > Symbol.VolumeInUnitsMax)
{
result = Symbol.VolumeInUnitsMax;
}
else if (result < Symbol.VolumeInUnitsMin)
{
result = Symbol.VolumeInUnitsMin;
}
else if (result % Symbol.VolumeInUnitsStep != 0)
{
result = result - (result % Symbol.VolumeInUnitsStep);
}
return result;
}
}
}
@amusleh
amusleh
10 Mar 2022, 10:11
Hi,
cTrader has three different APIs:
- cTrader Automate API: It's part of cTrader desktop app, you can use it to create indicators and cBots for cTrader desktop app.
- FIX API: It's the standard FIX API implementation that is available for cTrader trading accounts, you can use it to trade and get price data of your cTrader trading account, but the FIX standard is very limited and old, you can get your trading account FIX API credentials from cTrader app settings section, we have some samples on our Github that you can use.
- Open API: This is another API cTrader provides, it's not dependent on cTrader desktop/web/mobile apps and it's fully separate from the two abovementioned APIs, this is the API that you can use to create fully featured trading platforms or trading algorithms that will operate on your or any other cTrader users trading accounts. if you want to create an app or a trading algorithm outside cTrader official provided apps that will be your go to option. we have plenty of rich samples for this API on our Github for different programming languages, we have developed SDKs for this and also some third party developers made lots of contribution to develop different packages/wrappers for this cTrader API, you can check our OpenAPI.NET or OpenApiPy Github repositories.
Now regarding your question, you can use Open API for personal use, there is nothing that limits you.
You can provide some arbitrary Company name and site and we will approve your application.
But if you want to operate only on your own trading accounts then the best option for you is to use Automate API or FIX.
@amusleh
amusleh
10 Mar 2022, 10:00
( Updated at: 10 Mar 2022, 10:05 )
Hi,
First of all this is great idea! we might develop an indicator for this.
The issue with your code is you take the mouse up event time value and you use it as target for another chart.
The time value of mouse up event is not related to scrolling at all, it's the time point where the mouse cursor was.
To solve the issue you can use the chart scroll changed event instead, ex:
using System;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
using cAlgo.Indicators;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Threading;
namespace cAlgo
{
[Indicator(IsOverlay = true, TimeZone = TimeZones.IsraelStandardTime, AccessRights = AccessRights.FileSystem)]
public class SyncObjectsInstance : Indicator
{
protected override void Initialize()
{
Synchronizer.Instance.Register(this);
Timer.Start(Synchronizer.HeartbeatRate);
}
protected override void OnTimer()
{
Synchronizer.Instance.Heartbeat(this);
}
public override void Calculate(int index)
{
// do nothing
}
}
public class Synchronizer
{
public static readonly TimeSpan HeartbeatTimeout = TimeSpan.FromSeconds(5);
public static readonly TimeSpan HeartbeatRate = TimeSpan.FromSeconds(4);
private static readonly object _sync = new object();
private static Synchronizer _instance = null;
public static Synchronizer Instance
{
get
{
if (_instance != null)
return _instance;
lock (_sync)
{
if (_instance != null)
return _instance;
_instance = new Synchronizer();
}
return _instance;
}
}
private readonly Dictionary<string, HashSet<SyncObjectsInstance>> _instances;
private readonly Dictionary<SyncObjectsInstance, DateTime> _instanceHeartbeats;
public Synchronizer()
{
_instances = new Dictionary<string, HashSet<SyncObjectsInstance>>(StringComparer.OrdinalIgnoreCase);
_instanceHeartbeats = new Dictionary<SyncObjectsInstance, DateTime>();
}
public void Register(SyncObjectsInstance instance)
{
// instance.Print("Register");
lock (_sync)
{
Restore(instance);
}
}
public void Heartbeat(SyncObjectsInstance instance)
{
// instance.Print("Heartbeat");
lock (_sync)
{
var now = DateTime.Now;
_instanceHeartbeats[instance] = now;
var expiredInstances = _instanceHeartbeats.Where(hb => now - hb.Value > HeartbeatTimeout).Select(hb => hb.Key).ToArray();
foreach (var expiredInstance in expiredInstances)
{
expiredInstance.Chart.ScrollChanged -= Chart_ScrollChanged;
_instanceHeartbeats.Remove(expiredInstance);
_instances[expiredInstance.SymbolName].Remove(expiredInstance);
}
}
}
private void Chart_ScrollChanged(ChartScrollEventArgs obj)
{
lock (_sync)
{
HashSet<SyncObjectsInstance> symbolInstances;
if (!_instances.TryGetValue(obj.Chart.SymbolName, out symbolInstances))
return;
foreach (var instance in symbolInstances)
{
if (instance.Chart == obj.Chart)
continue;
instance.BeginInvokeOnMainThread(() => ScrollChart(instance, obj.Chart.Bars.OpenTimes[obj.Chart.FirstVisibleBarIndex]));
}
}
}
private void ScrollChart(SyncObjectsInstance targetInstance, DateTime targetTime)
{
//p("ScrollChart " + targetTime);
targetInstance.Print("ScrollChart | ", targetInstance.TimeFrame);
targetInstance.Chart.ScrollXTo(targetTime);
//int middleBar = targetInstance.Chart.FirstVisibleBarIndex + ((targetInstance.Chart.LastVisibleBarIndex - targetInstance.Chart.FirstVisibleBarIndex) / 2);
//DateTime midDate = targetInstance.Bars.OpenTimes[middleBar];
//bool crossDate = false;
//int crossDir = midDate < targetTime ? 1 : -1;
//while (midDate != targetTime && !crossDate)
//{
// p("midDate= " + midDate + " targetTime= " + targetTime + " middleBar= " + middleBar + " midDate= " + midDate);
// p("FirstVisibleBarIndex= " + targetInstance.Chart.FirstVisibleBarIndex + " LastVisibleBarIndex= " + targetInstance.Chart.LastVisibleBarIndex);
// targetInstance.Chart.ScrollXBy(crossDir);
// middleBar = targetInstance.Chart.FirstVisibleBarIndex + ((targetInstance.Chart.LastVisibleBarIndex - targetInstance.Chart.FirstVisibleBarIndex) / 2);
// midDate = targetInstance.Bars.OpenTimes[middleBar];
// crossDate = crossDir == 1 ? midDate > targetTime : midDate < targetTime;
//}
}
private void p(string text)
{
File.AppendAllText("d:\\temp\\a.log", text + Environment.NewLine);
}
//p("a targetTime= " + targetTime +
// " targetInstance.Chart.TimeFrame.ToString()= " + targetInstance.Chart.TimeFrame.ToString() +
// " FirstVisibleBarIndex= " + targetInstance.Chart.FirstVisibleBarIndex +
// );
//targetInstance.Chart.ScrollXBy(100);
//targetInstance.Chart.ScrollXTo(targetTime);
//Thread.Sleep(300);
//targetInstance.Chart.ScrollXBy((targetInstance.Chart.FirstVisibleBarIndex - targetInstance.Chart.LastVisibleBarIndex) / 2);
//p("diff= " + ((targetInstance.Chart.FirstVisibleBarIndex - targetInstance.Chart.LastVisibleBarIndex) / 2));
//p("f" + " TimeFrame= " + targetInstance.Chart.TimeFrame + " args.targetTime= " + targetTime + " LastVisibleBarIndex= " +
// targetInstance.Chart.LastVisibleBarIndex + " lastTime= " + targetInstance.Bars.OpenTimes[targetInstance.Chart.LastVisibleBarIndex] +
// " FirstVisibleBarIndex= " + targetInstance.Chart.FirstVisibleBarIndex + " firstTime= " +
// targetInstance.Bars.OpenTimes[targetInstance.Chart.FirstVisibleBarIndex] +
// " middleIdx= " + middleBar +
// " middleDate= " + targetInstance.Bars.OpenTimes[middleBar] +
// "-2Bars= " + ((targetInstance.Chart.LastVisibleBarIndex - targetInstance.Chart.FirstVisibleBarIndex) / -2).ToString()
// );
//p("crossDir= " + crossDir);
//p("a FirstVisibleBarIndex= " + targetInstance.Chart.FirstVisibleBarIndex + " LastVisibleBarIndex= " + targetInstance.Chart.LastVisibleBarIndex);
//for (int i = 0; i < 100; i++)
//{
// //p("FirstVisibleBarIndex= " + targetInstance.Chart.FirstVisibleBarIndex + " LastVisibleBarIndex= " + targetInstance.Chart.LastVisibleBarIndex);
// targetInstance.Chart.ScrollXBy(-1);
// targetInstance.Chart.
// //Thread.Sleep(300);
//}
//p("b FirstVisibleBarIndex= " + targetInstance.Chart.FirstVisibleBarIndex + " LastVisibleBarIndex= " + targetInstance.Chart.LastVisibleBarIndex);
private void Restore(SyncObjectsInstance sender)
{
HashSet<SyncObjectsInstance> symbolInstances;
if (!_instances.TryGetValue(sender.SymbolName, out symbolInstances))
{
symbolInstances = new HashSet<SyncObjectsInstance>();
_instances.Add(sender.SymbolName, symbolInstances);
}
sender.Chart.ScrollChanged += Chart_ScrollChanged; ;
symbolInstances.Add(sender);
_instanceHeartbeats[sender] = DateTime.Now;
}
}
}
You can improve it by using Bars delta of scroll changed event args instead of first visible bar on the chart.
Also there is the issue of simultaneous scrolling which can be solved if you work little bit on it.
@amusleh
amusleh
09 Mar 2022, 10:16
( Updated at: 09 Mar 2022, 10:25 )
Hi,
I just tested on a Spotware beta demo account for EURUSD, and the results were matching.
M1 Bar data on cTrader:
Open: 1.09257
Low: 1.09244
High: 1.09263
Close: 1.09261
API Bar Data:
{ "ctidTraderAccountId": "19188459", "symbolId": "1", "bid": "109261", "ask": "109262", "trendbar": [ { "volume": "207", "period": "M1", "low": "109244", "deltaOpen": "13", "deltaHigh": "19", "utcTimestampInMinutes": 27446889 } ] }
And ETH/USD test:
M1 Bar data on cTrader:
Open: 2,729.796
Low: 2,729.675
High: 2,732.071
Close: 2,731.171
API Bar Data:
{ "ctidTraderAccountId": "19188459", "symbolId": "22397", "bid": "273117100", "ask": "273144500", "trendbar": [ { "volume": "172", "period": "M1", "low": "272967500", "deltaOpen": "12100", "deltaHigh": "239600", "utcTimestampInMinutes": 27446900 } ] }
The spot event message is the latest received event for that bar.
@amusleh
amusleh
09 Mar 2022, 08:42
Hi,
The indicator code is not posted by him, so it's not clear how it works or which output properties it has.
If the DSS indicator output property name is Result then try this:
using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
namespace cAlgo
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class ClickAlgoSchoolSMA : Robot
{
#region User defined parameters
[Parameter("Instance Name", DefaultValue = "001")]
public string InstanceName { get; set; }
[Parameter("Lot Size", DefaultValue = 0.1)]
public double LotSize { get; set; }
[Parameter("Stochastic period", DefaultValue = 13)]
public int Stochastic_Period { get; set; }
[Parameter("EMA period", DefaultValue = 8)]
public int EMA_Period { get; set; }
[Parameter("WMA period", DefaultValue = 8)]
public int WMA_Period { get; set; }
[Parameter("Calculate OnBar", DefaultValue = false)]
public bool CalculateOnBar { get; set; }
[Parameter()]
public DataSeries SourceSeries { get; set; }
#endregion
#region Indicator declarations
private DSSBressert _DSSBressert { get; set; }
private WeightedMovingAverage WMA { get; set; }
#endregion
#region cTrader events
/// <summary>
/// This is called when the robot first starts, it is only called once.
/// </summary>
protected override void OnStart()
{
// construct the indicators
_DSSBressert = Indicators.GetIndicator<DSSBressert>(Stochastic_Period, EMA_Period);
WMA = Indicators.WeightedMovingAverage(SourceSeries, WMA_Period);
}
/// <summary>
/// This method is called every time the price changes for the symbol
/// </summary>
protected override void OnTick()
{
if (CalculateOnBar)
{
return;
}
ManagePositions();
}
/// <summary>
/// This method is called at every candle (bar) close, when it has formed
/// </summary>
protected override void OnBar()
{
if (!CalculateOnBar)
{
return;
}
ManagePositions();
}
/// <summary>
/// This method is called when your robot stops, can be used to clean-up memory resources.
/// </summary>
protected override void OnStop()
{
// unused
}
#endregion
#region Position management
private void ManagePositions()
{
if (_DSSBressert.Result.HasCrossedAbove(WMA.Result, 1))
{
// if there is no buy position open, open one and close any sell position that is open
if (!IsPositionOpenByType(TradeType.Buy))
{
OpenPosition(TradeType.Buy);
}
ClosePosition(TradeType.Sell);
}
// if a sell position is already open and signal is buy do nothing
if (_DSSBressert.Result.HasCrossedAbove(WMA.Result, 1))
{
// if there is no sell position open, open one and close any buy position that is open
if (!IsPositionOpenByType(TradeType.Sell))
{
OpenPosition(TradeType.Sell);
}
ClosePosition(TradeType.Buy);
}
}
/// <summary>
/// Opens a new long position
/// </summary>
/// <param name="type"></param>
private void OpenPosition(TradeType type)
{
// calculate volume from lot size.
long volume = Symbol.QuantityToVolume(LotSize);
// open a new position
ExecuteMarketOrder(type, this.Symbol, volume, InstanceName, null, null);
}
/// <summary>
///
/// </summary>
/// <param name="type"></param>
private void ClosePosition(TradeType type)
{
var p = Positions.Find(InstanceName, this.Symbol, type);
if (p != null)
{
ClosePosition(p);
}
}
#endregion
#region Position Information
/// <summary>
///
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
private bool IsPositionOpenByType(TradeType type)
{
var p = Positions.FindAll(InstanceName, Symbol, type);
if (p.Count() >= 1)
{
return true;
}
return false;
}
#endregion
}
}
@amusleh
amusleh
08 Mar 2022, 09:27
RE: RE:
florent.herb said:
Hi,
Thank you for your reply!
One more question that has nothing to do with the topic of the post. Does the exit in the cbot of the stop loss and take profits "on bar closed" instead of "on tick" is the difference between the results with ctrader optimization between data set on "tick" and on "m1 bar open prices"? I hope my question make sense. Thank you.
Hi,
Not sure what do you mean, if you want to backtest in most accurate possible way then use tick data, as it calls the OnTick method per each actual tick and it takes into account the real spread.
The m1 bar open prices option only use the one minute bars open prices to generate other time frames bars and it calls the OnTick per each M1 bar open price, the OnBar method will be called by combining multiple M1 bar open prices to generate one bar.
@amusleh
amusleh
14 Mar 2022, 08:58
Hi,
You can use the loaded Bars BarOpened event instead of Bot OnBar method, ex:
This way the execution logic will be executed only once per bar based on your selected time frame.
@amusleh