Smart Grid free

by SaifBD in category Range at 01/07/2015
Description

Smart Grid cBot will open first position based on trend. Next positions will be added using 'PipStep' parameter. Dynamic Volume Exponent & 1 trade per 1 bar to minimize draw-down risk. Follow trend direction manually & open Buy Sell your choice. 

13270 downloads
How to install
Warning! Executing the following cBot may result in loss of funds. Use it at your own risk.
Notification Publishing copyrighted material is strictly prohibited. If you believe there is copyrighted material in this section you may use the Copyright Infringement Notification form to submit a claim.
Formula / Source Code
Language: C#
Trading Platform: cAlgo
//+------------------------------------------------------------------+
//|                                                  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 System.Linq;
using cAlgo.API;

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class SmartGrid : Robot
    {
        [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 AverageTP { get; set; }

        private string Label = "cls";
        private Position position;
        private DateTime tc_31;
        private DateTime tc_32;
        private int gi_21;
        private double sp_d;
        private bool is_12 = true;
        private bool cStop = false;
        protected override void OnStart()
        {
        }
        protected override void OnTick()
        {
            sp_d = (Symbol.Ask - Symbol.Bid) / Symbol.PipSize;
            if (o_tm(TradeType.Buy) > 0)
                f0_86(pnt_12(TradeType.Buy), AverageTP);
            if (o_tm(TradeType.Sell) > 0)
                f0_88(pnt_12(TradeType.Sell), AverageTP);
            if (MaxSpread >= sp_d && !cStop)
                Open_24();
            RCN();
        }
        protected override void OnError(Error error)
        {
            if (error.Code == ErrorCode.NoMoney)
            {
                cStop = true;
                Print("openning stopped because: not enough money");
            }
        }
        protected override void OnBar()
        {
            RefreshData();
        }
        protected override void OnStop()
        {
            ChartObjects.RemoveAllObjects();
        }
        private void Open_24()
        {
            if (is_12)
            {
                if (Buy && o_tm(TradeType.Buy) == 0 && MarketSeries.Close.Last(1) > MarketSeries.Close.Last(2))
                {
                    gi_21 = OrderSend(TradeType.Buy, fer(FirstVolume, 0));
                    if (gi_21 > 0)
                        tc_31 = MarketSeries.OpenTime.Last(0);
                    else
                        Print("First BUY openning error at: ", Symbol.Ask, "Error Type: ", LastResult.Error);
                }
                if (Sell && o_tm(TradeType.Sell) == 0 && MarketSeries.Close.Last(2) > MarketSeries.Close.Last(1))
                {
                    gi_21 = OrderSend(TradeType.Sell, fer(FirstVolume, 0));
                    if (gi_21 > 0)
                        tc_32 = MarketSeries.OpenTime.Last(0);
                    else
                        Print("First SELL openning error at: ", Symbol.Bid, "Error Type: ", LastResult.Error);
                }
            }
            N_28();
        }
        private void N_28()
        {
            if (o_tm(TradeType.Buy) > 0)
            {
                if (Math.Round(Symbol.Ask, Symbol.Digits) < Math.Round(D_TD(TradeType.Buy) - PipStep * Symbol.PipSize, Symbol.Digits) && tc_31 != MarketSeries.OpenTime.Last(0))
                {
                    long gl_57 = n_lt(TradeType.Buy);
                    gi_21 = OrderSend(TradeType.Buy, fer(gl_57, 2));
                    if (gi_21 > 0)
                        tc_31 = MarketSeries.OpenTime.Last(0);
                    else
                        Print("Next BUY openning error at: ", Symbol.Ask, "Error Type: ", LastResult.Error);
                }
            }
            if (o_tm(TradeType.Sell) > 0)
            {
                if (Math.Round(Symbol.Bid, Symbol.Digits) > Math.Round(U_TD(TradeType.Sell) + PipStep * Symbol.PipSize, Symbol.Digits))
                {
                    long gl_59 = n_lt(TradeType.Sell);
                    gi_21 = OrderSend(TradeType.Sell, fer(gl_59, 2));
                    if (gi_21 > 0)
                        tc_32 = MarketSeries.OpenTime.Last(0);
                    else
                        Print("Next SELL openning error at: ", Symbol.Bid, "Error Type: ", LastResult.Error);
                }
            }
        }
        private int OrderSend(TradeType TrdTp, long iVol)
        {
            int cd_8 = 0;
            if (iVol > 0)
            {
                TradeResult result = ExecuteMarketOrder(TrdTp, Symbol, iVol, Label, 0, 0, 0, "smart_grid");

                if (result.IsSuccessful)
                {
                    Print(TrdTp, "Opened at: ", result.Position.EntryPrice);
                    cd_8 = 1;
                }
                else
                    Print(TrdTp, "Openning Error: ", result.Error);
            }
            else
                Print("Volume calculation error: Calculated Volume is: ", iVol);
            return cd_8;
        }
        private void f0_86(double ai_4, int ad_8)
        {
            foreach (var position in Positions)
            {
                if (position.Label == Label && position.SymbolCode == Symbol.Code)
                {
                    if (position.TradeType == TradeType.Buy)
                    {
                        double? li_16 = Math.Round(ai_4 + ad_8 * Symbol.PipSize, Symbol.Digits);
                        if (position.TakeProfit != li_16)
                            ModifyPosition(position, position.StopLoss, li_16);
                    }
                }
            }
        }
        private void f0_88(double ai_4, int ad_8)
        {
            foreach (var position in Positions)
            {
                if (position.Label == Label && position.SymbolCode == Symbol.Code)
                {
                    if (position.TradeType == TradeType.Sell)
                    {
                        double? li_16 = Math.Round(ai_4 - ad_8 * Symbol.PipSize, Symbol.Digits);
                        if (position.TakeProfit != li_16)
                            ModifyPosition(position, position.StopLoss, li_16);
                    }
                }
            }
        }
        private void RCN()
        {
            if (o_tm(TradeType.Buy) > 1)
            {
                double y = pnt_12(TradeType.Buy);
                ChartObjects.DrawHorizontalLine("bpoint", y, Colors.Yellow, 2, LineStyle.Dots);
            }
            else
                ChartObjects.RemoveObject("bpoint");
            if (o_tm(TradeType.Sell) > 1)
            {
                double z = pnt_12(TradeType.Sell);
                ChartObjects.DrawHorizontalLine("spoint", z, Colors.HotPink, 2, LineStyle.Dots);
            }
            else
                ChartObjects.RemoveObject("spoint");
            ChartObjects.DrawText("pan", A_cmt_calc(), StaticPosition.TopLeft, Colors.Tomato);
        }
        private string A_cmt_calc()
        {
            string gc_78 = "";
            string wn_7 = "";
            string wn_8 = "";
            string sp_4 = "";
            string ppb = "";
            string lpb = "";
            string nb_6 = "";
            double dn_7 = 0;
            double dn_9 = 0;
            sp_4 = "\nSpread = " + Math.Round(sp_d, 1);
            nb_6 = "\nwww.facebook.com/cls.fx\n";
            if (dn_7 > 0)
                wn_7 = "\nBuy Positions = " + o_tm(TradeType.Buy);
            if (dn_9 > 0)
                wn_8 = "\nSell Positions = " + o_tm(TradeType.Sell);
            if (o_tm(TradeType.Buy) > 0)
            {
                double igl = Math.Round((pnt_12(TradeType.Buy) - Symbol.Bid) / Symbol.PipSize, 1);
                ppb = "\nBuy Target Away = " + igl;
            }
            if (o_tm(TradeType.Sell) > 0)
            {
                double osl = Math.Round((Symbol.Ask - pnt_12(TradeType.Sell)) / Symbol.PipSize, 1);
                lpb = "\nSell Target Away = " + osl;
            }
            if (sp_d > MaxSpread)
                gc_78 = "MAX SPREAD EXCEED";
            else
                gc_78 = "Smart Grid" + nb_6 + wn_7 + sp_4 + wn_8 + ppb + lpb;
            return (gc_78);
        }
        private int cnt_16()
        {
            int ASide = 0;

            for (int i = Positions.Count - 1; i >= 0; i--)
            {
                position = Positions[i];
                if (position.Label == Label && position.SymbolCode == Symbol.Code)
                    ASide++;
            }
            return ASide;
        }
        private int o_tm(TradeType TrdTp)
        {
            int TSide = 0;

            for (int i = Positions.Count - 1; i >= 0; i--)
            {
                position = Positions[i];
                if (position.Label == Label && position.SymbolCode == Symbol.Code)
                {
                    if (position.TradeType == TrdTp)
                        TSide++;
                }
            }
            return TSide;
        }
        private double pnt_12(TradeType TrdTp)
        {
            double Result = 0;
            double AveragePrice = 0;
            long Count = 0;

            for (int i = Positions.Count - 1; i >= 0; i--)
            {
                position = Positions[i];
                if (position.Label == Label && position.SymbolCode == Symbol.Code)
                {
                    if (position.TradeType == TrdTp)
                    {
                        AveragePrice += position.EntryPrice * position.Volume;
                        Count += position.Volume;
                    }
                }
            }
            if (AveragePrice > 0 && Count > 0)
                Result = Math.Round(AveragePrice / Count, Symbol.Digits);
            return Result;
        }
        private double D_TD(TradeType TrdTp)
        {
            double D_TD = 0;

            for (int i = Positions.Count - 1; i >= 0; i--)
            {
                position = Positions[i];
                if (position.Label == Label && position.SymbolCode == Symbol.Code)
                {
                    if (position.TradeType == TrdTp)
                    {
                        if (D_TD == 0)
                        {
                            D_TD = position.EntryPrice;
                            continue;
                        }
                        if (position.EntryPrice < D_TD)
                            D_TD = position.EntryPrice;
                    }
                }
            }
            return D_TD;
        }
        private double U_TD(TradeType TrdTp)
        {
            double U_TD = 0;

            for (int i = Positions.Count - 1; i >= 0; i--)
            {
                position = Positions[i];
                if (position.Label == Label && position.SymbolCode == Symbol.Code)
                {
                    if (position.TradeType == TrdTp)
                    {
                        if (U_TD == 0)
                        {
                            U_TD = position.EntryPrice;
                            continue;
                        }
                        if (position.EntryPrice > U_TD)
                            U_TD = position.EntryPrice;
                    }
                }
            }
            return U_TD;
        }
        private double f_tk(TradeType TrdTp)
        {
            double prc_4 = 0;
            int tk_4 = 0;
            for (int i = Positions.Count - 1; i >= 0; i--)
            {
                position = Positions[i];
                if (position.Label == Label && position.SymbolCode == Symbol.Code)
                {
                    if (position.TradeType == TrdTp)
                    {
                        if (tk_4 == 0 || tk_4 > position.Id)
                        {
                            prc_4 = position.EntryPrice;
                            tk_4 = position.Id;
                        }
                    }
                }
            }
            return prc_4;
        }
        private long lt_8(TradeType TrdTp)
        {
            long lot_4 = 0;
            int tk_4 = 0;
            for (int i = Positions.Count - 1; i >= 0; i--)
            {
                position = Positions[i];
                if (position.Label == Label && position.SymbolCode == Symbol.Code)
                {
                    if (position.TradeType == TrdTp)
                    {
                        if (tk_4 == 0 || tk_4 > position.Id)
                        {
                            lot_4 = position.Volume;
                            tk_4 = position.Id;
                        }
                    }
                }
            }
            return lot_4;
        }
        private long clt(TradeType TrdTp)
        {
            long Result = 0;
            for (int i = Positions.Count - 1; i >= 0; i--)
            {
                position = Positions[i];
                if (position.Label == Label && position.SymbolCode == Symbol.Code)
                {
                    if (position.TradeType == TrdTp)
                        Result += position.Volume;
                }
            }
            return Result;
        }
        private int Grd_Ex(TradeType ai_0, TradeType ci_0)
        {
            double prc_4 = f_tk(ci_0);
            int tk_4 = 0;
            for (int i = Positions.Count - 1; i >= 0; i--)
            {
                position = Positions[i];
                if (position.Label == Label && position.SymbolCode == Symbol.Code)
                {
                    if (position.TradeType == ai_0 && ai_0 == TradeType.Buy)
                    {
                        if (Math.Round(position.EntryPrice, Symbol.Digits) <= Math.Round(prc_4, Symbol.Digits))
                            tk_4++;
                    }
                    if (position.TradeType == ai_0 && ai_0 == TradeType.Sell)
                    {
                        if (Math.Round(position.EntryPrice, Symbol.Digits) >= Math.Round(prc_4, Symbol.Digits))
                            tk_4++;
                    }
                }
            }
            return (tk_4);
        }
        private long n_lt(TradeType ca_8)
        {
            int ic_g = Grd_Ex(ca_8, ca_8);
            long gi_c = lt_8(ca_8);
            long ld_4 = Symbol.NormalizeVolume(gi_c * Math.Pow(VolumeExponent, ic_g));
            return (ld_4);
        }
        private long fer(long ic_9, int bk_4)
        {
            long ga_i = Symbol.VolumeMin;
            long gd_i = Symbol.VolumeStep;
            long dc_i = Symbol.VolumeMax;
            long ic_8 = ic_9;
            if (ic_8 < ga_i)
                ic_8 = ga_i;
            if (ic_8 > dc_i)
                ic_8 = dc_i;
            return (ic_8);
        }
    }
}


