Topics
Forum Topics not found
Replies
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
08 Mar 2022, 09:01
Hi,
If optimization crashes cTrader there could several causes for it, there might be something wrong with your cBot code which is the most probable cause.
And yes, a faster CPU with more cores can increase optimization speed.
Please submit a troubleshoot report and use this thread link on the report text box.
Also if you post the cBot code that is causing the crash that will be very helpful.
@amusleh
amusleh
08 Mar 2022, 08:57
Hi,
The position has net profit and gross profit properties, and you can use them, ex:
var sellPosition = Positions.Find("Short", SymbolName, TradeType.Sell);
if (sellPosition != null && sellPosition.NetProfit > 0 && MACDline > prevMACDline)
{
ClosePosition(sellPosition);
}
var buyPosition = Positions.Find("Long", SymbolName, TradeType.Sell);
if (buyPosition != null && buyPosition.NetProfit > 0 && MACDline < prevMACDline)
{
ClosePosition(buyPosition);
}
Please check the API references example codes.
@amusleh
amusleh
04 Mar 2022, 15:12
Hi,
What do you mean by calling the custom indicators from PC?
You can reference and use custom indicators inside a cBot, here is the guide: https://help.ctrader.com/ctrader-automate/guides/indicators#referencing-custom-indicators
@amusleh
amusleh
04 Mar 2022, 07:37
Hi,
When you place a limit order you want to buy/sell something in a better price, not worse price than current price.
The issue with your code was the price of orders, for buy limit order you were adding 10 pips to current price, it's not how limit orders work, actually you should minus 10 pips from current price to buy it on a better price, here is your code that works:
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 NewcBot : Robot
{
[Parameter("Quantity (Lots)", Group = "Volume", DefaultValue = 1, MinValue = 0.01, Step = 0.01)]
public double Quantity { get; set; }
[Parameter("TP", DefaultValue = 20)]
public int TP { get; set; }
[Parameter("SL", DefaultValue = 10)]
public int SL { get; set; }
[Parameter("MA Type", Group = "Moving Average")]
public MovingAverageType MAType { get; set; }
[Parameter("Source", Group = "Moving Average")]
public DataSeries SourceSeries { get; set; }
[Parameter("Slow Periods", Group = "Moving Average", DefaultValue = 50)]
public int SlowPeriods { get; set; }
[Parameter("Fast Periods", Group = "Moving Average", DefaultValue = 16)]
public int FastPeriods { get; set; }
private MovingAverage slowMa;
private MovingAverage fastMa;
private const string label = "Sample Trend cBot";
protected override void OnStart()
{
fastMa = Indicators.MovingAverage(SourceSeries, FastPeriods, MAType);
slowMa = Indicators.MovingAverage(SourceSeries, SlowPeriods, MAType);
}
protected override void OnTick()
{
var longPosition = Positions.Find("Buy Limit", SymbolName, TradeType.Buy);
var shortPosition = Positions.Find("Sell Limit", SymbolName, TradeType.Sell);
var currentSlowMa = slowMa.Result.Last(0);
var currentFastMa = fastMa.Result.Last(0);
var previousSlowMa = slowMa.Result.Last(1);
var previousFastMa = fastMa.Result.Last(1);
if (Positions.Count == 0)
{
//Buy Entry
if (previousSlowMa > previousFastMa && currentSlowMa <= currentFastMa && longPosition == null)
{
if (PendingOrders.Count(item => item.OrderType == PendingOrderType.Limit && item.TradeType == TradeType.Buy) == 0)
PlaceLimitOrder(TradeType.Buy, SymbolName, VolumeInUnits, Symbol.Ask - 10 * Symbol.PipSize, "Buy Limit", SL, TP);
}
//Sell Entry
else if (previousSlowMa < previousFastMa && currentSlowMa >= currentFastMa && shortPosition == null)
{
if (PendingOrders.Count(item => item.OrderType == PendingOrderType.Limit && item.TradeType == TradeType.Sell) == 0)
PlaceLimitOrder(TradeType.Sell, SymbolName, VolumeInUnits, Symbol.Bid + 10 * Symbol.PipSize, "Sell Limit", SL, TP);
}
}
}
private double VolumeInUnits
{
get { return Symbol.QuantityToVolumeInUnits(Quantity); }
}
protected override void OnStop()
{
// Put your deinitialization logic here
}
}
}
If you want to buy something or sell something on worse price than current price then use stop order, with a stop order you can place an order to buy something 10 pips above it's current price.
@amusleh
amusleh
04 Mar 2022, 07:22
RE: RE: RE:
william@hallsdesign.co.uk said:
prenven570 said:
Edit:
i solved the problem of the unauthorized trading account, but the second question remains: How to open a position?
Hi, how did you solve the unauthorised trading account bit? I have this same issue and I am unsure how to solve. ( just changed my accountID to xxxxxxxx ).
Message received:
ctidTraderAccountId: xxxxxxxx
errorCode: "ACCOUNT_NOT_AUTHORIZED"
description: "Account is not authorized"Any help is greatly appreciated.
Hi,
You have to send a ProtoOAAccountAuthReq before sending any other request for an account.
After you received the ProtoOAAccountAuthRes then you can start sending other types of requests for that account.
Please check console sample setAccount command code.
@amusleh
amusleh
03 Mar 2022, 08:26
Hi,
Try this:
using System;
using cAlgo.API;
using cAlgo.API.Internals;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class NewcBot : Robot
{
[Parameter(DefaultValue = 10.5678)]
public double Pips { get; set; }
protected override void OnStart()
{
Print(NormalizePips(Pips));
}
private double NormalizePips(double pips)
{
var currentPrice = Convert.ToDecimal(Symbol.Bid);
var pipSize = Convert.ToDecimal(Symbol.PipSize);
var pipsDecimal = Convert.ToDecimal(pips);
var pipsAddedToCurrentPrice = Math.Round((pipsDecimal * pipSize) + currentPrice, Symbol.Digits);
var tickSize = Convert.ToDecimal(Symbol.TickSize);
var result = (pipsAddedToCurrentPrice - currentPrice) * (tickSize / pipSize * Convert.ToDecimal(Math.Pow(10, Symbol.Digits)));
return decimal.ToDouble(result);
}
}
}
It can normalize any Pips number to something that you can use as a stop loss or take profit.
It should work for all symbols.
@amusleh
amusleh
01 Mar 2022, 14:26
Hi,
You can do it like this:
# this will contain all symbol IDs with their bid/ask prices
symbolsData = dict()
def symbolsResponseCallback(result):
print("\nSymbols received")
symbols = Protobuf.extract(result)
global symbolsData
for symbol in symbols.symbol:
symbolsData.append(symbol.symbolId, (0, 0))
spotRequest = ProtoOASubscribeSpotsReq()
spotRequest.symbolId = symbol.symbolId
spotRequest.ctidTraderAccountId = credentials["AccountId"]
deferred = client.send(request)
deferred.addErrback(onError)
def accountAuthResponseCallback(result):
print("\nAccount authenticated")
request = ProtoOASymbolsListReq()
request.ctidTraderAccountId = credentials["AccountId"]
request.includeArchivedSymbols = False
deferred = client.send(request)
deferred.addCallbacks(symbolsResponseCallback, onError)
def applicationAuthResponseCallback(result):
print("\nApplication authenticated")
request = ProtoOAAccountAuthReq()
request.ctidTraderAccountId = credentials["AccountId"]
request.accessToken = credentials["AccessToken"]
deferred = client.send(request)
deferred.addCallbacks(accountAuthResponseCallback, onError)
def onError(client, failure): # Call back for errors
print("\nMessage Error: ", failure)
def disconnected(client, reason): # Callback for client disconnection
print("\nDisconnected: ", reason)
def onMessageReceived(client, message): # Callback for receiving all messages
if message.payloadType in [ProtoHeartbeatEvent().payloadType, ProtoOAAccountAuthRes().payloadType, ProtoOAApplicationAuthRes().payloadType, ProtoOASymbolsListRes().payloadType, ProtoOAGetTrendbarsRes().payloadType]:
return
elif message.payloadType == ProtoOASpotEvent().payloadType:
global symbolsData
spotEvent = Protobuf.extract(message)
symbolsData[spotEvent.symbolId] = (spotEvent.bid / 100000, spotEvent.ask / 100000)
# now you have the symbol prices, do anything you want to here or by using
# the symbolsData dictionary
#print("\nMessage received: \n", Protobuf.extract(message))
def connected(client): # Callback for client connection
print("\nConnected")
request = ProtoOAApplicationAuthReq()
request.clientId = credentials["ClientId"]
request.clientSecret = credentials["Secret"]
deferred = client.send(request)
deferred.addCallbacks(applicationAuthResponseCallback, onError)
# Setting optional client callbacks
client.setConnectedCallback(connected)
client.setDisconnectedCallback(disconnected)
client.setMessageReceivedCallback(onMessageReceived)
My code might have some issues as I haven't tested it but it will give you an idea.
@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