Stochastic&Bands strategy

Moderator: admin

Re: Stochastic&Bands strategy

Postby tdesiato » Sat Sep 21, 2013 8:37 pm

The issue I'm having is when backtesting on a demo account, the LImit works fine until I set a stop. Once i set a stop, the limit no longer closes the trade when that limit is reached. Even if I set the stop for 500 or some crazy high number. it's like setting the SetStop to "yes" breaks the Limit function in the code. I've been trying to find the bug, but not having any luck.

Also, for anyone who is familiar with Forexmentor and their Slingshot trade strategy, I'm trying to modify this code to detect this setup. For the most part, it's the opposite of what this code was doing. Trigger a "B" when the Stochastic is overbought and flat, Trigger a "S" when it is oversold and flat. Then add the 8 EMA crosses the 20 SMA, and it should be a really super strategy with very tight stops.

Any help solving this Stop/Limit bug will be much appreciated.

Thank you.

Code: Select all
function Init() --The strategy profile initialization
    strategy:name("Stochastic+BB strategy");
    strategy:description("MACD Divergence+BB strategy");

    strategy.parameters:addGroup("Stochastic parameters");
    strategy.parameters:addInteger("Stoch_K", "Number of periods for %K", "Number of periods for %K", 5, 2, 1000);
    strategy.parameters:addInteger("Stoch_SD", "%D slowing periods", "%D slowing periods", 3, 2, 1000);
    strategy.parameters:addInteger("Stoch_D", "Number of periods for %D", "Number of periods for %D", 3, 2, 1000);

    strategy.parameters:addString("Stoch_MVAT_K", "Smoothing type for %K", "Smoothing type for %K", "MVA");
    strategy.parameters:addStringAlternative("Stoch_MVAT_K", "MVA", "", "MVA");
    strategy.parameters:addStringAlternative("Stoch_MVAT_K", "EMA", "", "EMA");
    strategy.parameters:addStringAlternative("Stoch_MVAT_K", "FS", "", "FS");

    strategy.parameters:addString("Stoch_MVAT_D", "Smoothing type for %D", "Smoothing type for %D", "MVA");
    strategy.parameters:addStringAlternative("Stoch_MVAT_D", "MVA", "", "MVA");
    strategy.parameters:addStringAlternative("Stoch_MVAT_D", "MVA", "", "EMA");

    strategy.parameters:addGroup("Bands parameters");
    strategy.parameters:addInteger("BB_N", "Number of periods", "Number of periods", 20, 1, 10000);
    strategy.parameters:addDouble("BB_Dev", "Number of standard deviation", "Number of standard deviation", 2.0, 0.0001, 1000.0);
    strategy.parameters:addString("BB_Price", "Price for bands", "", "close");
    strategy.parameters:addStringAlternative("BB_Price", "close", "", "close");
    strategy.parameters:addStringAlternative("BB_Price", "open", "", "open");
    strategy.parameters:addStringAlternative("BB_Price", "high", "", "high");
    strategy.parameters:addStringAlternative("BB_Price", "low", "", "low");
    strategy.parameters:addStringAlternative("BB_Price", "median", "", "median");
    strategy.parameters:addStringAlternative("BB_Price", "typical", "", "typical");
    strategy.parameters:addStringAlternative("BB_Price", "weighted", "", "weighted");

    strategy.parameters:addGroup("Strategy Parameters");
    strategy.parameters:addDouble("OversoldLevel", "Oversold level", "Oversold level", 20, 0, 100);
    strategy.parameters:addDouble("OverboughtLevel", "Overbought level", "Overbought level", 80, 0, 100);
    strategy.parameters:addInteger("MaxDistance", "Max. distance between Stochastic and BB events", "Max. distance between Stochastic and BB events", 1, 0, 1000);
  --  strategy.parameters:addString("TypeSignal", "Type of signal", "", "direct");
  --  strategy.parameters:addStringAlternative("TypeSignal", "direct", "", "direct");
  --  strategy.parameters:addStringAlternative("TypeSignal", "reverse", "", "reverse");

    strategy.parameters:addGroup("Price Parameters");
    strategy.parameters:addString("TF", "Time Frame", "", "m15");
    strategy.parameters:setFlag("TF", core.FLAG_PERIODS);

    strategy.parameters:addGroup("Trading Parameters");
    strategy.parameters:addBoolean("AllowTrade", "Allow strategy to trade", "", false);
    strategy.parameters:addString("Account", "Account to trade on", "", "");
    strategy.parameters:setFlag("Account", core.FLAG_ACCOUNT);
    strategy.parameters:addInteger("Amount", "Trade Amount in Lots", "", 1, 1, 100);
    strategy.parameters:addBoolean("SetLimit", "Set Limit Orders", "", false);
    strategy.parameters:addInteger("Limit", "Limit Order in pips", "", 30, 1, 10000);
    strategy.parameters:addBoolean("SetStop", "Set Stop Orders", "", false);
    strategy.parameters:addInteger("Stop", "Stop Order in pips", "", 30, 1, 10000);
    strategy.parameters:addBoolean("TrailingStop", "Trailing stop order", "", false);
    strategy.parameters:addString("AllowDirection", "Allow direction for positions", "", "Both");
    strategy.parameters:addStringAlternative("AllowDirection", "Both", "", "Both");
    strategy.parameters:addStringAlternative("AllowDirection", "Long", "", "Long");
    strategy.parameters:addStringAlternative("AllowDirection", "Short", "", "Short");

    strategy.parameters:addGroup("Signal Parameters");
    strategy.parameters:addBoolean("ShowAlert", "Show Alert", "", true);
    strategy.parameters:addBoolean("PlaySound", "Play Sound", "", false);
    strategy.parameters:addFile("SoundFile", "Sound File", "", "");
    strategy.parameters:setFlag("SoundFile", core.FLAG_SOUND);
    strategy.parameters:addBoolean("Recurrent", "RecurrentSound", "", false);

    strategy.parameters:addGroup("Email Parameters");
    strategy.parameters:addBoolean("SendEmail", "Send email", "", false);
    strategy.parameters:addString("Email", "Email address", "", "");
    strategy.parameters:setFlag("Email", core.FLAG_EMAIL);