Comments

aimerdoux - July 05, 2015 @ 21:34

where did you learn all of this?

aimerdoux - July 05, 2015 @ 21:42

this is by far the best bot i ever seen 

spike.bhv - July 17, 2015 @ 09:41

One Word:  Amazing ;)

I've added some Features:

Volume Maximum (if Volume Exponent >1)

PipStep Maximum (if Volume Maximum ist reached, alternative set Buy / Sell flag = false)

Stop Loss ( not importend, but cTrader will note when Stoploss not set)

Advanced Stopp Loss.  I set TP a lttle bit higher then AverageTP. When current price  reached  TP-1 Pip (for Example) New StopLoss will be set TP - 3 (for Example), wich is = Average TP. The TP will increased by TrailingStep. So if the Curent Price will grow up, the (Trailing) Stop Loss will grow up too.

 

Sorry for my bad english, I'm German ;)

aimerdoux - July 21, 2015 @ 01:45

hi spike do u use any social network like facebook or linkedIn Id like to talk to u

spike.bhv - July 21, 2015 @ 16:08

search for Mi Be     in Bremerhaven / Germany

spike.bhv - July 21, 2015 @ 16:11

on Facebook ;)

aimerdoux - July 21, 2015 @ 18:23

i dont find you my facebook is: https://www.facebook.com/omar.hernandez.167189

