Rules:
1) The strategy enters long when RB Clear indicator switches up.
2) The strategy enters short when RB Clear indicator switches down.
3) The strategy closes all opposite positions first.
Options:
1) The strategy can show signals (alerts, sounds (including recurrent), emails) as well as can trade. By default trading is disabled. To let the strategy trade please go to the "Trading Parameters" and switch "Allow strategy to trade" parameter to "Yes".
2) In trading parameters you can also switch on and configure stop and limit orders.
Please, do not forget to download and install the Ron Black's Clear Method indicator (rb_clear.lua).
Download strategy:
- Code: Select all
function Init()
strategy:name("Clear Method Strategy");
strategy:description("Signals when Ron Black's clear method indicator changes direction");
strategy.parameters:addGroup("Price Parameters");
strategy.parameters:addString("Type", "Price type", "", "Bid");
strategy.parameters:addStringAlternative("Type", "Bid", "", "Bid");
strategy.parameters:addStringAlternative("Type", "Ask", "", "Ask");
strategy.parameters:addString("TF", "Timeframe", "", "m1");
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
-- Internal Parameters
local source = nil;
local clear;
-- Signal Parameters
local ShowAlert;
local SoundFile;
local RecurrentSound;
local SendEmail, Email;
-- 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()
assert(core.indicators:findIndicator("RB_CLEAR") ~= nil, "The RB_CLEAR.LUA indicator must be downloaded and installed");
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 (PlaySound and SoundFile ~= ""), "Sound file must be specified");
RecurrentSound = instance.parameters.Recurrent;
SendEmail = instance.parameters.SendEmail;
if SendEmail then
Email = instance.parameters.Email;
else
Email = nil;
end
assert(not(SendEmail) or (SendEmail and 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:instrument() .. "[" .. 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, instance.parameters.Type == "Bid", "bar");
clear = core.indicators:create("RB_CLEAR", source);
ExtSetupSignal(name .. ":", ShowAlert);
ExtSetupSignalMail(name);
end
function ExtUpdate(id, source, period)
clear:update(core.UpdateLast);
-- Check that we have enough data
if (clear.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 MustB=false;
local MustS=false;
-- if clear.Up:hasData(period) and clear.Dn:hasData(period - 1) then
-- ExtSignal(instance.bid, instance.bid:size() - 1, "Swing Up", SoundFile, Email);
-- elseif clear.Dn:hasData(period) and clear.Up:hasData(period - 1) then
-- ExtSignal(instance.bid, instance.bid:size() - 1, "Swing Down", SoundFile, Email);
-- end
if clear.Dn:hasData(period) and clear.Up:hasData(period - 1) then
-- if instance.parameters.TypeSignal=="direct" then
MustS=true;
-- else
-- MustB=true;
-- end
end
if clear.Up:hasData(period) and clear.Dn:hasData(period - 1) then
-- if instance.parameters.TypeSignal=="direct" then
MustB=true;
-- else
-- MustS=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 MustS==true then
if ShowAlert then
if AllowDirection~="Long" then
ExtSignal(source, period, "Close BUY and SELL", SoundFile, Email, RecurrentSound);
else
ExtSignal(source, period, "Close BUY", SoundFile, Email, RecurrentSound);
end
end
if AllowTrade then
Close(row);
if AllowDirection~="Long" then
Open("S")
end
end
end
elseif row.BS == 'S' then
if MustB==true then
if ShowAlert then
if AllowDirection~="Short" then
ExtSignal(source, period, "Close SELL and BUY", SoundFile, Email, RecurrentSound);
else
ExtSignal(source, period, "Close SELL", SoundFile, Email, RecurrentSound);
end
end
if AllowTrade then
Close(row);
if AllowDirection~="Short" then
Open("B")
end
end
end
end
end
end
else
if MustB==true then
if ShowAlert and AllowDirection~="Short" then
ExtSignal(source, period, "BUY", SoundFile, Email, RecurrentSound)
if AllowTrade then
Open("B")
end
end
end
if MustS==true then
if ShowAlert and AllowDirection~="Long" then
ExtSignal(source, period, "SELL", SoundFile, Email, RecurrentSound)
if AllowTrade then
Open("S")
end
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
-- 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");
The Strategy was revised and updated on December 09, 2018.