end

-- Signal Parameters
local ShowAlert;
local SoundFile;
local RecurrentSound;
local SendEmail, Email;

-- Internal indicators
local Stoch = nil;
local BB = nil;

-- Strategy parameters
local openLevel = 0
local closeLevel = 0
local confirmTrend;

-- Trading parameters
local AllowTrade = nil;
local Account = nil;
local Amount = nil;
local BaseSize = nil;
local PipSize;
local SetLimit = nil;
local Limit = nil;
local SetStop = nil;
local Stop = nil;
local TrailingStop = nil;
local CanClose = nil;
local AllowDirection;

--
--
--
function Prepare()
    ShowAlert = instance.parameters.ShowAlert;
    AllowDirection = instance.parameters.AllowDirection;
    local PlaySound = instance.parameters.PlaySound
    if  PlaySound then
        SoundFile = instance.parameters.SoundFile;
    else
        SoundFile = nil;
    end
    assert(not(PlaySound) or SoundFile ~= "", "Sound file must be chosen");
    RecurrentSound = instance.parameters.Recurrent;

    local SendEmail = instance.parameters.SendEmail;
    if SendEmail then
        Email = instance.parameters.Email;
    else
        Email = nil;
    end
    assert(not(SendEmail) or Email ~= "", "Email address must be specified");
    assert(instance.parameters.TF ~= "t1", "The time frame must not be tick");

    local name;
    name = profile:id() .. "(" .. instance.bid:name() .. "." .. instance.parameters.TF;
    instance:name(name);

    AllowTrade = instance.parameters.AllowTrade;
    if AllowTrade then
        Account = instance.parameters.Account;
        Amount = instance.parameters.Amount;
        BaseSize = core.host:execute("getTradingProperty", "baseUnitSize", instance.bid:instrument(), Account);
        Offer = core.host:findTable("offers"):find("Instrument", instance.bid:instrument()).OfferID;
        CanClose = core.host:execute("getTradingProperty", "canCreateMarketClose", instance.bid:instrument(), Account);
        PipSize = instance.bid:pipSize();
        SetLimit = instance.parameters.SetLimit;
        Limit = instance.parameters.Limit;
        SetStop = instance.parameters.SetStop;
        Stop = instance.parameters.Stop;
        TrailingStop = instance.parameters.TrailingStop;
    end

    Source = ExtSubscribe(2, nil, instance.parameters.TF, true, "bar");
    Stoch = core.indicators:create("STOCHASTIC", Source, instance.parameters.Stoch_K, instance.parameters.Stoch_SD, instance.parameters.Stoch_D, instance.parameters.Stoch_MVAT_K, instance.parameters.Stoch_MVAT_D);
    Price=instance.parameters.BB_Price;
    if Price=="close" then
     BB = core.indicators:create("BB", Source.close, instance.parameters.BB_N, instance.parameters.BB_Dev);
    elseif Price=="open" then
     BB = core.indicators:create("BB", Source.open, instance.parameters.BB_N, instance.parameters.BB_Dev);
    elseif Price=="high" then
     BB = core.indicators:create("BB", Source.high, instance.parameters.BB_N, instance.parameters.BB_Dev);
    elseif Price=="low" then
     BB = core.indicators:create("BB", Source.low, instance.parameters.BB_N, instance.parameters.BB_Dev);
    elseif Price=="typical" then
     BB = core.indicators:create("BB", Source.typical, instance.parameters.BB_N, instance.parameters.BB_Dev);
    elseif Price=="median" then
     BB = core.indicators:create("BB", Source.median, instance.parameters.BB_N, instance.parameters.BB_Dev);
    else
     BB = core.indicators:create("BB", Source.weighted, instance.parameters.BB_N, instance.parameters.BB_Dev);
    end

    ExtSetupSignal(profile:id() .. ":", ShowAlert);
    ExtSetupSignalMail(name);
