Topics
Replies
thoy1
27 Feb 2020, 06:51
RE:
PanagiotisCharalampous said:
Hi elmpie,
Yes it will be available in the API as well.
Best Regards,
Panagiotis
Hi Panagiotis,
Are we also able to have text-wrapping for Chart.DrawStaticText etc? So it will auto go to the next line if text is too wide for a percentage of the chart etc?
Say like: Chart.DrawStaticText("objname", "text", Vertical, Horizontal, Color, Font, Fontsize, Wrapping width %)?
Kind regards,
Thoy
@thoy1
thoy1
27 Feb 2020, 00:28
RE:
ClickAlgo said:
I would also consider buying one of the shelf if you have the funds, why invent the wheel :-)
http://www.babelfor.net/products/licensing
Paul Hayes
Sales & Marketing
Email: contact@clickalgo.com
Phone: (44) 203 289 6573
Website: https://clickalgo.comTwitter | Facebook | YouTube | Pinterest | LinkedIn
PS: Why not join our instant chat group on Telegram or visit our YouTube Channel
Hi Paul,
That solution does indeed look awesome. Do you have any idea what the going rate for profitable bots is? I too have made one which I am looking at commercializing. It pulls in roughly 70% return per annum. I have also backtested it across 8 years to ensure it makes it through the 2011-2015 period (Aussie Boom, Brexit, US slump, CHF ceiling removal etc). Your thoughts?
TIA
Thoy
@thoy1
thoy1
13 Feb 2020, 12:43
( Updated at: 21 Dec 2023, 09:21 )
RE:
PanagiotisCharalampous said:
Hi thoy1,
See below
Symbol symbol = Symbols.GetSymbol(position.SymbolName);
Best Regards,
Panagiotis
Hi Pangiotis,
So I have managed to get my full bot working which is programmed quite clunky (lots of repetition for multiple symbols etc. I have done my best to get it to process each symbol with a loop but the looped version crashes in OnBar. Any ideas on why this might be? My settings to leave a couple of Symbols empty is deliberate for testing functionality. Cheers :)
EDIT: I have since done another backtest with all the symbol info entered, and found that it works 100%. So the issue has to do with MySymbols not processing the nullorwhitespace correctly. I have assumed that it would still test this against the initial 'if' statement, but this appears to be where it is crashing. I have removed all the code that isn't required for testing this behavior.
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
{
//Instrument Information------------------------------------------------------------------------------------------------------------------------------------------Instrument Information
[Parameter("Number of Instruments", DefaultValue = 12, Group = "Instrument Info")]
public double instruments { get; set; }
[Parameter("Symbol 1", DefaultValue = "AUDCAD.spa", Group = "Instrument Info")]
public string symbol_1 { get; set; }
[Parameter("Symbol 2", DefaultValue = "AUDCHF.spa", Group = "Instrument Info")]
public string symbol_2 { get; set; }
[Parameter("Symbol 3", DefaultValue = "AUDNZD.spa", Group = "Instrument Info")]
public string symbol_3 { get; set; }
[Parameter("Symbol 4", DefaultValue = "CADCHF.spa", Group = "Instrument Info")]
public string symbol_4 { get; set; }
[Parameter("Symbol 5", DefaultValue = "GBPAUD.spa", Group = "Instrument Info")]
public string symbol_5 { get; set; }
[Parameter("Symbol 6", DefaultValue = "GBPCAD.spa", Group = "Instrument Info")]
public string symbol_6 { get; set; }
[Parameter("Symbol 7", DefaultValue = "GBPCHF.spa", Group = "Instrument Info")]
public string symbol_7 { get; set; }
[Parameter("Symbol 8", DefaultValue = "GBPNZD.spa", Group = "Instrument Info")]
public string symbol_8 { get; set; }
[Parameter("Symbol 9", DefaultValue = "NZDCAD.spa", Group = "Instrument Info")]
public string symbol_9 { get; set; }
[Parameter("Symbol 10", DefaultValue = "NZDUSD.spa", Group = "Instrument Info")]
public string symbol_10 { get; set; }
[Parameter("Symbol 11", DefaultValue = "USDCAD.spa", Group = "Instrument Info")]
public string symbol_11 { get; set; }
[Parameter("Symbol 12", DefaultValue = "USDZAR.spa", Group = "Instrument Info")]
public string symbol_12 { get; set; }
//Declarations--------------------------------------------------------------------------------------------------------------------------------------------------------------Declarations
private Symbol sym;
public Symbol[] MySymbols;
Color clrPlus = Color.Gray;
Color clrMinus = Color.Gray;
//On Start//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////On Start
//On Start//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////On Start
protected override void OnStart()
{
if (string.IsNullOrWhiteSpace(symbol_1) == true && string.IsNullOrWhiteSpace(symbol_2) == true && string.IsNullOrWhiteSpace(symbol_3) == true && string.IsNullOrWhiteSpace(symbol_4) == true && string.IsNullOrWhiteSpace(symbol_5) == true && string.IsNullOrWhiteSpace(symbol_6) == true && string.IsNullOrWhiteSpace(symbol_7) == true && string.IsNullOrWhiteSpace(symbol_8) == true && string.IsNullOrWhiteSpace(symbol_9) == true && string.IsNullOrWhiteSpace(symbol_10) == true && string.IsNullOrWhiteSpace(symbol_11) == true && string.IsNullOrWhiteSpace(symbol_12) == true)
{
Print("No active instruments, Bot has stopped running.");
Stop();
}
}
//On Bar//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////On Bar
//On Bar//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////On Bar
protected override void OnBar()
{
double riskvol = Account.Equity / instruments;
MySymbols = Symbols.GetSymbols("" + symbol_1, "" + symbol_2, "" + symbol_3, "" + symbol_4, "" + symbol_5, "" + symbol_6, "" + symbol_7, "" + symbol_8, "" + symbol_9, "" + symbol_10,
"" + symbol_11, "" + symbol_12);
foreach (var symbol in MySymbols)
{
Print("{0}", symbol.Name);
//for testing
if (string.IsNullOrWhiteSpace(symbol.Name) == false)
{
sym = Symbols.GetSymbol(symbol.Name);
Print("{0} Passed", sym);
}
}
}
//On Stop////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////On Stop
//On Stop////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////On Stop
protected override void OnStop()
{
// Put your deinitialization logic here
}
}
}
@thoy1
thoy1
13 Feb 2020, 09:06
RE:
PanagiotisCharalampous said:
Hi Takis,
Just use the code you posted and enable/disable your network adapter. You should see the events registering in the log.
Best Regards,
Panagiotis
Hi Panagiotis,
This is also how I tested Takis' work and found it to work well.
I have also sorted out my NaN issue. For some reason it didn't like me using moving average for the BB data series. Possibly because I was asking the BB to have 90 results after the MA had its 90 results, so my backtesting probably needed to wait for 180 days of data to be loaded befor the NaN became a decimal. I have removed the MA from the code and it works well now :)
I have run into another issue though. I can't seem to extract the SymbolName from position info in order to find the Ask/Bid price of said symbol. I am aware position.SymbolName is in string format, where I need to use it in Symbol format. Please see the code below, cheers :) The aim here is to move the SL protection to an 'in-profit' position when the Ask/Bid has moved enough.
foreach (var position in Positions)
{
Symbol symbol = position.SymbolName; //Need to convert to Symbol, not string.
TradeType tradetype = position.TradeType;
double entry = position.EntryPrice;
double? tp = position.TakeProfit;
double? newsl = (tp + entry) / 2;
//Print("entry is: {0} TP is: {1}", entry, tp); //Testing how data got extracted
if (tradetype == TradeType.Buy)
{
if (symbol.Ask >= newsl + ((tp - entry) * 0.1))
{
ModifyPosition(position, newsl, tp);
}
}
else
{
if (symbol.Bid <= newsl - ((entry - tp) * 0.1))
{
ModifyPosition(position, newsl, tp);
}
}
}
@thoy1
thoy1
11 Feb 2020, 20:39
RE: RE:
Takis Genn said:
I saw this some days ago and forced it out with the line PlusMinusColors(true)
Server.IsConnected and events OnServerConnected, OnServerDisconnected do not work.
The way i use them:
Color clrPlus = Color.Gray;
Color clrMinus = Color.Gray;protected override void Initialize()
{
Server.Connected += OnServerConnected;
Server.Disconnected += OnServerDisconnected;
PlusMinusColors(Server.IsConnected);
//PlusMinusColors(true);
void OnServerConnected()
{
PlusMinusColors(true);
}
void OnServerDisconnected()
{
PlusMinusColors(false);
}
void PlusMinusColors(bool plus)
{
if (plus)
{
clrPlus = Color.Lime;
clrMinus = Color.Tomato;
}
else
{
clrPlus = Color.Gray;
clrMinus = Color.Gray;
}
}
Hi Takis,
You legend! I had tried so many OnTimer options and none of them seemed to register the re-connections. Your version works beautifully!
For anybody else reading this thread I have completed the code to have the Thread.Sleep included. The reason for this script is upon reconnecting, the server at times sends a false Bid/Ask price and my bot likes to trade on it - creating a label which is well out of the array my bot runs. This delay allows ctrader to fully catch-up and have accurate Bid/Ask prices.
Now I just need to solve my BollingerBand issue.
using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
using System.Threading;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class ConnectionTest : Robot
{
Color clrPlus = Color.Gray;
Color clrMinus = Color.Gray;
protected override void OnStart()
{
// Put your initialization logic here
Server.Connected += OnServerConnected;
Server.Disconnected += OnServerDisconnected;
PlusMinusColors(Server.IsConnected);
}
void OnServerConnected()
{
PlusMinusColors(true);
}
void OnServerDisconnected()
{
PlusMinusColors(false);
}
void PlusMinusColors(bool plus)
{
if (plus)
{
clrPlus = Color.Lime;
clrMinus = Color.Tomato;
Print("Connected, pausing trades for 15 seconds.");
System.Threading.Thread.Sleep(15000);
Print("Trading active again.");
}
else
{
clrPlus = Color.Gray;
clrMinus = Color.Gray;
Print("Disconnected");
}
}
protected override void OnTick()
{
Print("Tick");
}
protected override void OnStop()
{
// Put your deinitialization logic here
}
}
}
@thoy1
thoy1
10 Feb 2020, 09:36
( Updated at: 21 Dec 2023, 09:21 )
RE:
PanagiotisCharalampous said:
Hi thoy1,
1) You have placed your checks in OnTick. If the server is disconnected, you will not receive any ticks hence no checks will be made. Use a timer instead.
2) I could not reproduce any NaN values with your BollingerTest. Can you provide exact steps to reproduce this problem and post some screenshots as well?
Best Regards,
Panagiotis
Hi Panagiotis,
1) Ahh yes, an oversight of mine. That makes sense, thanks.
2) I have added a screen-shot. The Print lines in the above code are for troubleshooting. In the shot below you can see that both the 'Top Value' and 'Bottom Value' are giving NaN, this is causing 's1range' to produce a NaN error also, and subsequently both 's1buy' and 's1sell' (entry positions) are showing NaN too.
@thoy1
thoy1
09 Feb 2020, 05:22
This is the second issue to do with Bollinger Band data.
In this Bot I am trying to find out the numerical value of the Top and Bottom bands. Both of the lines are bring up a NaN (Not a Number) error. As a result, trades are not being placed when I would expect them to be. How do I convert bb1.Top.LastValue and bb1.Bottom.LastValue into numbers? TIA
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 BollingerTest : Robot
{
//Instrument Information------------------------------------------------------------------------------------------------------------------------------------------Instrument Information
[Parameter("Symbol 1", DefaultValue = "AUDCAD", Group = "Instrument Info")]
public string symbol_1 { get; set; }
//Protection Settings------------------------------------------------------------------------------------------------------------------------------------------------Protection Settings
[Parameter("Take Profit Strength:", DefaultValue = 70, Group = "Protection Settings")]
public double tpstrength { get; set; }
[Parameter("Stop Loss Strength:", DefaultValue = 30, Group = "Protection Settings")]
public double slstrength { get; set; }
[Parameter("Range percent for order trigger:", DefaultValue = 85, Group = "Protection Settings")]
public double range { get; set; }
//Declarations--------------------------------------------------------------------------------------------------------------------------------------------------------------Declarations
private SimpleMovingAverage ma1;
private Bars series1;
private Symbol symbol1;
private BollingerBands bb1;
//On Start//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////On Start
protected override void OnStart()
{
if (string.IsNullOrWhiteSpace(symbol_1) == false)
{
Print("Symbol 1 = {0}", symbol_1);
}
}
//On Bar//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////On Bar
protected override void OnBar()
{
symbol1 = Symbols.GetSymbol(symbol_1);
series1 = MarketData.GetBars(TimeFrame.Daily, symbol_1);
ma1 = Indicators.SimpleMovingAverage(series1.MedianPrices, 90);
bb1 = Indicators.BollingerBands(ma1.Result, 90, 2.5, MovingAverageType.Simple);
if (string.IsNullOrWhiteSpace(symbol_1) == false)
{
Print("pass");
double s1range = (bb1.Top.LastValue - bb1.Bottom.LastValue);
double s1sell = bb1.Bottom.LastValue + (s1range * (range / 100));
double s1buy = bb1.Top.LastValue - (s1range * (range / 100));
double s1sl = s1range * (slstrength / 100);
double s1tp = s1range * (tpstrength / 100);
double s1vol = 1000;
Print("s1sell: {0}", s1sell);
Print("s1buy: {0}", s1buy);
Print("ask = {0}", symbol1);
Print("Top: {0}", bb1.Top.LastValue);
Print("Bottom: {0}", bb1.Bottom.LastValue);
Print("Pos Count: {0}", Positions.Where(x => x.SymbolName == symbol_1).Count());
if (Positions.Where(x => x.SymbolName == symbol_1).Count() < 1)
{
if (symbol1.Ask >= s1sell)
{
ExecuteMarketOrder(TradeType.Sell, symbol_1, s1vol, "" + symbol_1 + "_Sell", s1sl, s1tp);
}
else if (symbol1.Bid <= s1buy)
{
ExecuteMarketOrder(TradeType.Buy, symbol_1, s1vol, "" + symbol_1 + "_Buy", s1sl, s1tp);
}
}
}
}
protected override void OnStop()
{
// Put your deinitialization logic here
}
}
}
@thoy1
thoy1
08 Oct 2019, 12:39
RE:
Panagiotis Charalampous said:
Hi reza h,
We plan to release this feature in v3.7.
Best Regards,
Panagiotis
Fantastic news!
This will be a gamechanger in Bot development and strategy development for many.
With 3.6 having just released I am looking forward to the next version release (3.7)
~Thoy1
@thoy1
thoy1
04 Oct 2019, 09:17
RE:
Panagiotis Charalampous said:
Hi thoy1,
Thanks for sharing your cBot with us. You can always upload it in the relevant algo section so that it does not get lost in the discussions.
Best Regards,
Panagiotis
Hi Panagiotis,
I have done this now. Thanks for the suggestion :)
Kind regards,
Thoy1
@thoy1
thoy1
01 Oct 2019, 05:58
RE:
Panagiotis Charalampous said:
Hi thoy1,
Try
PendingOrders.Count(x => x.TradeType == TradeType.Buy)Best Regards,
Panagiotis
Hi Panagiotis,
Edit:
Nevermind, I used the first two lines, followed by the remaining code to show its purpose. This will be usefull to anyone running bot's which have multiple positions on multiple instruments.
int buyCount = Positions.Where(x => x.SymbolName == Symbol.Name).Where(x => x.TradeType == TradeType.Buy).Count(); int sellCount = Positions.Where(x => x.SymbolName == Symbol.Name).Where(x => x.TradeType == TradeType.Sell).Count(); Chart.DrawStaticText("Account Stats", "Balance: " + Account.Balance + " Equity: " + Account.Equity, VerticalAlignment.Top, HorizontalAlignment.Center, Color.SkyBlue); Chart.DrawStaticText("Chart Text", "Number of Positions: " + (buyCount + sellCount), VerticalAlignment.Bottom, HorizontalAlignment.Center, Color.SkyBlue); if (buyCount == sellCount) { Chart.RemoveObject("Symbol Strength"); Chart.DrawStaticText("Symbol Strength", "Symbol is in Equilibrium", VerticalAlignment.Center, HorizontalAlignment.Center, Color.Yellow); } else if (buyCount > sellCount) { Chart.RemoveObject("Symbol Strength"); Chart.DrawStaticText("Symbol Strength", "Position is: Buy $" + (buyCount - sellCount) + "k", VerticalAlignment.Center, HorizontalAlignment.Center, Color.Yellow); } else { Chart.RemoveObject("Symbol Strength"); Chart.DrawStaticText("Symbol Strength", "Position is: Sell $" + (sellCount - buyCount) + "k", VerticalAlignment.Center, HorizontalAlignment.Center, Color.Yellow); }
Thanks and regards,
Thoy
@thoy1
thoy1
15 May 2018, 12:39
Awesome! Thanks!
if (Positions.Count + PendingOrders.Count < noOfIncrements * 2) { if ((PendingOrders.Count(x => x.TradeType == TradeType.Buy) + Positions.Count(x => x.TradeType == TradeType.Buy)) < maximumTrades) { if (Symbol.Ask <= rangeLow && Symbol.Ask <= tpRangeLow) { ExecuteMarketOrder(TradeType.Buy, Symbol, buyVolume, "" + newOrder, stopLoss, buytpExtreme); } if (Symbol.Ask <= rangeLow && Symbol.Ask > tpRangeLow) { ExecuteMarketOrder(TradeType.Buy, Symbol, buyVolume, "" + newOrder, stopLoss, takeProfit); } if (Symbol.Ask > rangeLow && Symbol.Ask < rangeHigh) { ExecuteMarketOrder(TradeType.Buy, Symbol, buyVolume, "" + newOrder, stopLoss, takeProfit); } } if ((PendingOrders.Count(x => x.TradeType == TradeType.Sell) + Positions.Count(x => x.TradeType == TradeType.Sell)) < maximumTrades) { if (Symbol.Ask > rangeLow && Symbol.Ask < rangeHigh) { ExecuteMarketOrder(TradeType.Sell, Symbol, sellVolume, "" + newOrder, stopLoss, takeProfit); } if (Symbol.Ask > rangeHigh && Symbol.Ask < tpRangeHigh) { ExecuteMarketOrder(TradeType.Sell, Symbol, sellVolume, "" + newOrder, stopLoss, takeProfit); } if (Symbol.Ask >= rangeHigh && Symbol.Ask >= tpRangeHigh) { ExecuteMarketOrder(TradeType.Sell, Symbol, sellVolume, "" + newOrder, stopLoss, selltpExtreme); } } }
Awesome, here is what the code ended up looking like :) Now to see if this solves the behaviour I saw in backtesting.
@thoy1
thoy1
18 Feb 2018, 04:43
RE:
Hi Panagiotis,
Thanks for the response. I ended up getting the issue sorted, after discovering a loop in the close/open opposite sequence a few changes were needed. I have posted the finished bot below, works 100% with back testing complete too - and resulted in a steady 20-25° downward slope. Hopefully the script below can help anybody else wanting to explore the idea further :)
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 AATracer : Robot { [Parameter("Volume", DefaultValue = 1000)] public int _volume { get; set; } [Parameter("Gap Size", DefaultValue = 15)] public int _gapsize { get; set; } [Parameter("Take Profit", DefaultValue = 15)] public int _takeprofit { get; set; } [Parameter("Stop Loss", DefaultValue = 15)] public int _stoploss { get; set; } public double balance; public bool stopping = false; public TradeType last; public TradeResult lastposition; public HistoricalTrade tradetype; public PositionClosedEventArgs args; protected override void OnStart() { // Put initialization logic here Positions.Closed += PositionsClosed; lastposition = ExecuteMarketOrder(TradeType.Buy, Symbol, _volume, "last", _stoploss, _takeprofit); } protected override void OnTick() { // Open more trades if the price moved x amount of pips if (lastposition != null && lastposition.Position.Pips > _gapsize) { if (lastposition.Position.TradeType == TradeType.Buy) { lastposition = ExecuteMarketOrder(TradeType.Buy, Symbol, _volume, "last", _stoploss, _takeprofit); } else if (lastposition.Position.TradeType == TradeType.Sell) { lastposition = ExecuteMarketOrder(TradeType.Sell, Symbol, _volume, "last", _stoploss, _takeprofit); } } if (stopping == true) { // Close all open positions foreach (var position in Positions) { ClosePosition(position); // Timer.Start(TimeSpan.FromSeconds(10000)); } System.Threading.Thread.Sleep(30000); stopping = false; } else if (stopping == false) { if (Positions.Count == 0) { // Open opposite trade if (last == TradeType.Buy) { lastposition = ExecuteMarketOrder(TradeType.Sell, Symbol, _volume, "last", _stoploss, _takeprofit); } else { lastposition = ExecuteMarketOrder(TradeType.Buy, Symbol, _volume, "last", _stoploss, _takeprofit); } } } } private void PositionsClosed(PositionClosedEventArgs args) { stopping = true; last = args.Position.TradeType; } protected override void OnStop() { // Put deinitialization logic here } } }
@thoy1
thoy1
27 Feb 2020, 07:02
RE: RE:
Hi All,
I have found the solution to my issue. Will leave this here for everyone's reference.
Kind regards,
~Thoy
@thoy1