aimerdoux - July 21, 2015 @ 19:00

 in the method private long fer(long ic_9, int bk_4) he never actuallyuses this variavle what is funny long gd_i = Symbol.VolumeStep;

spike.bhv - July 21, 2015 @ 19:38

I send you a friend request.

The Method is to validate the tradeble Volume (min, max, and steps) of this symbol.

f.e. if exist (i don't know that) a maximum tradevolume for a symbol, this Method set the maximum if you want a higher volume.

Hope you understand what i mean. My English is not very good...

SaifBD - July 24, 2015 @ 19:05

@spike.bhv

I added that in my cBot. see

            long dc_i = Symbol.VolumeMax;

            if (ic_8 > dc_i)

                ic_8 = dc_i;

megamemo - July 28, 2015 @ 05:16

 SaifBD is a pleasure i have a great strategie that worth the soot programming it are you interested my mail

burnigonhell@gmail.com

zilva - July 31, 2015 @ 10:20

@SaifBD This is IMO the Max tradable Volume of a Symbol.

I mean to set myself the max i want to risk.

P.S. spike.bhv is my old ID.

SaifBD - July 31, 2015 @ 19:59

        @zilva try this.

[Parameter("Max Volume", DefaultValue = 10000000, Step = 1000)]
        public int MaxVolume { get; set; }

if (ic_8 > MaxVolume)
                ic_8 = MaxVolume;

9469cd97 - July 31, 2015 @ 23:34

@SaifBD

Sorry to bother you, but I have an issue need your help.

I using AUDCAD pair to run optimization and parameters shows both "Buy-Yes" and "Sell-Yes", then I run it in Live account with only "Buy-Yes" setting and cAlgo still open Sell position, is that normal? 

Thanks a lot.

9469cd97 - July 31, 2015 @ 23:45

@SaifBD

Make it more clear.  I open two "AUDCAD" pair cBots, one with only "Buy" option and another with only "Sell" option then start both cBots, in the middle of time, I stopped one with "Sell" option and let another keep running, from this moment on, cBot should only open Buy position is that correct? somehow it still open Sell position and that really confuse me.

Foss - August 02, 2015 @ 06:09

This looks good but it does not seem to have a stop loss by default. I've added:

private double pipSize;
 private double stopLoss = 3.6;
 private double sL;

and then added this to the order method:

if (TrdTp == TradeType.Sell)
            {

                sL = Symbol.Ask + stopLoss * pipSize;
            }

            else if (TrdTp == TradeType.Buy)
            {

                sL = Symbol.Bid - stopLoss * pipSize;

            }

            int cd_8 = 0;
            if (iVol > 0)
            {
                TradeResult result = ExecuteMarketOrder(TrdTp, Symbol, iVol, Label, sL, 0, 0, "smart_grid");

Is this ok or is there a better way to do this?

 

 

SaifBD - August 03, 2015 @ 08:27

@9469cd97

It's not normal. cBot will not open sell position if "Sell" is false. never!

RelaX - August 03, 2015 @ 14:57

@SaifBD

Hello,

SaifBD is it possible to add Step Volume paramether to your cBot? So if I set First Volume to 1000 and Step Volume to 1000 then cBot should open 1k then 2k then 3k then 4k then 5k and so on...if I set First Volume to 2000 and Step Volume to 2000 then cBot should open 2k then 4k then 6k then 8k and so on...is that possibile?  I want cBot to add value seted in Step Volume paramether when opening next position instead of using Volume Exponent paramether. Is that possibile?

For now there is only Volume Exponent paramether which multiplies previous volume when I set it more then 1.0

Razor - August 04, 2015 @ 13:34

Could you add a step exponent multiplier so as to increase the pip step with each position that is added?

RelaX - August 05, 2015 @ 13:58

Does anyone know how to set new parameter in that cBot to be able to open (in case of volume traded) new positions every 1k or 2k or 3k...when cBot is increasing sell or buy side? Let's say that I would like to start from 1k and then have next position 2k and 3k and 4k and so on, when I set step volume to 1k. So newly created position is always 1k volume higher then previous one. Next example - when I set first volume and step volume to 2k I would like to have 2k then 4k, 6k, 8k, 10k and so on. Next buy or sell position should be always 2k volume higher then previous one in that example. All other functionality of cBot should stay as it is now. No other changes. Can anyone help with that?

vitalikifel - August 07, 2015 @ 12:30

Nice Robot. Works in backtesting pretty good but i really miss a stopp loss. SafiBD can you please add this feature to the cBot?

3012658 - August 09, 2015 @ 20:42

hello SafiiBD,

is it possible to build a filter in this cBot only long  -only short and long and short.
plus a stop los possibility.

zilva - August 11, 2015 @ 10:13

@ Relax

Set New Parameter: 

[Parameter("Volume Step", DefaultValue = 1000, MinValue = 1000, Step = 1000)]
public int VolumeStep { get; set; }

 

And replace the Method n_lt(TradeType ca_8) with This:

private long n_lt(TradeType ca_8)
        {
            int ic_g = Grd_Ex(ca_8, ca_8);
            long gi_c = lt_8(ca_8);
            long ld_4 = Symbol.NormalizeVolume(gi_c + VolumeStep);
            return (ld_4);
        }

I did not tested this, but seems to be work.

Razor - August 11, 2015 @ 17:20

Is there anyone that could code a multiplier to the pip step parameter? I would appreciate this with cash thankyou.

zilva - August 12, 2015 @ 11:41

@ Conno123.

 

Okay, just found the Error.

replace this:

long ld_4 = Symbol.NormalizeVolume(gi_c + VolumeStep);

with this:

long ld_4 = Symbol.NormalizeVolume(gi_c + (VolumeStep * ic_g));

 

greetz

zilva

RelaX - August 18, 2015 @ 11:02

@ Zilva

Thank you very much for ammendments in code. After adding new parameter and changes in Method n_lt(TradeType ca_8) cBOT is working like I wanted.

There is one more case to figure out in cBOT. I notice the same what @Cannon123 wrote that cBOT is executing more then 1 trade per bar. In cBOT description there is written that cBOT contains code which should limit drawdown by adding only one trade per bar. It is not working correctly. I also check that with oryginal code and the same happen. 

Even if I am using 1m timeframe and PipStep =10 and there is big move on the market during market data release cBOT is opening more then 1 position in 1 minute bar if the price movement is exceeding PipStep paramether during 1m candle drawing. I would like to make changes which will limit that risk and create new order at the beggining of next 1m bar instead of opening somewhere in the middle of bar. So if the price movement is higher then PipStep paramether during 1m candle drawing cBOT should open position at the begining of next bar. I think that cBOT conditions should be validate on bar instead of on tick but when newly created position is added, TP modifications should be created immediately on tick.

Is that possibile? Can you assist with such changes as well?  

Cheers,

RelaX

marek_b - August 20, 2015 @ 19:49

great JOB!

zilva - August 21, 2015 @ 15:48

Yes, in the description is written one trade per bar.

For me is it still not necessary to open only one trade per bar, so i don't search for the Code to do that.

 

By the way, nice to help you ;)

RelaX - August 21, 2015 @ 17:02

OK, thank you for your point of view. I will double test that on demo acc.

Just one more question...Is it possibile to change code to check conditions by set timeframe instead of checking by each tick? I mean that when I am using 1m timeframe I want code to be checked after each 1m candle. If cBot conditions are met at the beginning of 1m candle (pipstep distance and maxspread) ,then he should open next position, if not then wait till next 1m candle and check again...Is such change possible? 

Thank you once more,

RelaX

8051361 - August 25, 2015 @ 15:09

@SaifBD

One word Awesome!

I am new to cBots and dont have a programmers brain :(. Wondering if you could explain the Take Profit calculation I am not able to figure out the logic.

If its not too much trouble.

Thanks.

ColossusFX - August 27, 2015 @ 15:09

Has anyone got a working stop loss feature?

Could they possibly share the code?

I have built with a stoploss code, but it does not actually set the stop loss.

Thanks

zilva - September 30, 2015 @ 12:31

@ Relax...

it is possible, just code what you want to do in onBar() instead of onTick().

 

@8051361

In easy Words.... It calculate all positions in one Direction to compensate Profit and Loss, then just added Take Profit.

 

@ Piratetunes, @ Conno123

Just ad a Stoploss in ExecuteMarketOrder (TradeType, Symbol, Volume, Label, STOPLOSS, TakeProfit, Marketrange, Comment)

 

Beste Grüße (Greetz)

zilva

mariam14 - October 03, 2015 @ 21:58

That's great .. 

do you have a one for the metatrader ?

chiripacha - October 09, 2015 @ 18:11

would it make sense to have "max. trades"? on my demo runnung smart grid ihave now 17 positions!

could i copy a line with max trades from another bot and put it into smart grid?

tom_348 - October 27, 2015 @ 14:49

@SaifBD

This algo is amazing but the only problem is, is that with a smaller starting capital, the amount of trades for a certain lot size will decrease dramatically compared to the same lot size with a higher starting capital. Could you please fix this some how, as I don't know anything about coding. Or if you could reply and I'll give you my e-mail address so we can talk.

Thankyou

gizmotn76 - November 03, 2015 @ 09:22

From the best I can tell this codebase is based on some type of mt4 ea that was decompiled which made it difficult to read and follow.  I was looking to do some modifications to the code so before I started I decided to clean things up so I could see what was going on.  I am posting the results (hopefully) the logic should be the same as the original but a bit easier to read.  Note, backtest this bot as it like most grid based bots can get into a catastrophic equity drain if the underlying starts to trend hard.

 

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

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; }

        private double CurrentSpread { get {return (Symbol.Ask - Symbol.Bid)/Symbol.PipSize; } }
        

        protected override void OnStart()
        {
        }

        protected override void OnTick()
        {
            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, 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);
        }
    }
}