end

function ExtUpdate(id, source, period)  -- The method called every time when a new bid or ask price appears.
    Stoch:update(core.UpdateLast);
    BB:update(core.UpdateLast);

    -- Check that we have enough data
    if (Stoch.DATA:first() > (period - 1)) then
        return
    end
    if (BB.DATA:first() > (period - 1)) then
        return
    end

    local pipSize = instance.bid:pipSize()

    local trades = core.host:findTable("trades");
    local haveTrades = (trades:find('AccountID', Account) ~= nil)
   
    local MustOpenB=false;
    local MustOpenS=false;
   
    if Stoch.K[period]<=instance.parameters.OversoldLevel and Stoch.D[period]<=instance.parameters.OversoldLevel then
     if BB_Touch("U",period) then
      MustOpenS=true;
     end
    end
   
    if Stoch.K[period]>=instance.parameters.OverboughtLevel and Stoch.D[period]>=instance.parameters.OverboughtLevel then
     if BB_Touch("L",period) then
      MustOpenB=true;
     end
    end
   
    if (haveTrades) then
        local enum = trades:enumerator();
        while true do
            local row = enum:next();
            if row == nil then break end

            if row.AccountID == Account and row.OfferID == Offer then
                    -- Close position if we have corresponding closing conditions.
                if row.BS == 'B' then
                  if MustOpenS then
               if ShowAlert then
                 if instance.parameters.AllowDirection=="Long" then
                  ExtSignal(source, period, "Close BUY", SoundFile, Email, RecurrentSound);
                      else
                  ExtSignal(source, period, "Close BUY and SELL", SoundFile, Email, RecurrentSound);
                 end   
               end

               if AllowTrade then
                       Close(row);
                       if instance.parameters.AllowDirection~="Long" then
                         Open("S")
                       end
               end
                  end
                elseif row.BS == 'S' then
                  if MustOpenB then
               if ShowAlert then
                 if instance.parameters.AllowDirection=="Short" then
                        ExtSignal(source, period, "Close SELL", SoundFile, Email, RecurrentSound);
                      else
                  ExtSignal(source, period, "Close SELL and BUY", SoundFile, Email, RecurrentSound);
                 end   
               end

               if AllowTrade then
                      Close(row);
                      if instance.parameters.AllowDirection~="Short" then
                        Open("B")
                      end
               end
                  end
                end

            end
        end
   else
        if MustOpenB==true and instance.parameters.AllowDirection~="Short" then
          if ShowAlert then
            ExtSignal(source, period, "BUY", SoundFile, Email, RecurrentSound)
          end

          if AllowTrade then
            Open("B")
          end
        end

        if MustOpenS==true and instance.parameters.AllowDirection~="Long" then
          if ShowAlert then
            ExtSignal(source, period, "SELL", SoundFile, Email, RecurrentSound)
          end

        if AllowTrade then
            Open("S")
         end
        end
    end
end

-- The strategy instance finalization.
function ReleaseInstance()
end

