Category Other  Published on 22/06/2019

Smart Grid V3

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's avatar
jumpycalm

Joined on 28.03.2019

  • Distribution: Free
  • Language: C#
  • Trading platform: cTrader Automate
  • File name: Smart Grid V3.algo
  • Rating: 5
  • Installs: 4904
Comments
Log in to add a comment.
fazle.subhan1994's avatar
fazle.subhan1994 · 10 months ago

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 

RI

Guys, any setting can share please?

UM
umadrat2012 · 2 years ago

Can someone please help me, how do I fix the sell only problem

CO
CoreTradingHouse · 3 years ago

Thank you! :) 

CT
ctraderbeta · 3 years ago

@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 )

JU
JuicyJ · 3 years ago

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

TG
tgjobscv · 3 years ago

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 ?

TG
tgjobscv · 3 years ago

How cTrader demo to live ctrader, mt4/mt5 Trade Copier ?

MR
Mr4x · 4 years ago

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

MR
Mr4x · 4 years ago

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

CO
CoreTradingHouse · 4 years ago

@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

        }

    }
}

 

CO
CoreTradingHouse · 4 years ago

@jumpycalm working on something new right now!

 

 

MI
michaeldespott · 4 years ago

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

AM
amplificator · 4 years ago

This bot doesn't seem to add TP, only SL. How does that work?

CT
ctid1642639 · 4 years ago

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.

CO
CoreTradingHouse · 4 years ago

@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

TG
tgjobscv · 4 years ago

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

TG
tgjobscv · 4 years ago

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

TG
tgjobscv · 4 years ago

//+------------------------------------------------------------------+ //| 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

BI
bitcoinspeak · 4 years ago

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

jumpycalm's avatar
jumpycalm · 4 years ago

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.

BA
bave.rowe · 4 years ago

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 

jumpycalm's avatar
jumpycalm · 5 years ago

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.

JA
jamestryke · 5 years ago

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.

KubilayBoz's avatar
KubilayBoz · 5 years ago

this bot is not working :(

TG
tgjobscv · 5 years ago

65 Errors ?