mariam14 - January 01, 2016 @ 16:00

@gizmotn76

Thanks man, great job !

it's easy now to edit the cbot

jan-vdh - January 16, 2016 @ 21:00

Hey man this thing is working great, but some equity drawdowns are just too hard!

I had a maximum equity drawdown of 110% so i would be in a complete loss. What can we do against that?

Nobody - January 27, 2016 @ 19:47

Hi Guys,

does someone has good results with this bot ? if yes on wich symbol and with which paramaters values ?

i you could publish results of backtesting or myfxbook perf it would be nice !

Thanks a lot and have good trades ;)

TraderML - February 03, 2016 @ 19:27

Hello,

i think, this is a very good cbot, but can someone help me to add a "Stop Loss"

i'm not a programmer, so i have no idea to do this (i've tried it -  but with no results)

 

thx a lot !

tomrocks - February 25, 2016 @ 04:37

I can't seem to get any working stop loss. I am not a coder but have researched every possible solution with no results. I love this code and would like to use it with minimum drawdown. If anyone is willing to help I would greatly appreciate it.

Regards

ColossusFX - March 17, 2016 @ 19:47

Put this at the top

[Parameter("Stop Loss", DefaultValue = 10)]
        public int StopLoss { get; set; }

Copy below section and paste whole section, or simply add StopLoss after Label.

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;
        }