-- The method enters to the market
function Open(side)
    local valuemap;

    valuemap = core.valuemap();
    valuemap.OrderType = "OM";
    valuemap.OfferID = Offer;
    valuemap.AcctID = Account;
    valuemap.Quantity = Amount * BaseSize;
    valuemap.CustomID = CID;
    valuemap.BuySell = side;
    valuemap.QTXT="1";
    if SetStop and CanClose then
        valuemap.PegTypeStop = "O";
        if side == "B" then
            valuemap.PegPriceOffsetPipsStop = -Stop;
        else
            valuemap.PegPriceOffsetPipsStop = Stop;
        end
        if TrailingStop then
            valuemap.TrailStepStop = 1;
        end;
    end
    if SetLimit and CanClose then
        valuemap.PegTypeLimit = "O";
        if side == "B" then
            valuemap.PegPriceOffsetPipsLimit = Limit;
        else
            valuemap.PegPriceOffsetPipsLimit = -Limit;
        end
    end
    success, msg = terminal:execute(200, valuemap);
    assert(success, msg);

    -- FIFO Account, in that case we have to open Net Limit and Stop Orders
    if not(CanClose) then
        if SetStop then
            valuemap = core.valuemap();
            valuemap.OrderType = "SE"
            valuemap.OfferID = Offer;
            valuemap.AcctID = Account;
            valuemap.NetQtyFlag = 'y';
            if side == "B" then
                valuemap.BuySell = "S";
                rate = instance.ask[NOW] - Stop * PipSize;
                valuemap.Rate = rate;
            elseif side == "S" then
                valuemap.BuySell = "B";
                rate = instance.bid[NOW] + Stop * PipSize;
                valuemap.Rate = rate;
            end
            if TrailingStop then
                valuemap.TrailUpdatePips = 1
            end
            success, msg = terminal:execute(200, valuemap);
            --core.host:trace('Set stop @ ' .. rate);
            assert(success, msg);
        end
        if SetLimit then
            valuemap = core.valuemap();
            valuemap.OrderType = "LE"
            valuemap.OfferID = Offer;
            valuemap.AcctID = Account;
            valuemap.NetQtyFlag = 'y';
            if side == "B" then
                valuemap.BuySell = "S";
                rate = instance.ask[NOW] + Limit * PipSize;
                valuemap.Rate = rate;
            elseif side == "S" then
                valuemap.BuySell = "B";
                rate = instance.bid[NOW] - Limit * PipSize;
                valuemap.Rate = rate;
            end
            success, msg = terminal:execute(200, valuemap);
            --core.host:trace('Set limit @ ' .. rate);
            assert(success, msg);
        end
    end
end

function BB_Touch(Band,period)
 local period_=period;
 while period_>Source:first() and period-period_<=instance.parameters.MaxDistance do
  if Band=="U" and Source.high[period_]>=BB.TL[period_] then
   return true;
  elseif Band=="L" and Source.low[period_]<=BB.BL[period_] then
   return true;
  end
  period_=period_-1;
 end
 return false;
end

-- Closes specific position
function Close(trade)
    local valuemap;
    valuemap = core.valuemap();

    if CanClose then
        -- non-FIFO account, create a close market order
        valuemap.OrderType = "CM";
        valuemap.TradeID = trade.TradeID;
    else
        -- FIFO account, create an opposite market order
        valuemap.OrderType = "OM";
    end

    valuemap.OfferID = trade.OfferID;
    valuemap.AcctID = trade.AccountID;
    valuemap.Quantity = trade.Lot;
    valuemap.CustomID = trade.QTXT;
    if trade.BS == "B" then valuemap.BuySell = "S"; else valuemap.BuySell = "B"; end
    success, msg = terminal:execute(200, valuemap);
    assert(success, msg);
end

function AsyncOperationFinished(cookie, successful, message)
  if not successful then
    core.host:trace('Error: ' .. message)
  end
end

dofile(core.app_path() .. "\\strategies\\standard\\include\\helper.lua");
tdesiato
 
Posts: 13
Joined: Sun Jun 02, 2013 11:47 pm

Re: Stochastic&Bands strategy

Postby Victor.Tereschenko » Mon Sep 23, 2013 5:12 am

tdesiato wrote:The issue I'm having is when backtesting on a demo account, the LImit works fine until I set a stop. Once i set a stop, the limit no longer closes the trade when that limit is reached. Even if I set the stop for 500 or some crazy high number. it's like setting the SetStop to "yes" breaks the Limit function in the code. I've been trying to find the bug, but not having any luck.

Also, for anyone who is familiar with Forexmentor and their Slingshot trade strategy, I'm trying to modify this code to detect this setup. For the most part, it's the opposite of what this code was doing. Trigger a "B" when the Stochastic is overbought and flat, Trigger a "S" when it is oversold and flat. Then add the 8 EMA crosses the 20 SMA, and it should be a really super strategy with very tight stops.

Any help solving this Stop/Limit bug will be much appreciated.

Thank you.

