Description
Very special thanks to SaifBD for posting the very original code on to ctrader.com, that made the version 1 of the code
https://ctrader.com/algos/cbots/show/876
Special thanks to Candeias for re-writing the decompiled code to more human readable code which made the version 2 of the code.
Also, very thanks to Panagiotis Charalampous, every time I encountered cBot programing issue and try to search online, I will always find your useful code and suggestions posted on cTrader forum!
Many thanks to the folks’ comments on ctrader.com to made improvements on this code.
I re-wrote the code and shortend the code by more than half thanks to the use of System.Linq Namespaces.
This cBot works best with 15 minutes chart. Default parameters are optimized for EURUSD and GBPUSD.
This project is on GitHub as well
https://github.com/jumpycalm/jumpycalm-cBot-Grid-V3
Change logs:
20190416 (Version 3.0) This is the first version, code is based on the code written by Candeias (Version 2). Some changes below:
1. Code was cleaned up and code was modified to work on cTrader 3.5. The code is not backwards compatible with older version of cTrader;
2. Open buy and open sell Boolean was replaced with maximum open buy and sell number. For example, if you predict future is bullish market, set Maximum open sell position to 0;
3. The long-awaited stop loss was added. However, setting up stop loss is not recommended. If you don't need to enable stop loss, set stop loss to a very large number;
4. Setup parameters were grouped, new feature for cTrader 3.5
5. Added close all trade on stop flag to easy back test and forward test cBot. Currently, cTrader backtester does not show equity with open position when cBot stopped. So, this feature is crucial for accurate back test.
6. cTrader does not handle order take profit well, so, instead of setting a take profit value, this version will check open position on each tick and will execute close order then condition met.
7. I only back tested with this cBot, so, the chart drawing function was not tested. Chart drawing code was the original code from version 2.
Please leave comments below or post a pool on github. If you have coding background, feel free add your suggestions on github.
I hope the whole community here makes a best grid cBot in the market.
I am a software developer, I work for myself, there's no middleman involved. If you have a strategy and would like me to write the code for you. I can offer you the best price in the market. I only write cBot and cTrader indicators. I do not write MT4 and MT5 code.
For business contact, email me at info@mrkeyfob.com
//To use Math
using System;
//To use Positions.Count() method
using System.Linq;
using cAlgo.API;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class SmartGridV3 : Robot
{
[Parameter("Maximum open buy position?", Group = "Basic Setup", DefaultValue = 8, MinValue = 0)]
public int MaxOpenBuy { get; set; }
[Parameter("Maximum open Sell position?", Group = "Basic Setup", DefaultValue = 8, MinValue = 0)]
public int MaxOpenSell { get; set; }
[Parameter("Pip step", Group = "Basic Setup", DefaultValue = 10, MinValue = 1)]
public int PipStep { get; set; }
[Parameter("Stop loss pips", Group = "Basic Setup", DefaultValue = 100, MinValue = 10, Step = 10)]
public double StopLossPips { get; set; }
[Parameter("First order volume", Group = "Basic Setup", DefaultValue = 1000, MinValue = 1, Step = 1)]
public double FirstVolume { get; set; }
[Parameter("Max spread allowed to open position", Group = "Basic Setup", DefaultValue = 3.0)]
public double MaxSpread { get; set; }
[Parameter("Target profit for each group of trade", Group = "Basic Setup", DefaultValue = 3, MinValue = 1)]
public int AverageTakeProfit { get; set; }
[Parameter("Debug flag, set to No on real account to avoid closing all positions when stoping this cBot", Group = "Advanced Setup", DefaultValue = false)]
public bool IfCloseAllPositionsOnStop { get; set; }
[Parameter("Volume exponent", Group = "Advanced Setup", DefaultValue = 1.0, MinValue = 0.1, MaxValue = 5.0)]
public double VolumeExponent { get; set; }
private string ThiscBotLabel;
private DateTime LastBuyTradeTime;
private DateTime LastSellTradeTime;
// cBot initialization
protected override void OnStart()
{
// Set position label to cBot name
ThiscBotLabel = this.GetType().Name;
// Normalize volume in case a wrong volume was entered
if (FirstVolume != (FirstVolume = Symbol.NormalizeVolumeInUnits(FirstVolume)))
{
Print("Volume entered incorrectly, volume has been changed to ", FirstVolume);
}
}
// Error handling
protected override void OnError(Error error)
{
Print("Error occured, error code: ", error.Code);
}
protected override void OnTick()
{
// Close all buy positions if all buy positions' target profit is met
if (Positions.Count(x => x.TradeType == TradeType.Buy && x.SymbolName == SymbolName && x.Label == ThiscBotLabel) > 0)
{
if (Positions.Where(x => x.TradeType == TradeType.Buy && x.SymbolName == SymbolName && x.Label == ThiscBotLabel).Average(x => x.NetProfit) >= FirstVolume * AverageTakeProfit * Symbol.PipSize)
{
foreach (var position in Positions)
{
if (position.TradeType == TradeType.Buy && position.SymbolName == SymbolName && position.Label == ThiscBotLabel)
ClosePosition(position);
}
}
}
// Close all sell positions if all sell positions' target profit is met
if (Positions.Count(x => x.TradeType == TradeType.Sell && x.SymbolName == SymbolName && x.Label == ThiscBotLabel) > 0)
{
if (Positions.Where(x => x.TradeType == TradeType.Sell && x.SymbolName == SymbolName && x.Label == ThiscBotLabel).Average(x => x.NetProfit) >= FirstVolume * AverageTakeProfit * Symbol.PipSize)
{
foreach (var position in Positions)
{
if (position.TradeType == TradeType.Sell && position.SymbolName == SymbolName && position.Label == ThiscBotLabel)
ClosePosition(position);
}
}
}
// Conditions check before process trade
if (Symbol.Spread / Symbol.PipSize <= MaxSpread)
{
if (Positions.Count(x => x.TradeType == TradeType.Buy && x.SymbolName == SymbolName && x.Label == ThiscBotLabel) < MaxOpenBuy)
ProcessBuy();
if (Positions.Count(x => x.TradeType == TradeType.Sell && x.SymbolName == SymbolName && x.Label == ThiscBotLabel) < MaxOpenSell)
ProcessSell();
}
if (!this.IsBacktesting)
DisplayStatusOnChart();
}
protected override void OnStop()
{
Chart.RemoveAllObjects();
// Close all open positions opened by this cBot on stop
if (this.IsBacktesting || IfCloseAllPositionsOnStop)
{
foreach (var position in Positions)
{
if (position.SymbolName == SymbolName && position.Label == ThiscBotLabel)
ClosePosition(position);
}
}
}
private void ProcessBuy()
{
if (Positions.Count(x => x.TradeType == TradeType.Buy && x.SymbolName == SymbolName && x.Label == ThiscBotLabel) == 0 && MarketSeries.Close.Last(1) > MarketSeries.Close.Last(2))
{
ExecuteMarketOrder(TradeType.Buy, SymbolName, FirstVolume, ThiscBotLabel, StopLossPips, null);
LastBuyTradeTime = MarketSeries.OpenTime.Last(0);
}
if (Positions.Count(x => x.TradeType == TradeType.Buy && x.SymbolName == SymbolName && x.Label == ThiscBotLabel) > 0)
{
if (Symbol.Ask < (Positions.Where(x => x.TradeType == TradeType.Buy && x.SymbolName == SymbolName && x.Label == ThiscBotLabel).Min(x => x.EntryPrice) - PipStep * Symbol.PipSize) && LastBuyTradeTime != MarketSeries.OpenTime.Last(0))
{
ExecuteMarketOrder(TradeType.Buy, SymbolName, CalculateVolume(TradeType.Buy), ThiscBotLabel, StopLossPips, null);
LastBuyTradeTime = MarketSeries.OpenTime.Last(0);
}
}
}
private void ProcessSell()
{
if (Positions.Count(x => x.TradeType == TradeType.Sell && x.SymbolName == SymbolName && x.Label == ThiscBotLabel) == 0 && MarketSeries.Close.Last(2) > MarketSeries.Close.Last(1))
{
ExecuteMarketOrder(TradeType.Sell, SymbolName, FirstVolume, ThiscBotLabel, StopLossPips, null);
LastSellTradeTime = MarketSeries.OpenTime.Last(0);
}
if (Positions.Count(x => x.TradeType == TradeType.Sell && x.SymbolName == SymbolName && x.Label == ThiscBotLabel) > 0)
{
if (Symbol.Bid > (Positions.Where(x => x.TradeType == TradeType.Sell && x.SymbolName == SymbolName && x.Label == ThiscBotLabel).Max(x => x.EntryPrice) + PipStep * Symbol.PipSize) && LastSellTradeTime != MarketSeries.OpenTime.Last(0))
{
ExecuteMarketOrder(TradeType.Sell, SymbolName, CalculateVolume(TradeType.Sell), ThiscBotLabel, StopLossPips, null);
LastSellTradeTime = MarketSeries.OpenTime.Last(0);
}
}
}
private double CalculateVolume(TradeType tradeType)
{
return Symbol.NormalizeVolumeInUnits(FirstVolume * Math.Pow(VolumeExponent, Positions.Count(x => x.TradeType == tradeType && x.SymbolName == SymbolName && x.Label == ThiscBotLabel)));
}
private void DisplayStatusOnChart()
{
if (Positions.Count(x => x.TradeType == TradeType.Buy && x.SymbolName == SymbolName && x.Label == ThiscBotLabel) > 1)
{
var y = Positions.Where(x => x.TradeType == TradeType.Buy && x.SymbolName == SymbolName && x.Label == ThiscBotLabel).Average(x => x.EntryPrice);
Chart.DrawHorizontalLine("bpoint", y, Color.Yellow, 2, LineStyle.Dots);
}
else
Chart.RemoveObject("bpoint");
if (Positions.Count(x => x.TradeType == TradeType.Sell && x.SymbolName == SymbolName && x.Label == ThiscBotLabel) > 1)
{
var z = Positions.Where(x => x.TradeType == TradeType.Sell && x.SymbolName == SymbolName && x.Label == ThiscBotLabel).Average(x => x.EntryPrice);
Chart.DrawHorizontalLine("spoint", z, Color.HotPink, 2, LineStyle.Dots);
}
else
Chart.RemoveObject("spoint");
Chart.DrawStaticText("pan", GenerateStatusText(), VerticalAlignment.Top, HorizontalAlignment.Left, Color.Tomato);
}
private string GenerateStatusText()
{
var statusText = "";
var buyPositions = "";
var sellPositions = "";
var spread = "";
var buyDistance = "";
var sellDistance = "";
spread = "\nSpread = " + Math.Round(Symbol.Spread / Symbol.PipSize, 1);
buyPositions = "\nBuy Positions = " + Positions.Count(x => x.TradeType == TradeType.Buy && x.SymbolName == SymbolName && x.Label == ThiscBotLabel);
sellPositions = "\nSell Positions = " + Positions.Count(x => x.TradeType == TradeType.Sell && x.SymbolName == SymbolName && x.Label == ThiscBotLabel);
if (Positions.Count(x => x.TradeType == TradeType.Buy && x.SymbolName == SymbolName && x.Label == ThiscBotLabel) > 0)
{
var averageBuyFromCurrent = Math.Round((Positions.Where(x => x.TradeType == TradeType.Buy && x.SymbolName == SymbolName && x.Label == ThiscBotLabel).Average(x => x.EntryPrice) - Symbol.Bid) / Symbol.PipSize, 1);
buyDistance = "\nBuy Target Away = " + averageBuyFromCurrent;
}
if (Positions.Count(x => x.TradeType == TradeType.Sell && x.SymbolName == SymbolName && x.Label == ThiscBotLabel) > 0)
{
var averageSellFromCurrent = Math.Round((Symbol.Ask - Positions.Where(x => x.TradeType == TradeType.Sell && x.SymbolName == SymbolName && x.Label == ThiscBotLabel).Average(x => x.EntryPrice)) / Symbol.PipSize, 1);
sellDistance = "\nSell Target Away = " + averageSellFromCurrent;
}
if (Symbol.Spread / Symbol.PipSize > MaxSpread)
statusText = "MAX SPREAD EXCEED";
else
statusText = ThiscBotLabel + buyPositions + spread + sellPositions + buyDistance + sellDistance;
return (statusText);
}
}
}
jumpycalm
Joined on 28.03.2019
- Distribution: Free
- Language: C#
- Trading platform: cTrader Automate
- File name: Smart Grid V3.algo
- Rating: 5
- Installs: 5318
- Modified: 13/10/2021 09:55
Comments
Thanks for you effor jumycalm , in the code there is bug becuase the exponent volum can not work better it open trade with same lot in same direction
Guys, any setting can share please?
Can someone please help me, how do I fix the sell only problem
Thank you! :)
@tgjobscv To fix the buy issue.
When there are no buy trades the FindLowestPositionPrice is zero. The ask is never going to be less than zero.so the first buy trade will never happen
Add an || FindLowestPositionPrice == 0 to add the first buy
Change
// send buy orders
if (direction == 1)
{
if (Math.Round(Symbol.Ask, Symbol.Digits) < Math.Round(FindLowestPositionPrice(TradeType.Buy) - PipStep * Symbol.PipSize, Symbol.Digits) || (FindLowestPositionPrice(TradeType.Buy) == 0 )
Hi
I LOVE this bot. Well done and thank you
However I have a challenge. It seems to not trade JPY pairs unlike version 1. How can I fix this.
Many Thanks
Hi.
Mod SmartGrid:
https://ctrader.com/algos/cbots/show/876
up 07.2020
SellSmartGrid - Only - Sell trend (parametr Buy is ignoring) with MA and one way trend LimitStop Sell H1 H4 - only Sell trend backtest date.
https://ctrader.com/forum/calgo-support/22008?page=1
up 07.2020
What are your ideas for improving the code after testing - for Sell trend in xauusd, xagusd, majors etc ?
SellSmartGrid - improving ?!
How 1. cTrader demo to live ctrader, mt4/mt5 Trade Copier ?
How 2. mt4/mt5 demo to live ctrader, mt4/mt5 Trade Copier ?
How cTrader demo to live ctrader, mt4/mt5 Trade Copier ?
CoreTradingHouse,
A couple more observations too:
First Volume is always 1000, regardless of what number you put in the field.
Volume Exponent isn't accurate, and sometimes places the highest volume trade on starting a new grid even once the grid restarted. Eg: previous grid may get to 12 lots, then grid closes, then new grid starts at 12 lots instead of 0.1.
Just some hopefully helpful observations so far :)
Mr4x
CoreTradingHouse,
I compiled your version of the grid trade and definitely very interesting results. 20% profit over a 3 year period on EURUSD but one thing I noticed is that it only places sell trades? Anyway thought you should know :)
Another idea I have, but my bot-building skills are basic at best, is to incorporate a moving average to smartgrid V3 that can be defined by the user, and have the bot only grid in the direction of the moving average, with an overall take profit that closes all long and short positions when x amount in profit. What do you think?
Mr4x
@jumpycalm working on something new right now!
Added:
- 1 std BB
- 2 std BB
- Awesome oscillator
instead of opening trades, when ist overbought / sold, it places 3 stop orders with 1 day expiration. Then the grid is managed as usual.
Still has to be polished, but it seriously reduces DD. tell me what you think, and suggestions are accepted! :)
//------------------------------------------------------
using System;
using cAlgo.API;
using cAlgo.API.Indicators;
namespace cAlgo
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class SmartGrid : Robot
{
private bool _accountIsOutOfMoney;
private int _openTradeResult;
private readonly string Label = "SmartGrid2";
private DateTime _lastBuyTradeTime;
private DateTime _lastSellTradeTime;
[Parameter("Buy", DefaultValue = true)]
public bool Buy { get; set; }
[Parameter("Sell", DefaultValue = true)]
public bool Sell { get; set; }
[Parameter("Pip Step", DefaultValue = 10, MinValue = 1)]
public int PipStep { get; set; }
[Parameter("First Volume", DefaultValue = 1000, MinValue = 1000, Step = 1000)]
public int FirstVolume { get; set; }
[Parameter("Volume Exponent", DefaultValue = 1.0, MinValue = 0.1, MaxValue = 5.0)]
public double VolumeExponent { get; set; }
[Parameter("Max Spread", DefaultValue = 3.0)]
public double MaxSpread { get; set; }
[Parameter("Average TP", DefaultValue = 3, MinValue = 1)]
public int AverageTakeProfit { get; set; }
[Parameter("BB_Source")]
public DataSeries BB_Source { get; set; }
[Parameter("BandPeriods", DefaultValue = 20)]
public int BB_BandPeriod { get; set; }
[Parameter("Std", DefaultValue = 1)]
public int BB_std { get; set; }
[Parameter("MAType")]
public MovingAverageType BB_MAType { get; set; }
[Parameter("BB2_Source")]
public DataSeries BB2_Source { get; set; }
[Parameter("BandPeriods", DefaultValue = 20)]
public int BB2_BandPeriod { get; set; }
[Parameter("Std", DefaultValue = 2)]
public int BB2_std { get; set; }
[Parameter("MAType")]
public MovingAverageType BB2_MAType { get; set; }
private double CurrentSpread
{
get { return (Symbol.Ask - Symbol.Bid) / Symbol.PipSize; }
}
private BollingerBands BB_boll;
private BollingerBands BB_2boll;
private AwesomeOscillator awesomeOscillator;
protected override void OnStart()
{
BB_boll = Indicators.BollingerBands(BB_Source, BB_BandPeriod, BB_std, BB_MAType);
BB_2boll = Indicators.BollingerBands(BB2_Source, BB2_BandPeriod, BB2_std, BB2_MAType);
awesomeOscillator = Indicators.AwesomeOscillator();
}
protected override void OnBar()
{
//indicators();
//ProcessTrades_NEW();
if (CountOfTradesOfType(TradeType.Buy) > 2)
AdjustBuyPositionTakeProfits(CalculateAveragePositionPrice(TradeType.Buy), AverageTakeProfit);
if (CountOfTradesOfType(TradeType.Sell) > 2)
AdjustSellPositionTakeProfits(CalculateAveragePositionPrice(TradeType.Sell), AverageTakeProfit);
if (CurrentSpread <= MaxSpread && !_accountIsOutOfMoney)
ProcessTrades_NEW();
RefreshData();
if (!this.IsBacktesting)
DisplayStatusOnChart();
}
protected override void OnError(Error error)
{
if (error.Code == ErrorCode.NoMoney)
{
_accountIsOutOfMoney = true;
Print("opening stopped because: not enough money");
}
}
// protected override void OnBar()
// {
//}
protected override void OnStop()
{
ChartObjects.RemoveAllObjects();
}
//------------------------------------------------------------------------------------------------------------
private void ProcessTrades_NEW()
{
DateTime expiration = Server.Time.AddDays(1);
var AO = Math.Round(awesomeOscillator.Result.Last(0), 5);
var AO_last = Math.Round(awesomeOscillator.Result.Last(1), 5);
var direction = 0;
if (!this.IsBacktesting)
{
ChartObjects.DrawText("DIR", " " + direction, StaticPosition.TopCenter, Colors.White);
}
var BB2_top = Math.Round(BB_2boll.Top.LastValue, 5);
//BB2 top
var BB_top = Math.Round(BB_boll.Top.LastValue, 5);
//BB top
var mid = Math.Round(BB_boll.Main.LastValue, 5);
//BB mid
var BB_bottom = Math.Round(BB_boll.Bottom.LastValue, 5);
//BB bottom
var BB2_bottom = Math.Round(BB_2boll.Bottom.LastValue, 5);
//BB2 bottom
var TP_CALC = Math.Round((BB2_top - BB2_bottom) / Symbol.PipSize, 1);
if (!this.IsBacktesting)
{
ChartObjects.DrawText("DIR", " " + direction + "|" + TP_CALC, StaticPosition.TopCenter, Colors.White);
}
if (AO < AO_last && AO > 0 && AO_last > 0 && Symbol.Bid > mid)
{
direction = -1;
if (!this.IsBacktesting)
{
ChartObjects.DrawText("DIR", "SELL " + direction + "|" + TP_CALC, StaticPosition.TopCenter, Colors.White);
}
}
if (AO > AO_last && AO < 0 && AO_last < 0 && Symbol.Ask < mid)
{
direction = 1;
if (!this.IsBacktesting)
{
ChartObjects.DrawText("DIR", "BUY " + direction + "|" + TP_CALC, StaticPosition.TopCenter, Colors.White);
}
}
// send buy orders
if (direction == 1)
{
if (Math.Round(Symbol.Ask, Symbol.Digits) < Math.Round(FindLowestPositionPrice(TradeType.Buy) - PipStep * Symbol.PipSize, Symbol.Digits))
{
var calculatedVolume = CalculateVolume(TradeType.Buy);
PlaceStopOrder(TradeType.Buy, Symbol, LimitVolume(calculatedVolume), BB_bottom, Label, 0, TP_CALC, expiration);
PlaceStopOrder(TradeType.Buy, Symbol, LimitVolume(calculatedVolume), mid, Label, 0, TP_CALC, expiration);
PlaceStopOrder(TradeType.Buy, Symbol, LimitVolume(calculatedVolume), BB_top, Label, 0, TP_CALC, expiration);
}
}
// send SELL orders
if (direction == -1)
{
if (Math.Round(Symbol.Bid, Symbol.Digits) > Math.Round(FindHighestPositionPrice(TradeType.Sell) + PipStep * Symbol.PipSize, Symbol.Digits))
{
var calculatedVolume = CalculateVolume(TradeType.Sell);
PlaceStopOrder(TradeType.Sell, Symbol, LimitVolume(calculatedVolume), BB_bottom, Label, 0, TP_CALC, expiration);
PlaceStopOrder(TradeType.Sell, Symbol, LimitVolume(calculatedVolume), mid, Label, 0, TP_CALC, expiration);
PlaceStopOrder(TradeType.Sell, Symbol, LimitVolume(calculatedVolume), BB_top, Label, 0, TP_CALC, expiration);
}
}
if (!this.IsBacktesting)
{
ChartObjects.DrawHorizontalLine("BB2 top", BB2_top, Colors.White, 2, LineStyle.Dots);
//BB2 top
ChartObjects.DrawHorizontalLine("BB top", BB_top, Colors.Yellow, 2, LineStyle.Dots);
//BB top
ChartObjects.DrawHorizontalLine("mid", mid, Colors.White, 2, LineStyle.Dots);
//BB mid
ChartObjects.DrawHorizontalLine("BB bottom", BB_bottom, Colors.Yellow, 2, LineStyle.Dots);
//BB bottom
ChartObjects.DrawHorizontalLine("BB2 bottom", BB2_bottom, Colors.White, 2, LineStyle.Dots);
//BB2 bottom
ChartObjects.DrawText("AO", "AO: " + AO, StaticPosition.TopRight, Colors.White);
ChartObjects.DrawText("AO_last", "\n AAO - last: " + AO_last, StaticPosition.TopRight, Colors.White);
//AO REsults
}
}
//------------------------------------------------------------------------------------------------------------
private void ProcessTrades()
{
if (Buy && CountOfTradesOfType(TradeType.Buy) == 0 && MarketSeries.Close.Last(1) > MarketSeries.Close.Last(2))
{
_openTradeResult = OrderSend(TradeType.Buy, LimitVolume(FirstVolume));
if (_openTradeResult > 0)
_lastBuyTradeTime = MarketSeries.OpenTime.Last(0);
else
Print("First BUY openning error at: ", Symbol.Ask, "Error Type: ", LastResult.Error);
}
if (Sell && CountOfTradesOfType(TradeType.Sell) == 0 && MarketSeries.Close.Last(2) > MarketSeries.Close.Last(1))
{
_openTradeResult = OrderSend(TradeType.Sell, LimitVolume(FirstVolume));
if (_openTradeResult > 0)
_lastSellTradeTime = MarketSeries.OpenTime.Last(0);
else
Print("First SELL opening error at: ", Symbol.Bid, "Error Type: ", LastResult.Error);
}
if (CountOfTradesOfType(TradeType.Buy) > 0)
{
if (Math.Round(Symbol.Ask, Symbol.Digits) < Math.Round(FindLowestPositionPrice(TradeType.Buy) - PipStep * Symbol.PipSize, Symbol.Digits) && _lastBuyTradeTime != MarketSeries.OpenTime.Last(0))
{
var calculatedVolume = CalculateVolume(TradeType.Buy);
_openTradeResult = OrderSend(TradeType.Buy, LimitVolume(calculatedVolume));
if (_openTradeResult > 0)
_lastBuyTradeTime = MarketSeries.OpenTime.Last(0);
else
Print("Next BUY opening error at: ", Symbol.Ask, "Error Type: ", LastResult.Error);
}
}
if (CountOfTradesOfType(TradeType.Sell) > 0)
{
if (Math.Round(Symbol.Bid, Symbol.Digits) > Math.Round(FindHighestPositionPrice(TradeType.Sell) + PipStep * Symbol.PipSize, Symbol.Digits) && _lastSellTradeTime != MarketSeries.OpenTime.Last(0))
{
var calculatedVolume = CalculateVolume(TradeType.Sell);
_openTradeResult = OrderSend(TradeType.Sell, LimitVolume(calculatedVolume));
if (_openTradeResult > 0)
_lastSellTradeTime = MarketSeries.OpenTime.Last(0);
else
Print("Next SELL opening error at: ", Symbol.Bid, "Error Type: ", LastResult.Error);
}
}
}
private int OrderSend(TradeType tradeType, long volumeToUse)
{
var returnResult = 0;
if (volumeToUse > 0)
{
var result = ExecuteMarketOrder(tradeType, Symbol, volumeToUse, Label, 0, 0, 0, "smart_grid");
if (result.IsSuccessful)
{
Print(tradeType, "Opened at: ", result.Position.EntryPrice);
returnResult = 1;
}
else
Print(tradeType, "Openning Error: ", result.Error);
}
else
Print("Volume calculation error: Calculated Volume is: ", volumeToUse);
return returnResult;
}
private void AdjustBuyPositionTakeProfits(double averageBuyPositionPrice, int averageTakeProfit)
{
foreach (var buyPosition in Positions)
{
if (buyPosition.Label == Label && buyPosition.SymbolCode == Symbol.Code)
{
if (buyPosition.TradeType == TradeType.Buy)
{
double? calculatedTakeProfit = Math.Round(averageBuyPositionPrice + averageTakeProfit * Symbol.PipSize, Symbol.Digits);
if (buyPosition.TakeProfit != calculatedTakeProfit)
ModifyPosition(buyPosition, buyPosition.StopLoss, calculatedTakeProfit);
}
}
}
}
private void AdjustSellPositionTakeProfits(double averageSellPositionPrice, int averageTakeProfit)
{
foreach (var sellPosition in Positions)
{
if (sellPosition.Label == Label && sellPosition.SymbolCode == Symbol.Code)
{
if (sellPosition.TradeType == TradeType.Sell)
{
double? calculatedTakeProfit = Math.Round(averageSellPositionPrice - averageTakeProfit * Symbol.PipSize, Symbol.Digits);
if (sellPosition.TakeProfit != calculatedTakeProfit)
ModifyPosition(sellPosition, sellPosition.StopLoss, calculatedTakeProfit);
}
}
}
}
private void DisplayStatusOnChart()
{
if (CountOfTradesOfType(TradeType.Buy) > 1)
{
var y = CalculateAveragePositionPrice(TradeType.Buy);
ChartObjects.DrawHorizontalLine("bpoint", y, Colors.Yellow, 2, LineStyle.Dots);
}
else
ChartObjects.RemoveObject("bpoint");
if (CountOfTradesOfType(TradeType.Sell) > 1)
{
var z = CalculateAveragePositionPrice(TradeType.Sell);
ChartObjects.DrawHorizontalLine("spoint", z, Colors.HotPink, 2, LineStyle.Dots);
}
else
ChartObjects.RemoveObject("spoint");
ChartObjects.DrawText("pan", GenerateStatusText(), StaticPosition.TopLeft, Colors.Tomato);
}
private string GenerateStatusText()
{
var statusText = "";
var buyPositions = "";
var sellPositions = "";
var spread = "";
var buyDistance = "";
var sellDistance = "";
spread = "\nSpread = " + Math.Round(CurrentSpread, 1);
buyPositions = "\nBuy Positions = " + CountOfTradesOfType(TradeType.Buy);
sellPositions = "\nSell Positions = " + CountOfTradesOfType(TradeType.Sell);
if (CountOfTradesOfType(TradeType.Buy) > 0)
{
var averageBuyFromCurrent = Math.Round((CalculateAveragePositionPrice(TradeType.Buy) - Symbol.Bid) / Symbol.PipSize, 1);
buyDistance = "\nBuy Target Away = " + averageBuyFromCurrent;
}
if (CountOfTradesOfType(TradeType.Sell) > 0)
{
var averageSellFromCurrent = Math.Round((Symbol.Ask - CalculateAveragePositionPrice(TradeType.Sell)) / Symbol.PipSize, 1);
sellDistance = "\nSell Target Away = " + averageSellFromCurrent;
}
if (CurrentSpread > MaxSpread)
statusText = "MAX SPREAD EXCEED";
else
statusText = "Smart Grid" + buyPositions + spread + sellPositions + buyDistance + sellDistance;
return (statusText);
}
private int CountOfTradesOfType(TradeType tradeType)
{
var tradeCount = 0;
foreach (var position in Positions)
{
if (position.Label == Label && position.SymbolCode == Symbol.Code)
{
if (position.TradeType == tradeType)
tradeCount++;
}
}
return tradeCount;
}
private double CalculateAveragePositionPrice(TradeType tradeType)
{
double result = 0;
double averagePrice = 0;
long count = 0;
foreach (var position in Positions)
{
if (position.Label == Label && position.SymbolCode == Symbol.Code)
{
if (position.TradeType == tradeType)
{
averagePrice += position.EntryPrice * position.Volume;
count += position.Volume;
}
}
}
if (averagePrice > 0 && count > 0)
result = Math.Round(averagePrice / count, Symbol.Digits);
return result;
}
private double FindLowestPositionPrice(TradeType tradeType)
{
double lowestPrice = 0;
foreach (var position in Positions)
{
if (position.Label == Label && position.SymbolCode == Symbol.Code)
{
if (position.TradeType == tradeType)
{
if (lowestPrice == 0)
{
lowestPrice = position.EntryPrice;
continue;
}
if (position.EntryPrice < lowestPrice)
lowestPrice = position.EntryPrice;
}
}
}
return lowestPrice;
}
private double FindHighestPositionPrice(TradeType tradeType)
{
double highestPrice = 0;
foreach (var position in Positions)
{
if (position.Label == Label && position.SymbolCode == Symbol.Code)
{
if (position.TradeType == tradeType)
{
if (highestPrice == 0)
{
highestPrice = position.EntryPrice;
continue;
}
if (position.EntryPrice > highestPrice)
highestPrice = position.EntryPrice;
}
}
}
return highestPrice;
}
private double FindPriceOfMostRecentPositionId(TradeType tradeType)
{
double price = 0;
var highestPositionId = 0;
foreach (var position in Positions)
{
if (position.Label == Label && position.SymbolCode == Symbol.Code)
{
if (position.TradeType == tradeType)
{
if (highestPositionId == 0 || highestPositionId > position.Id)
{
price = position.EntryPrice;
highestPositionId = position.Id;
}
}
}
}
return price;
}
private long GetMostRecentPositionVolume(TradeType tradeType)
{
long mostRecentVolume = 0;
var highestPositionId = 0;
foreach (var position in Positions)
{
if (position.Label == Label && position.SymbolCode == Symbol.Code)
{
if (position.TradeType == tradeType)
{
if (highestPositionId == 0 || highestPositionId > position.Id)
{
mostRecentVolume = position.Volume;
highestPositionId = position.Id;
}
}
}
}
return mostRecentVolume;
}
private int CountNumberOfPositionsOfType(TradeType tradeType)
{
var mostRecentPrice = FindPriceOfMostRecentPositionId(tradeType);
var numberOfPositionsOfType = 0;
foreach (var position in Positions)
{
if (position.Label == Label && position.SymbolCode == Symbol.Code)
{
if (position.TradeType == tradeType && tradeType == TradeType.Buy)
{
if (Math.Round(position.EntryPrice, Symbol.Digits) <= Math.Round(mostRecentPrice, Symbol.Digits))
numberOfPositionsOfType++;
}
if (position.TradeType == tradeType && tradeType == TradeType.Sell)
{
if (Math.Round(position.EntryPrice, Symbol.Digits) >= Math.Round(mostRecentPrice, Symbol.Digits))
numberOfPositionsOfType++;
}
}
}
return (numberOfPositionsOfType);
}
private long CalculateVolume(TradeType tradeType)
{
var numberOfPositions = CountNumberOfPositionsOfType(tradeType);
var mostRecentVolume = GetMostRecentPositionVolume(tradeType);
var calculatedVolume = Symbol.NormalizeVolume(mostRecentVolume * Math.Pow(VolumeExponent, numberOfPositions));
return (calculatedVolume);
}
private long LimitVolume(long volumeIn)
{
var symbolVolumeMin = Symbol.VolumeMin;
var symbolVolumeMax = Symbol.VolumeMax;
var result = volumeIn;
if (result < symbolVolumeMin)
result = symbolVolumeMin;
if (result > symbolVolumeMax)
result = symbolVolumeMax;
return (result);
}
// - tweaks
private void indicators()
{
var AO = Math.Round(awesomeOscillator.Result.Last(0), 5);
var AO_last = Math.Round(awesomeOscillator.Result.Last(1), 5);
ChartObjects.DrawHorizontalLine("BB2 top", BB_2boll.Top.LastValue, Colors.White, 2, LineStyle.Dots);
//BB2 top
ChartObjects.DrawHorizontalLine("BB top", BB_boll.Top.LastValue, Colors.Yellow, 2, LineStyle.Dots);
//BB top
ChartObjects.DrawHorizontalLine("mid", BB_boll.Main.LastValue, Colors.White, 2, LineStyle.Dots);
//BB mid
ChartObjects.DrawHorizontalLine("BB bottom", BB_boll.Bottom.LastValue, Colors.Yellow, 2, LineStyle.Dots);
//BB bottom
ChartObjects.DrawHorizontalLine("BB2 bottom", BB_2boll.Bottom.LastValue, Colors.White, 2, LineStyle.Dots);
//BB2 bottom
ChartObjects.DrawText("AO", "AO: " + AO, StaticPosition.TopRight, Colors.White);
ChartObjects.DrawText("AO_last", "\n AAO - last: " + AO_last, StaticPosition.TopRight, Colors.White);
//AO REsults
}
}
}
@jumpycalm working on something new right now!
Great piece of work, I have been working with this and running multiple tests of the last few weeks, with mixed yet positive results. One thing we are working on adding, but having a little bit of difficulty with, is a balance dependent initial volume addition to the code, i.e. $1,000 = 1000 lots. Does anyone have any existing money management code that we might be able to use?
Kindest Regards,
Michael Despott
http://www.myfxbook.com/members/transhuman/enigma-capital-xi/5032788
This bot doesn't seem to add TP, only SL. How does that work?
I would like to thank jumpycalm and all the people who collaborated in the development of this excellent cBot.
I've been using it for a few weeks with satisfactory results. I would like to ask if possible to make new transactions open immediately after the old ones are closed.
Thanks in advance for the help and congratulations again.
@jumpycalm thank you very much!
Been away for a While, how is it going? if you want, we can work together in future devs!
Best regards
Bruno Candeias
One way trend Sell - SmartGrid MA LimitStop Sell trend. For Gold sell trend.
What are your ideas for improving the code after testing?
https://ctrader.com/forum/calgo-support/22008
One way trend Sell - SmartGrid MA LimitStop Sell trend. For Gold sell trend.
What are your ideas for improving the code after testing?
https://ctrader.com/forum/calgo-support/22008
//+------------------------------------------------------------------+ //| Smart Grid | //| Copyright 2014, MD SAIF | //| http://www.facebook.com/cls.fx | //+------------------------------------------------------------------+ //-Grid trader cBot based on Bar-Time & Trend. For range market & 15 minute TimeFrame is best. using System; 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 oSGMABuy : Robot { private bool _accountIsOutOfMoney; private int _openTradeResult; private readonly string Label = "SmartPBuy"; private DateTime _lastBuyTradeTime; private DateTime _lastSellTradeTime; [Parameter("Source SMA_AO")] public DataSeries Source_SMA { get; set; } [Parameter("Buy", DefaultValue = true)] public bool Buy { get; set; } [Parameter("Sell", DefaultValue = false)] public bool Sell { get; set; } [Parameter("Pip Step", DefaultValue = 20, MinValue = 1)] public int PipStep { get; set; } [Parameter("First Volume", DefaultValue = 10000, MinValue = 1000, Step = 1000)] public int FirstVolume { get; set; } [Parameter("Volume Exponent", DefaultValue = 1.0, MinValue = 0.1, MaxValue = 5.0)] public double VolumeExponent { get; set; } [Parameter("Max Spread", DefaultValue = 3.0)] public double MaxSpread { get; set; } [Parameter("Average TP", DefaultValue = 100, MinValue = 1)] public int AverageTakeProfit { get; set; } [Parameter("Stop Loss", DefaultValue = 0)] public int StopLoss { get; set; } private double CurrentSpread { get { return (Symbol.Ask - Symbol.Bid) / Symbol.PipSize; } } private SimpleMovingAverage _SMA_slow; private SimpleMovingAverage _SMA_Fast; protected override void OnStart() { } protected override void OnTick() { _SMA_slow = Indicators.SimpleMovingAverage(Source_SMA, 200); _SMA_Fast = Indicators.SimpleMovingAverage(Source_SMA, 50); if (_SMA_slow.Result.LastValue > _SMA_Fast.Result.LastValue && _SMA_slow.Result.LastValue > Symbol.Bid) { Buy = false; Sell = true; ChartObjects.DrawText("Sell", ("Vender"), StaticPosition.TopLeft, Colors.AliceBlue); } if (_SMA_slow.Result.LastValue < _SMA_Fast.Result.LastValue && _SMA_slow.Result.LastValue < Symbol.Ask) { Buy = true; Sell = false; ChartObjects.DrawText("buy", ("Comprar"), StaticPosition.TopLeft, Colors.AliceBlue); } if (CountOfTradesOfType(TradeType.Buy) > 0) AdjustBuyPositionTakeProfits(CalculateAveragePositionPrice(TradeType.Buy), AverageTakeProfit); if (CountOfTradesOfType(TradeType.Sell) > 0) AdjustSellPositionTakeProfits(CalculateAveragePositionPrice(TradeType.Sell), AverageTakeProfit); if (CurrentSpread <= MaxSpread && !_accountIsOutOfMoney) ProcessTrades(); if (!this.IsBacktesting) DisplayStatusOnChart(); } protected override void OnError(Error error) { if (error.Code == ErrorCode.NoMoney) { _accountIsOutOfMoney = true; Print("opening stopped because: not enough money"); } } protected override void OnBar() { RefreshData(); } protected override void OnStop() { ChartObjects.RemoveAllObjects(); } private void ProcessTrades() { if (Buy && CountOfTradesOfType(TradeType.Buy) == 0 && MarketSeries.Close.Last(1) > MarketSeries.Close.Last(2)) { _openTradeResult = OrderSend(TradeType.Buy, LimitVolume(FirstVolume)); if (_openTradeResult > 0) _lastBuyTradeTime = MarketSeries.OpenTime.Last(0); else Print("First BUY openning error at: ", Symbol.Ask, "Error Type: ", LastResult.Error); } if (Sell && CountOfTradesOfType(TradeType.Sell) == 0 && MarketSeries.Close.Last(2) > MarketSeries.Close.Last(1)) { _openTradeResult = OrderSend(TradeType.Sell, LimitVolume(FirstVolume)); if (_openTradeResult > 0) _lastSellTradeTime = MarketSeries.OpenTime.Last(0); else Print("First SELL opening error at: ", Symbol.Bid, "Error Type: ", LastResult.Error); } if (CountOfTradesOfType(TradeType.Buy) > 0) { if (Math.Round(Symbol.Ask, Symbol.Digits) < Math.Round(FindLowestPositionPrice(TradeType.Buy) - PipStep * Symbol.PipSize, Symbol.Digits) && _lastBuyTradeTime != MarketSeries.OpenTime.Last(0)) { var calculatedVolume = CalculateVolume(TradeType.Buy); _openTradeResult = OrderSend(TradeType.Buy, LimitVolume(calculatedVolume)); if (_openTradeResult > 0) _lastBuyTradeTime = MarketSeries.OpenTime.Last(0); else Print("Next BUY opening error at: ", Symbol.Ask, "Error Type: ", LastResult.Error); } } if (CountOfTradesOfType(TradeType.Sell) > 0) { if (Math.Round(Symbol.Bid, Symbol.Digits) > Math.Round(FindHighestPositionPrice(TradeType.Sell) + PipStep * Symbol.PipSize, Symbol.Digits) && _lastSellTradeTime != MarketSeries.OpenTime.Last(0)) { var calculatedVolume = CalculateVolume(TradeType.Sell); _openTradeResult = OrderSend(TradeType.Sell, LimitVolume(calculatedVolume)); if (_openTradeResult > 0) _lastSellTradeTime = MarketSeries.OpenTime.Last(0); else Print("Next SELL opening error at: ", Symbol.Bid, "Error Type: ", LastResult.Error); } } } private int OrderSend(TradeType tradeType, long volumeToUse) { var returnResult = 0; if (volumeToUse > 0) { var result = ExecuteMarketOrder(tradeType, Symbol, volumeToUse, Label, StopLoss, 0, 0, "smart_grid"); if (result.IsSuccessful) { Print(tradeType, "Opened at: ", result.Position.EntryPrice, result.Position.StopLoss); returnResult = 1; } else Print(tradeType, "Openning Error: ", result.Error); } else Print("Volume calculation error: Calculated Volume is: ", volumeToUse); return returnResult; } private void AdjustBuyPositionTakeProfits(double averageBuyPositionPrice, int averageTakeProfit) { foreach (var buyPosition in Positions) { if (buyPosition.Label == Label && buyPosition.SymbolCode == Symbol.Code) { if (buyPosition.TradeType == TradeType.Buy) { double? calculatedTakeProfit = Math.Round(averageBuyPositionPrice + averageTakeProfit * Symbol.PipSize, Symbol.Digits); if (buyPosition.TakeProfit != calculatedTakeProfit) ModifyPosition(buyPosition, buyPosition.StopLoss, calculatedTakeProfit); } } } } private void AdjustSellPositionTakeProfits(double averageSellPositionPrice, int averageTakeProfit) { foreach (var sellPosition in Positions) { if (sellPosition.Label == Label && sellPosition.SymbolCode == Symbol.Code) { if (sellPosition.TradeType == TradeType.Sell) { double? calculatedTakeProfit = Math.Round(averageSellPositionPrice - averageTakeProfit * Symbol.PipSize, Symbol.Digits); if (sellPosition.TakeProfit != calculatedTakeProfit) ModifyPosition(sellPosition, sellPosition.StopLoss, calculatedTakeProfit); } } } } private void DisplayStatusOnChart() { if (CountOfTradesOfType(TradeType.Buy) > 1) { var y = CalculateAveragePositionPrice(TradeType.Buy); ChartObjects.DrawHorizontalLine("bpoint", y, Colors.Yellow, 2, LineStyle.Dots); } else ChartObjects.RemoveObject("bpoint"); if (CountOfTradesOfType(TradeType.Sell) > 1) { var z = CalculateAveragePositionPrice(TradeType.Sell); ChartObjects.DrawHorizontalLine("spoint", z, Colors.HotPink, 2, LineStyle.Dots); } else ChartObjects.RemoveObject("spoint"); ChartObjects.DrawText("pan", GenerateStatusText(), StaticPosition.TopLeft, Colors.Tomato); } private string GenerateStatusText() { var statusText = ""; var buyPositions = ""; var sellPositions = ""; var spread = ""; var buyDistance = ""; var sellDistance = ""; spread = "\nSpread = " + Math.Round(CurrentSpread, 1); buyPositions = "\nBuy Positions = " + CountOfTradesOfType(TradeType.Buy); sellPositions = "\nSell Positions = " + CountOfTradesOfType(TradeType.Sell); if (CountOfTradesOfType(TradeType.Buy) > 0) { var averageBuyFromCurrent = Math.Round((CalculateAveragePositionPrice(TradeType.Buy) - Symbol.Bid) / Symbol.PipSize, 1); buyDistance = "\nBuy Target Away = " + averageBuyFromCurrent; } if (CountOfTradesOfType(TradeType.Sell) > 0) { var averageSellFromCurrent = Math.Round((Symbol.Ask - CalculateAveragePositionPrice(TradeType.Sell)) / Symbol.PipSize, 1); sellDistance = "\nSell Target Away = " + averageSellFromCurrent; } if (CurrentSpread > MaxSpread) statusText = "MAX SPREAD EXCEED"; else statusText = "Smart Grid" + buyPositions + spread + sellPositions + buyDistance + sellDistance; return (statusText); } private int CountOfTradesOfType(TradeType tradeType) { var tradeCount = 0; foreach (var position in Positions) { if (position.Label == Label && position.SymbolCode == Symbol.Code) { if (position.TradeType == tradeType) tradeCount++; } } return tradeCount; } private double CalculateAveragePositionPrice(TradeType tradeType) { double result = 0; double averagePrice = 0; long count = 0; foreach (var position in Positions) { if (position.Label == Label && position.SymbolCode == Symbol.Code) { if (position.TradeType == tradeType) { averagePrice += position.EntryPrice * position.Volume; count += position.Volume; } } } if (averagePrice > 0 && count > 0) result = Math.Round(averagePrice / count, Symbol.Digits); return result; } private double FindLowestPositionPrice(TradeType tradeType) { double lowestPrice = 0; foreach (var position in Positions) { if (position.Label == Label && position.SymbolCode == Symbol.Code) { if (position.TradeType == tradeType) { if (lowestPrice == 0) { lowestPrice = position.EntryPrice; continue; } if (position.EntryPrice < lowestPrice) lowestPrice = position.EntryPrice; } } } return lowestPrice; } private double FindHighestPositionPrice(TradeType tradeType) { double highestPrice = 0; foreach (var position in Positions) { if (position.Label == Label && position.SymbolCode == Symbol.Code) { if (position.TradeType == tradeType) { if (highestPrice == 0) { highestPrice = position.EntryPrice; continue; } if (position.EntryPrice > highestPrice) highestPrice = position.EntryPrice; } } } return highestPrice; } private double FindPriceOfMostRecentPositionId(TradeType tradeType) { double price = 0; var highestPositionId = 0; foreach (var position in Positions) { if (position.Label == Label && position.SymbolCode == Symbol.Code) { if (position.TradeType == tradeType) { if (highestPositionId == 0 || highestPositionId > position.Id) { price = position.EntryPrice; highestPositionId = position.Id; } } } } return price; } private long GetMostRecentPositionVolume(TradeType tradeType) { long mostRecentVolume = 0; var highestPositionId = 0; foreach (var position in Positions) { if (position.Label == Label && position.SymbolCode == Symbol.Code) { if (position.TradeType == tradeType) { if (highestPositionId == 0 || highestPositionId > position.Id) { mostRecentVolume = position.Volume; highestPositionId = position.Id; } } } } return mostRecentVolume; } private int CountNumberOfPositionsOfType(TradeType tradeType) { var mostRecentPrice = FindPriceOfMostRecentPositionId(tradeType); var numberOfPositionsOfType = 0; foreach (var position in Positions) { if (position.Label == Label && position.SymbolCode == Symbol.Code) { if (position.TradeType == tradeType && tradeType == TradeType.Buy) { if (Math.Round(position.EntryPrice, Symbol.Digits) <= Math.Round(mostRecentPrice, Symbol.Digits)) numberOfPositionsOfType++; } if (position.TradeType == tradeType && tradeType == TradeType.Sell) { if (Math.Round(position.EntryPrice, Symbol.Digits) >= Math.Round(mostRecentPrice, Symbol.Digits)) numberOfPositionsOfType++; } } } return (numberOfPositionsOfType); } private long CalculateVolume(TradeType tradeType) { var numberOfPositions = CountNumberOfPositionsOfType(tradeType); var mostRecentVolume = GetMostRecentPositionVolume(tradeType); var calculatedVolume = Symbol.NormalizeVolume(mostRecentVolume * Math.Pow(VolumeExponent, numberOfPositions)); return (calculatedVolume); } private long LimitVolume(long volumeIn) { var symbolVolumeMin = Symbol.VolumeMin; var symbolVolumeMax = Symbol.VolumeMax; var result = volumeIn; if (result < symbolVolumeMin) result = symbolVolumeMin; if (result > symbolVolumeMax) result = symbolVolumeMax; return (result); } } }
[Parameter("Sell", DefaultValue = false)] public bool Sell { get; set; }
Hi.
V4 with SMA, but:
1. What wrrong ?
[Parameter("Sell", DefaultValue = false)] public bool Sell { get; set; }
Bot now open buy and sell ?!
sell is false ?!
defaultvalue is ignore ?
How fix ?
2. How put parametrs ?
[Parameter("Maximum open buy position?", Group = "Basic Setup", DefaultValue = 5, MinValue = 0)]
public int MaxOpenBuy { get; set; }
[Parameter("Maximum open Sell position?", Group = "Basic Setup", DefaultValue = 5, MinValue = 0)]
public int MaxOpenSell { get; set; }
More forum:
https://ctrader.com/forum/calgo-support/16641?page=1#7
hello sir, how to add indicator options in determining the start of execution?
for example, I want to open an order when the SMA indicator shows bullish
Hi Bave,
Post your recommendation in this post or send me an email. I am working on a new bot based on similar concept as this one.
Good Job, looks very interesting, I am working on testing it, I will need to understand the reacl mechanism behind how it works now.
I am very much into this Cbot as I have been using SmartGrid2 for over 6 months on my life account and it has given great results ( doubled my investment in 6 months), even I have done some on my own brain storming and study of how the bot can be upgraded for better results and better optimization based on different users and investment amounts.
I am wondering if you would be open to discuss the upgrade I have worked on, I have worked them out in excel sheets since I am not a programmer.
Bave
Thank you jamestryke, I believe what you are trying to achieve is called reverse Martingale, I actually tried your method before I posted the code to ctrader.com, but that method did not help on reducing drawdown, on the contrary, it introduced more drawdown. I already have a more advanced version compare to this one and I will post it on ctrader.com as soon as cTrader 3.5 is rolled out on majority brokers. As of this time, I tried many brokers, only Trader’s Way upgraded to 3.5. So, the majority brokers will roll out 3.5 very soon. My guess is the next couple of weeks.
Very good work there. Been testing for a few days and can't wait for 3.5 to come live. Is it possible to code something along the lines of changing martingale direction, so instead of buy/buy/buy/buy every 20pips, you would buy/sell/buy/sell every 20pips or something like that?
For example, buy 0.01 lot @1.1130 > goes down to 1.1110 - instead of another buy 0.02 lot @1.1110, the bot sells 0.02 lot @1.1110. This may hopefully reduce the drawdown if the market goes into a trending market.
Also, for those saying error or the bot isn't working, this cbot is only working on Ctrader 3.5 which is currently in beta, just download it from ctrader (make sure it's the beta version). You (probably) would not get this from your broker as it's not live yet.
this bot is not working :(
65 Errors ?
very good cbot thank you very much
i can see that there is some bugs when backtesting and on live one of them is average tp
it would be nice if someone can update it
thanks again