chiripacha - March 31, 2016 @ 13:14

@Piratetunes

Thank you for your suggestions from March 17. The bot works really good, even on a small EUR 1000 account.

chiripacha - April 19, 2016 @ 02:10

@zilva

bitte schick' mir eine email an

 

info@sicherfair.de

 

Danke

 

Kurt

 

msforex - April 24, 2016 @ 18:33

Hello everybody,

while I tested this cBot I get better result using Onbar method of optimalization... But cAlgo gave me an attention - something like this robot is programmed for OnTick. So my question is it possible to change parameters to OnBar?And which must be changed? Thanks

freestuffenterprise - April 29, 2016 @ 16:41

Good day, is this Cbot valid or still works on Ctrader version 1.35.64939?

cfuorvito - May 03, 2016 @ 11:04

Hi SaifBD . Great cbot, I agree with others though about the equity drawdown.  I'm having trouble adding the stoploss to the code, calgo keeps giving back error readings.  Is there a possibility you or somebody else could post the whole Smart Grid code with the stop loss included? It would be much appriciated.

Many thanks.

Madis - May 09, 2016 @ 15:19

Bot does not work correctly. I have set parameters to sell only, but bot still opens buy positions :(

Trygve93 - June 03, 2016 @ 21:53

hello.

I've been using smartgrid for some months now, and today 12000 dollars were lost, due to an immense decline as to the value of eur/zar.. I've been having stoploss all the  time but today something did not quite go the way it should have. I am in a horrible shcock, and is right now trying to make some sence of this. Is there any way you could help me minimise the risk of this occuring once more? 

I've been frightened from continuing and I would like som support as how to procede.

many thanks.

Trygve93 - June 03, 2016 @ 21:55

I must say. it seems there has been a system fault causing this loss. is there any way of getting some of the money back?

 

thanks

RedDragon - July 05, 2016 @ 04:00

This is a great robot, but there are drawbacks. When he loses a strong trend. I am a C # programmer and try to modify it (add StopLoss and trend indicators stochastic, MACD Crossover). What do you think, if my attempt to be successful, I have the right to put it here without the approval of the author?

RedDragon - July 05, 2016 @ 05:51

I give first a quick option. I added a Stop Loss. http://gigapeta.com/dl/6562936a98dfba

ste_2019 - August 04, 2016 @ 20:04

@zilva

@gizmotn76

 

You can help me? I would like to change it yet. I would like to submit a maximum number of trades for direction (for example 10 to buy and 10 per sell) and maybe every time the logarithm by a new buy / sell signal this to run (perhaps with a larger volume) and it is closed to further loss.

I do not know if this will work better I would try and hear other opinions or ideas.

Thanks very much to everyone

PS. is it possible to change the volumes in lots instead of money so as to try this algorithm also about indexes?

ctid241089 - August 14, 2016 @ 15:52

Kind of love this robot bus as users before have said it have its flaws.

Ive also added a stoploss but without any success.

Have anyone tried to add maximum number of trades in any direction? 

And this pip step feature... will it close a position after like xx candles in a 15 minutes chart? or how does that work?

 

tasr1r1 - August 25, 2016 @ 11:36

i want to this this bot at Metatrader, can anybody port it to MQL4?

tasr1r1 - August 25, 2016 @ 11:40

or C# in order  to test it with Protrader, thanks

 

ngquocthang - August 31, 2016 @ 04:55

Hi I been trying this bot with my live acc. Started with $10000 since march 2016. My net profit atm is around $1800. Not bad. Worth drawdown is around $800-900. Currently the drawdown is $80. I am not saying this will work for sure with everyone. Trading on EURUSD 1D.

 

cfatienza2 - October 15, 2016 @ 05:46

From Aug 3 2016 to Oct 13 2016

1K -> 2.7k profit - not bad for SELL only no stop loss at GBPJPY.

https://gyazo.com/795c6c2de38a3830a8dbee46adefb13f

noormizzy - November 09, 2016 @ 12:19

hello everyone , i would like to know what pair is good for this bot .. also can anyone tell me money mangment for this bot for 1k account thanks

noormizzy - November 09, 2016 @ 12:36

hello what are the modified settings you using ?

 

noormizzy - November 09, 2016 @ 18:24

account blown with default setting , please dont use

ctid264552 - November 12, 2016 @ 22:01

i do back test with BRENT . it working good . make profit every month 30% - 660%. test date 1-30 of month..

amsman - November 22, 2016 @ 15:21

@Piratetunes

Thank you for your SL code from March 17. This bot is great, even for newbie like me....

rantrading - December 28, 2016 @ 03:34

Hi sailBD,

                I was just wondering if i could talk to you privately on skype.

 

 

Thanks Ross.

rantrading - January 08, 2017 @ 07:40

Hi ctid264552,

                       Would you please send me some back test results. I am interested in this CBOT or could i talk to you via Skype or email.

 

 

Thanks Ross.

alinacarstoiu - January 30, 2017 @ 13:29

Hi. Could someone create an updated version of this, with the sugestions people shared above? Probably not everyone knows how to encode or update by itself. Or eventually someone could teach? Thanks.

jaredthirsk - February 18, 2017 @ 03:45

This bot looks incredibly dangerous if you don't know what you're doing (but then I guess all of forex is if you don't know.)  It's sad to see someone lost their account here.

Looks like a martingale style keep increasing risk until you win, but if you keep risking until you run out of equity, you are doomed.

 

tomula@volny.cz - February 23, 2017 @ 11:45

Dont try to use stop loss on this grid bot. That strategy then totally loses half of its sense and purpose, just use your account size as your stop loss, decide on some basic capital which can hold reasonable amounts of pips for your parameter set and then withdraw any extra money from your account regularly.

ctid258440 - March 26, 2017 @ 21:20

This cbot has a fundemental flaw in it. it will keep adding losing positions in a trending market even with a stop loss it does not change how the bot works it will contine to do the same thing so the stop loss has no effect on capital preservation. That is why it has crazy drawdowns which will lead to a margin call. we all know that the markets will go into a hard trend at some point. this bot will clean out your account in those times.

jprgabuya@gmail.com - April 26, 2017 @ 17:36

To the one who created this bot, thanks a lot! I am currently making real money using this bot. I only trade in one direction, either buy or sell.... I am currently trading 1k volume only with ~ 40 USD per day. Sure to make you smile every morning! :)

Now, I am starting to build up my equity to be able to trade higher volumes.

amantalpur007@gmail.com - June 06, 2017 @ 10:53

hey, somebody please tell me how to set STOP LOSS in this bot. so that i dont have to set it manually every time there's new trade. i'm not good in coding. pls help me out. thanks

 

amantalpur007@gmail.com - June 06, 2017 @ 11:16

it would be much better if somebody paste the whole coding with stop loss included in it. i've tried to add stop loss code but it is not working for me, unfortunately. please paste the whole script of coding. thanks

i hope, someone will do it. :)

 