Code: Select all
function Init() --The strategy profile initialization
    strategy:name("Stochastic+BB strategy");
    strategy:description("MACD Divergence+BB strategy");

    strategy.parameters:addGroup("Stochastic parameters");
    strategy.parameters:addInteger("Stoch_K", "Number of periods for %K", "Number of periods for %K", 5, 2, 1000);
    strategy.parameters:addInteger("Stoch_SD", "%D slowing periods", "%D slowing periods", 3, 2, 1000);
    strategy.parameters:addInteger("Stoch_D", "Number of periods for %D", "Number of periods for %D", 3, 2, 1000);

    strategy.parameters:addString("Stoch_MVAT_K", "Smoothing type for %K", "Smoothing type for %K", "MVA");
    strategy.parameters:addStringAlternative("Stoch_MVAT_K", "MVA", "", "MVA");
    strategy.parameters:addStringAlternative("Stoch_MVAT_K", "EMA", "", "EMA");
    strategy.parameters:addStringAlternative("Stoch_MVAT_K", "FS", "", "FS");

    strategy.parameters:addString("Stoch_MVAT_D", "Smoothing type for %D", "Smoothing type for %D", "MVA");
    strategy.parameters:addStringAlternative("Stoch_MVAT_D", "MVA", "", "MVA");
    strategy.parameters:addStringAlternative("Stoch_MVAT_D", "MVA", "", "EMA");

    strategy.parameters:addGroup("Bands parameters");
    strategy.parameters:addInteger("BB_N", "Number of periods", "Number of periods", 20, 1, 10000);
    strategy.parameters:addDouble("BB_Dev", "Number of standard deviation", "Number of standard deviation", 2.0, 0.0001, 1000.0);
    strategy.parameters:addString("BB_Price", "Price for bands", "", "close");
    strategy.parameters:addStringAlternative("BB_Price", "close", "", "close");
    strategy.parameters:addStringAlternative("BB_Price", "open", "", "open");
    strategy.parameters:addStringAlternative("BB_Price", "high", "", "high");
    strategy.parameters:addStringAlternative("BB_Price", "low", "", "low");
    strategy.parameters:addStringAlternative("BB_Price", "median", "", "median");
    strategy.parameters:addStringAlternative("BB_Price", "typical", "", "typical");
    strategy.parameters:addStringAlternative("BB_Price", "weighted", "", "weighted");

    strategy.parameters:addGroup("Strategy Parameters");
    strategy.parameters:addDouble("OversoldLevel", "Oversold level", "Oversold level", 20, 0, 100);
    strategy.parameters:addDouble("OverboughtLevel", "Overbought level", "Overbought level", 80, 0, 100);
    strategy.parameters:addInteger("MaxDistance", "Max. distance between Stochastic and BB events", "Max. distance between Stochastic and BB events", 1, 0, 1000);
  --  strategy.parameters:addString("TypeSignal", "Type of signal", "", "direct");
  --  strategy.parameters:addStringAlternative("TypeSignal", "direct", "", "direct");
  --  strategy.parameters:addStringAlternative("TypeSignal", "reverse", "", "reverse");

    strategy.parameters:addGroup("Price Parameters");
    strategy.parameters:addString("TF", "Time Frame", "", "m15");
    strategy.parameters:setFlag("TF", core.FLAG_PERIODS);

    strategy.parameters:addGroup("Trading Parameters");
    strategy.parameters:addBoolean("AllowTrade", "Allow strategy to trade", "", false);
    strategy.parameters:addString("Account", "Account to trade on", "", "");
    strategy.parameters:setFlag("Account", core.FLAG_ACCOUNT);
    strategy.parameters:addInteger("Amount", "Trade Amount in Lots", "", 1, 1, 100);
    strategy.parameters:addBoolean("SetLimit", "Set Limit Orders", "", false);
    strategy.parameters:addInteger("Limit", "Limit Order in pips", "", 30, 1, 10000);
    strategy.parameters:addBoolean("SetStop", "Set Stop Orders", "", false);
    strategy.parameters:addInteger("Stop", "Stop Order in pips", "", 30, 1, 10000);
    strategy.parameters:addBoolean("TrailingStop", "Trailing stop order", "", false);
    strategy.parameters:addString("AllowDirection", "Allow direction for positions", "", "Both");
    strategy.parameters:addStringAlternative("AllowDirection", "Both", "", "Both");
    strategy.parameters:addStringAlternative("AllowDirection", "Long", "", "Long");
    strategy.parameters:addStringAlternative("AllowDirection", "Short", "", "Short");

    strategy.parameters:addGroup("Signal Parameters");
    strategy.parameters:addBoolean("ShowAlert", "Show Alert", "", true);
    strategy.parameters:addBoolean("PlaySound", "Play Sound", "", false);
    strategy.parameters:addFile("SoundFile", "Sound File", "", "");
    strategy.parameters:setFlag("SoundFile", core.FLAG_SOUND);
    strategy.parameters:addBoolean("Recurrent", "RecurrentSound", "", false);

    strategy.parameters:addGroup("Email Parameters");
    strategy.parameters:addBoolean("SendEmail", "Send email", "", false);
    strategy.parameters:addString("Email", "Email address", "", "");
    strategy.parameters:setFlag("Email", core.FLAG_EMAIL);
end

-- Signal Parameters
local ShowAlert;
local SoundFile;
local RecurrentSound;
local SendEmail, Email;

-- Internal indicators
local Stoch = nil;
local BB = nil;

-- Strategy parameters
local openLevel = 0
local closeLevel = 0
local confirmTrend;

-- Trading parameters
local AllowTrade = nil;
local Account = nil;
local Amount = nil;
local BaseSize = nil;
local PipSize;
local SetLimit = nil;
local Limit = nil;
local SetStop = nil;
local Stop = nil;
local TrailingStop = nil;
local CanClose = nil;
local AllowDirection;

--
--
--
function Prepare()
    ShowAlert = instance.parameters.ShowAlert;
    AllowDirection = instance.parameters.AllowDirection;
    local PlaySound = instance.parameters.PlaySound
    if  PlaySound then
        SoundFile = instance.parameters.SoundFile;
    else
        SoundFile = nil;
    end
    assert(not(PlaySound) or SoundFile ~= "", "Sound file must be chosen");
    RecurrentSound = instance.parameters.Recurrent;

    local SendEmail = instance.parameters.SendEmail;
    if SendEmail then
        Email = instance.parameters.Email;
    else
        Email = nil;
    end
    assert(not(SendEmail) or Email ~= "", "Email address must be specified");
    assert(instance.parameters.TF ~= "t1", "The time frame must not be tick");

    local name;
    name = profile:id() .. "(" .. instance.bid:name() .. "." .. instance.parameters.TF;
    instance:name(name);

    AllowTrade = instance.parameters.AllowTrade;
    if AllowTrade then
        Account = instance.parameters.Account;
        Amount = instance.parameters.Amount;
        BaseSize = core.host:execute("getTradingProperty", "baseUnitSize", instance.bid:instrument(), Account);
        Offer = core.host:findTable("offers"):find("Instrument", instance.bid:instrument()).OfferID;
        CanClose = core.host:execute("getTradingProperty", "canCreateMarketClose", instance.bid:instrument(), Account);
        PipSize = instance.bid:pipSize();
        SetLimit = instance.parameters.SetLimit;
        Limit = instance.parameters.Limit;
        SetStop = instance.parameters.SetStop;
        Stop = instance.parameters.Stop;
        TrailingStop = instance.parameters.TrailingStop;
    end

    Source = ExtSubscribe(2, nil, instance.parameters.TF, true, "bar");
    Stoch = core.indicators:create("STOCHASTIC", Source, instance.parameters.Stoch_K, instance.parameters.Stoch_SD, instance.parameters.Stoch_D, instance.parameters.Stoch_MVAT_K, instance.parameters.Stoch_MVAT_D);
    Price=instance.parameters.BB_Price;
    if Price=="close" then
     BB = core.indicators:create("BB", Source.close, instance.parameters.BB_N, instance.parameters.BB_Dev);
    elseif Price=="open" then
     BB = core.indicators:create("BB", Source.open, instance.parameters.BB_N, instance.parameters.BB_Dev);
    elseif Price=="high" then
     BB = core.indicators:create("BB", Source.high, instance.parameters.BB_N, instance.parameters.BB_Dev);
    elseif Price=="low" then
     BB = core.indicators:create("BB", Source.low, instance.parameters.BB_N, instance.parameters.BB_Dev);
    elseif Price=="typical" then
     BB = core.indicators:create("BB", Source.typical, instance.parameters.BB_N, instance.parameters.BB_Dev);
    elseif Price=="median" then
     BB = core.indicators:create("BB", Source.median, instance.parameters.BB_N, instance.parameters.BB_Dev);
    else
     BB = core.indicators:create("BB", Source.weighted, instance.parameters.BB_N, instance.parameters.BB_Dev);
    end

    ExtSetupSignal(profile:id() .. ":", ShowAlert);
    ExtSetupSignalMail(name);
end