louwmanlukas - October 30, 2017 @ 19:33

I am trying the code with the 15min timeframe. But the things with this bot is that it has to know when to stop adding more positions to a losing position. The idea is very good. But it has to know when the 15min trendline is broken and it has to be able to close the losing positions and start again opening positions in the new trend. 

 

Every week there are some pairs that a gaining or extending very much pips. And if the bot is trading that pair you can have very huge losses. So: if you are able to create a way to make it a little bit smarter it is a very good code.

CoreTradingHouse - February 21, 2018 @ 02:27

Added this to define direction of trades using SMA crossing:

 

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);
            }

CoreTradingHouse - February 21, 2018 @ 02:31

@amantalpur007@gmail.com here you go:

 

//+------------------------------------------------------------------+
//|                                                  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 SmartGrid : Robot
    {
        private bool _accountIsOutOfMoney;
        private int _openTradeResult;

        private readonly string Label = "SmartGrid2";
        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 = 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("Stop Loss", DefaultValue = 10)]
        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);
        }
    }
}

saka.nakhonsri - April 18, 2018 @ 08:17

How to convert to mt4? I traded both platforms.

zedodia - May 30, 2018 @ 13:27

Great little bot you made there. Since the update theres a few errors on build. Also I find that it always buys and sell regardless of selection.