function ExtUpdate(id, source, period)  -- The method called every time when a new bid or ask price appears.
    Stoch:update(core.UpdateLast);
    BB:update(core.UpdateLast);

    -- Check that we have enough data
    if (Stoch.DATA:first() > (period - 1)) then
        return
    end
    if (BB.DATA:first() > (period - 1)) then
        return
    end

    local pipSize = instance.bid:pipSize()

    local trades = core.host:findTable("trades");
    local haveTrades = (trades:find('AccountID', Account) ~= nil)
   
    local MustOpenB=false;
    local MustOpenS=false;
   
    if Stoch.K[period]<=instance.parameters.OversoldLevel and Stoch.D[period]<=instance.parameters.OversoldLevel then
     if BB_Touch("U",period) then
      MustOpenS=true;
     end
    end
   
    if Stoch.K[period]>=instance.parameters.OverboughtLevel and Stoch.D[period]>=instance.parameters.OverboughtLevel then
     if BB_Touch("L",period) then
      MustOpenB=true;
     end
    end
   
    if (haveTrades) then
        local enum = trades:enumerator();
        while true do
            local row = enum:next();
            if row == nil then break end

            if row.AccountID == Account and row.OfferID == Offer then
                    -- Close position if we have corresponding closing conditions.
                if row.BS == 'B' then
                  if MustOpenS then
               if ShowAlert then
                 if instance.parameters.AllowDirection=="Long" then
                  ExtSignal(source, period, "Close BUY", SoundFile, Email, RecurrentSound);
                      else
                  ExtSignal(source, period, "Close BUY and SELL", SoundFile, Email, RecurrentSound);
                 end   
               end

               if AllowTrade then
                       Close(row);
                       if instance.parameters.AllowDirection~="Long" then
                         Open("S")
                       end
               end
                  end
                elseif row.BS == 'S' then
                  if MustOpenB then
               if ShowAlert then
                 if instance.parameters.AllowDirection=="Short" then
                        ExtSignal(source, period, "Close SELL", SoundFile, Email, RecurrentSound);
                      else
                  ExtSignal(source, period, "Close SELL and BUY", SoundFile, Email, RecurrentSound);
                 end   
               end

               if AllowTrade then
                      Close(row);
                      if instance.parameters.AllowDirection~="Short" then
                        Open("B")
                      end
               end
                  end
                end

            end
        end
   else
        if MustOpenB==true and instance.parameters.AllowDirection~="Short" then
          if ShowAlert then
            ExtSignal(source, period, "BUY", SoundFile, Email, RecurrentSound)
          end

          if AllowTrade then
            Open("B")
          end
        end

        if MustOpenS==true and instance.parameters.AllowDirection~="Long" then
          if ShowAlert then
            ExtSignal(source, period, "SELL", SoundFile, Email, RecurrentSound)
          end

        if AllowTrade then
            Open("S")
         end
        end
    end
end

-- The strategy instance finalization.
function ReleaseInstance()
end

-- The method enters to the market
function Open(side)
    local valuemap;

    valuemap = core.valuemap();
    valuemap.OrderType = "OM";
    valuemap.OfferID = Offer;
    valuemap.AcctID = Account;
    valuemap.Quantity = Amount * BaseSize;
    valuemap.CustomID = CID;
    valuemap.BuySell = side;
    valuemap.QTXT="1";
    if SetStop and CanClose then
        valuemap.PegTypeStop = "O";
        if side == "B" then
            valuemap.PegPriceOffsetPipsStop = -Stop;
        else
            valuemap.PegPriceOffsetPipsStop = Stop;
        end
        if TrailingStop then
            valuemap.TrailStepStop = 1;
        end;
    end
    if SetLimit and CanClose then
        valuemap.PegTypeLimit = "O";
        if side == "B" then
            valuemap.PegPriceOffsetPipsLimit = Limit;
        else
            valuemap.PegPriceOffsetPipsLimit = -Limit;
        end
    end
    success, msg = terminal:execute(200, valuemap);
    assert(success, msg);

    -- FIFO Account, in that case we have to open Net Limit and Stop Orders
    if not(CanClose) then
        if SetStop then
            valuemap = core.valuemap();
            valuemap.OrderType = "SE"
            valuemap.OfferID = Offer;
            valuemap.AcctID = Account;
            valuemap.NetQtyFlag = 'y';
            if side == "B" then
                valuemap.BuySell = "S";
                rate = instance.ask[NOW] - Stop * PipSize;
                valuemap.Rate = rate;
            elseif side == "S" then
                valuemap.BuySell = "B";
                rate = instance.bid[NOW] + Stop * PipSize;
                valuemap.Rate = rate;
            end
            if TrailingStop then
                valuemap.TrailUpdatePips = 1
            end
            success, msg = terminal:execute(200, valuemap);
            --core.host:trace('Set stop @ ' .. rate);
            assert(success, msg);
        end
        if SetLimit then
            valuemap = core.valuemap();
            valuemap.OrderType = "LE"
            valuemap.OfferID = Offer;
            valuemap.AcctID = Account;
            valuemap.NetQtyFlag = 'y';
            if side == "B" then
                valuemap.BuySell = "S";
                rate = instance.ask[NOW] + Limit * PipSize;
                valuemap.Rate = rate;
            elseif side == "S" then
                valuemap.BuySell = "B";
                rate = instance.bid[NOW] - Limit * PipSize;
                valuemap.Rate = rate;
            end
            success, msg = terminal:execute(200, valuemap);
            --core.host:trace('Set limit @ ' .. rate);
            assert(success, msg);
        end
    end