Error CS0618: 'cAlgo.API.Position.Volume' is obsolete: 'Use VolumeInUnits instead'

Error CS0618: 'cAlgo.API.Internals.Symbol.NormalizeVolume(double, cAlgo.API.RoundingMode)' is obsolete: 'Use NormalizeVolumeInUnits instead'

Error CS0618: 'cAlgo.API.Internals.Symbol.VolumeMin' is obsolete: 'Use VolumeInUnitsMin instead'

Error CS0618: 'cAlgo.API.Internals.Symbol.VolumeMax' is obsolete: 'Use VolumeInUnitsMax instead'

zedodia - June 04, 2018 @ 23:00

Great work. I was wondering if there was any way to eliminate the losses. bot makes great profit but also losses great profit too. can more parameters be set to use with optimization?

saka.nakhonsri - June 06, 2018 @ 19:08

@zilva  or bruno.inaciocandeias@gmail.com

how to make Smart Grid cBot to be able to open (in case of volume traded) new positions every 1k ... 1k ...2k....4k....8k...16k....32k....64k........xxk when cBot is increasing sell or buy side?

 

Thank you

saka.nakhonsri - July 18, 2018 @ 19:28

@zilva  or bruno.inaciocandeias@gmail.com or dfwilkie83

How to limit Order Buy Or Sell 

Thank you

Rog2548 - August 02, 2018 @ 20:17

Anyone using this successfully for a while? If so, how do you prevent the massive drawdowns?

It trades great for a little while after backtesting and then activating it, but once it hits the trend the wrong way it wipes out the account. 

If anyone has a way to prevent this, please share or let me know I can pay for a modification to the bot.

klverenac - September 14, 2018 @ 18:38

@dfwilkie83 Did you manage to fix that one error on the end of the code?

CoreTradingHouse - January 28, 2019 @ 02:02

Here it goes, debugged and updated

 

 

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

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; }

        private double CurrentSpread
        {
            get { return (Symbol.Ask - Symbol.Bid) / Symbol.PipSize; }
        }


        protected override void OnStart()
        {
        }

        protected override void OnTick()
        {
            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();
            Chart.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, double 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);
                Chart.DrawHorizontalLine("bpoint", y, Color.Yellow, 2, LineStyle.Dots);
            }
            else
                //ChartObjects.RemoveObject("bpoint");
                Chart.RemoveObject("bpoint");
            if (CountOfTradesOfType(TradeType.Sell) > 1)
            {
                var z = CalculateAveragePositionPrice(TradeType.Sell);
                //ChartObjects.DrawHorizontalLine("spoint", z, Colors.HotPink, 2, LineStyle.Dots);
                Chart.DrawHorizontalLine("spoint", z, Color.HotPink, 2, LineStyle.Dots);
            }
            else
                //ChartObjects.RemoveObject("spoint");
                Chart.RemoveObject("spoint");
            //ChartObjects.DrawText("pan", GenerateStatusText(), StaticPosition.TopLeft, Colors.Tomato);
            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(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;
            double count = 0;


            foreach (var position in Positions)
            {
                if (position.Label == Label && position.SymbolCode == Symbol.Code)
                {
                    if (position.TradeType == tradeType)
                    {
                        averagePrice += position.EntryPrice * position.VolumeInUnits;
                        count += position.VolumeInUnits;
                    }
                }

            }

            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 double GetMostRecentPositionVolume(TradeType tradeType)
        {
            double 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.VolumeInUnits;
                            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 double CalculateVolume(TradeType tradeType)
        {
            var numberOfPositions = CountNumberOfPositionsOfType(tradeType);
            var mostRecentVolume = GetMostRecentPositionVolume(tradeType);
            var calculatedVolume = Symbol.NormalizeVolumeInUnits(mostRecentVolume * Math.Pow(VolumeExponent, numberOfPositions));
            return (calculatedVolume);
        }

        private double LimitVolume(double volumeIn)
        {
            var symbolVolumeMin = Symbol.VolumeInUnitsMin;
            var symbolVolumeMax = Symbol.VolumeInUnitsMax;
            var result = volumeIn;
            if (result < symbolVolumeMin)
                result = symbolVolumeMin;
            if (result > symbolVolumeMax)
                result = symbolVolumeMax;
            return (result);
        }
    }
}

bave_rowe28 - February 08, 2019 @ 16:37

Hi, Candeias & dfwilkie83 

this is a greate bot, i have been using and testing it for more than 6 months now, but is is still show several errors based on the last once you have published 

 

i have some greate ideas that if implemented on this bot it will convert it to a an excllent highly profitable bot but this needs a C# skill which i don't have, are you into discussing this project ? 

 

ZuniSoft - March 26, 2019 @ 19:06

there are eight functions listed below

------------------------------------------

int <- cnt_16()

double <-  D_TD(-)

double <-  U_TD(-)

double <- f-tk(-)

long <- It_8(-)

long <- clt(-)

int <- Grd_Ex(-,-)

long <- n_It(-)

------------------------------------

u have'nt used them any where, what r their purpose?

 

krecheage - April 10, 2019 @ 15:07

Hi guys, this is a very good cbot and if properly managed you will mke good profit in the long run, I use to trade with similer EA on MT4 so it was easy for me to modify it to what I was used to. below is how my modified version works:

If Buy is yes, the bot will buy and then place a BuyLimit for the next posible buy if price goes negative and if TP is hit, the BuyLimit is deleted.

I also introduce hedging system to protect account wip out, but once the heding system is triggard, if the TP is hit, all trades will close at small profit and if SL is hit, all trade will close at reasonable loss but account will not wip out. PM:- patways at rocketmail dot com

jumpycalm - April 17, 2019 @ 04:56

Hi guys, this is probably the most mentioned and most popular cBot on cTrader. I have re-written the code and posted the code on github. Since the comments on this page is very long. I also created a new cBot link on ctrader.com, you guys can post any new comment on the new page.

Very special thanks to SaifBD for posting the very original code on to ctrader.com, that made the version 1 of the code

Special thanks to Candeias for re-writing the decompiled code to more human readable code which made the version 2 of the code.

Below are the improvements for the new code.

1. Code has been cleaned up and shortened to half, from over 400 lines to 200 lines. I added some comments in the code for easier understanding on the cBot;

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.

https://ctrader.com/algos/cbots/show/1880

tgjobscv - April 24, 2019 @ 22:04

Who use in real account or VPS ?

 

Pb75 - May 03, 2019 @ 10:02

I download the bot from this page, the answer Is: Is the same version of Smart Grid v3 or this Is the old version? Thanks

kanapon - May 04, 2019 @ 09:21

All thank you so much for your contribute to improve this bot Can anyone help me if my account had leverage 1:100 how can i backtest with this leverage value? Thanks

KubilayBoz - May 14, 2019 @ 17:55

Test starts by 14.05.2019 Time:17:00 (UTC+3)

Chart : EURUSD

Timeframe : 3 min

Buy : Yes

Sell : Yes

Pipstep : 8

Volume Exponent : 1.1

Average TP : 4

First Volume : 10.000 (0.10 LOT)

Max Spread : 3

Account Margin : 10.000 US DOLLAR

Leverage : 1/10

Margin Call : %30

Mr4x - May 23, 2019 @ 14:44

Friends,

I feel like I have almost honed in on something worthy. I have figured that USDJPY and CHFJPY are very highly correlated most of the time, so therefor being long USDJPY and short CHFJPY at the same time can quite often yield good results, the swap is also positive overall this way.

The method I am using so far, with positive returns on both days after 2 days, cannot be backtested as it relies on running 2 instances of this bot on the same account at the same time (which also keeps your equity somewhat in balance). This means it has to be used in a demo account, unless one of you smart cookies can figure out a way to cross-test and share the best results. Here are my settings so far, please try to optimise them for better return / lower drawdown and get back to me:

Chart : USDJPY

Timeframe : 15 min

Buy : Yes

Sell : No

Pipstep : 5

Volume Exponent : 1.1

Average TP : 4

First Volume : 2000 (0.20 LOT)

Max Spread : 2

Account Margin : 40000 US DOLLAR

Leverage : 1/500

 

---AND---

 

Chart : CHFJPY

Timeframe : 15 min

Buy : No

Sell : Yes

Pipstep : 5

Volume Exponent : 1.1

Average TP : 4

First Volume : 2000 (0.20 LOT)

Max Spread : 2

Account Margin : 40000 US DOLLAR

Leverage : 1/500

kanapon - May 28, 2019 @ 10:21

Now i have issue with this bot, same as username "9469cd97" post on 2015

i run this bot on VPS and on GBPUSD. start i open buy and sell and then the i have waiting 10 positions on buy so i stop buy by set parameter to only sell. (not buy positions remain, not close them)

anyway system still open buy when pips step is meet condition.

i even try to rerun ctrader and delete instance but issue still persist. so sad.

anyone know how to solve? 

kanapon - June 01, 2019 @ 19:27

got the answer, the parameter is control buy sell when there are no position.

if we need to control when there are position opened, need to adjust code as below 

 

Old

if (CountOfTradesOfType(TradeType.Buy) > 0)

New

if (CountOfTradesOfType(TradeType.Buy) > 0 && Buy)

 

tgjobscv - September 13, 2019 @ 15:39

1

2

[Parameter("Sell", DefaultValue = false)]

        public bool Sell { get; set; }

Hi.

What wrrong. 

Bot now open buy and sell ?!

sell is false ?!

defaultvalue is ignore ?

How fix ?

tgjobscv - September 13, 2019 @ 16:10

V4 with SMA, but:

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

What wrrong. 

Bot now open buy and sell ?!

sell is false ?!

defaultvalue is ignore ?

How fix ?

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; }

tgjobscv - September 13, 2019 @ 16:11

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

What wrrong. 

Bot now open buy and sell ?!

sell is false ?!

defaultvalue is ignore ?

How fix ?

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

tgjobscv - September 13, 2019 @ 16:15

Hi.

V4 with SMA, but:

 

1. What wrrong ?

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

tgjobscv - October 01, 2019 @ 21:32

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

CoreTradingHouse - October 16, 2019 @ 02:09

@bave_rowe28

been away for a while! sure, we can develop something together!
 

tgjobscv - July 26, 2020 @ 18:02

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 ?

reking86 - August 04, 2020 @ 21:12

someone can help me set up the bot for a balance of 150 euros???

MarathonFX - January 04, 2021 @ 09:45

Thanks for the helpful sharing. I want to use this robot in a semi-automatic way. How does it stop automatically when taking a profit? Look forward to hearing from the coder

TradeHiTech - February 22, 2021 @ 12:52

What I need to change in the code for to ensure that when does it touch the TP if I want it to stop opening new positions?

DonDemon - September 22, 2022 @ 15:03

Just BS: You have to check the bot all the time. Opening new buys all the time, even with buys and sells set to off in parameters. Doesn't take long to margin call. Very sad. If the settings would work like they do it would be very good and profitable..

5