end

function BB_Touch(Band,period)
 local period_=period;
 while period_>Source:first() and period-period_<=instance.parameters.MaxDistance do
  if Band=="U" and Source.high[period_]>=BB.TL[period_] then
   return true;
  elseif Band=="L" and Source.low[period_]<=BB.BL[period_] then
   return true;
  end
  period_=period_-1;
 end
 return false;
end

-- Closes specific position
function Close(trade)
    local valuemap;
    valuemap = core.valuemap();

    if CanClose then
        -- non-FIFO account, create a close market order
        valuemap.OrderType = "CM";
        valuemap.TradeID = trade.TradeID;
    else
        -- FIFO account, create an opposite market order
        valuemap.OrderType = "OM";
    end

    valuemap.OfferID = trade.OfferID;
    valuemap.AcctID = trade.AccountID;
    valuemap.Quantity = trade.Lot;
    valuemap.CustomID = trade.QTXT;
    if trade.BS == "B" then valuemap.BuySell = "S"; else valuemap.BuySell = "B"; end
    success, msg = terminal:execute(200, valuemap);
    assert(success, msg);
end

function AsyncOperationFinished(cookie, successful, message)
  if not successful then
    core.host:trace('Error: ' .. message)
  end
end

dofile(core.app_path() .. "\\strategies\\standard\\include\\helper.lua");

Code: Select all
    ...
    success, msg = terminal:execute(200, valuemap);
    ...
    -- FIFO Account, in that case we have to open Net Limit and Stop Orders
    if not(CanClose) then
        if SetStop then
            ...
            success, msg = terminal:execute(200, valuemap);
            ...
        end
        if SetLimit then
            ...
            success, msg = terminal:execute(200, valuemap);
            ...
        end
    end

Don't use the same if of the command for these commands. Changing command id for the limit will fix the problem
Code: Select all
    ...
    success, msg = terminal:execute(200, valuemap);
    ...
        if SetStop then
            ...
            success, msg = terminal:execute(201, valuemap);
            ...
        end
        if SetLimit then
            ...
            success, msg = terminal:execute(202, valuemap);
            ...
        end
“There are only three sports: bullfighting, motor racing, and mountaineering; all the rest are merely games.” (c) Ernest Hemingway
Victor.Tereschenko
FXCodeBase: Confirmed User
 
Posts: 144
Joined: Fri Nov 19, 2010 8:55 am

Re: Stochastic&Bands strategy

Postby Alexander.Gettinger » Tue Apr 30, 2019 9:44 pm

Please try this strategy:
Stochastic_Bands_Strategy.lua
(13.1 KiB) Downloaded 636 times
Alexander.Gettinger
FXCodeBase: Confirmed User
 
Posts: 3785
Joined: Wed Mar 31, 2010 9:40 pm
Location: Russia, Omsk

Re: Stochastic&Bands strategy

Postby loleke5125 » Wed Dec 07, 2022 5:06 am

Alexander.Gettinger wrote:Please try this strategy:
Stochastic_Bands_Strategy.lua



can we convert lua to mql4 ? i see most of the files here are lua format.
loleke5125
 
Posts: 7
Joined: Wed Dec 07, 2022 4:53 am

Re: Stochastic&Bands strategy

Postby Apprentice » Thu Dec 08, 2022 9:32 am

We have added your request to the development list.
Development reference 810.
User avatar
Apprentice
FXCodeBase: Confirmed User
 
Posts: 36341
Joined: Thu Dec 31, 2009 11:59 am
Location: Zagreb, Croatia


Previous

Return to Indicator Development

Who is online

Users browsing this forum: Bing [Bot] and 6 guests