I will explain a bit what I want do with in my strategy... It's really simple.
When the price in over the pivot point of yesterday in D1, and the k line of stochastic crosses over the D line of stochastic then buy. If the price in under the pivot point and the k line of stochastic crosses under the D line then sell.
I want to use it on a different timeframe that it.
Thank you in advance.
- Code: Select all
-- Strategy profile initialization routine
-- Defines Strategy profile properties and Strategy parameters
-- TODO: Add minimal and maximal value of numeric parameters and default color of the streams
function Init()
strategy:name("PivotStochatic");
strategy:description("Pivot + stochatic ");
strategy:type(core.Both);
strategy:setTag("NonOptimizableParameters", "SendEmail,PlaySound,Email,SoundFile,RecurrentSound,ShowAlert");
strategy.parameters:addGroup("Price Parameters");
strategy.parameters:addString("TF", "Time frame ('t1', 'm1', 'm5', etc.)", "", "m5");
strategy.parameters:setFlag("TF", core.FLAG_PERIODS);
strategy.parameters:addGroup("Parameters");
strategy.parameters:addInteger("KPeriods", "%K periods", "No description", 5);
strategy.parameters:addInteger("DSlowingPeriods", "%D slowing periods", "No description", 3);
strategy.parameters:addInteger("DPeriods", "%D Periods", "No description", 3);
strategy.parameters:addGroup("Trading Parameters");
strategy.parameters:addBoolean("AllowTrade", "Allow strategy to trade", "", false);
strategy.parameters:setFlag("AllowTrade", core.FLAG_ALLOW_TRADE);
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:addGroup("Notification");
strategy.parameters:addBoolean("ShowAlert", "Show Alert", "", true);
strategy.parameters:addBoolean("PlaySound", "Play Sound", "", false);
strategy.parameters:addBoolean("RecurrentSound", "Recurrent Sound", "", false);
strategy.parameters:addFile("SoundFile", "Sound File", "", "");
strategy.parameters:setFlag("SoundFile", core.FLAG_SOUND);
strategy.parameters:addBoolean("SendEmail", "Send Email", "", false);
strategy.parameters:addString("Email", "Email", "", "");
strategy.parameters:setFlag("Email", core.FLAG_EMAIL);
end
-- strategy instance initialization routine
-- Processes strategy parameters and creates output streams
-- TODO: Calculate all constants, create instances all necessary indicators and load all required libraries
-- Parameters block
local KPeriods;
local DSlowingPeriods;
local DPeriods;
local gSource = nil; -- the source stream
local PlaySound;
local RecurrentSound;
local SoundFile;
local Email;
local SendEmail;
local AllowTrade;
local Account;
local Amount;
local BaseSize;
local SetLimit;
local Limit;
local SetStop;
local Stop;
local TrailingStop;
local Offer;
local CanClose;
--TODO: Add variable(s) for your indicator(s) if needed
local iSLowStoch;
-- Routine
function Prepare(nameOnly)
KPeriods = instance.parameters.KPeriods;
DSlowingPeriods = instance.parameters.DSlowingPeriods;
DPeriods = instance.parameters.DPeriods;
Period=instance.parameters.Period;
Method=instance.parameters.Method;
Filter1=instance.parameters.Filter1;
Filter2=instance.parameters.Filter2;
assert(instance.parameters.PivotTF ~= "t1", "The pivot time frame must not be tick");
if nameOnly then
return ;
end
PivotSource = ExtSubscribe(1, nil, instance.parameters.PivotTF, instance.parameters.Type == "Bid", "bar");
PipSize = PivotSource.close:pipSize();
local name = profile:id() .. "(" .. instance.bid:instrument() .. ", " .. tostring(KPeriods) .. ", " .. tostring(DSlowingPeriods) .. ", " .. tostring(DPeriods) .. ")";
instance:name(name);
if nameOnly then
return ;
end
ShowAlert = instance.parameters.ShowAlert;
PlaySound = instance.parameters.PlaySound;
if PlaySound then
RecurrentSound = instance.parameters.RecurrentSound;
SoundFile = instance.parameters.SoundFile;
else
SoundFile = nil;
end
assert(not(PlaySound) or (PlaySound and SoundFile ~= ""), "Sound file must be specified");
SendEmail = instance.parameters.SendEmail;
if SendEmail then
Email = instance.parameters.Email;
else
Email = nil;
end
assert(not(SendEmail) or (SendEmail and Email ~= ""), "E-mail address must be specified");
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);
SetLimit = instance.parameters.SetLimit;
Limit = instance.parameters.Limit * instance.bid:pipSize();
SetStop = instance.parameters.SetStop;
Stop = instance.parameters.Stop * instance.bid:pipSize();
TrailingStop = instance.parameters.TrailingStop;
end
gSource = ExtSubscribe(1, nil, instance.parameters.TF, instance.parameters.Type == "Bid", "bar");
--TODO: Find indicator's profile, intialize parameters, and create indicator's instance (if needed)
iSLowStoch = core.indicators:create("SSD",gSource , KPeriods, DSlowingPeriods, DPeriods)
end
function UpdateStream(period)
CalcLevels(PivotSource, period);
end
-- strategy calculation routine
-- TODO: Add your code for decision making
-- TODO: Update the instance of your indicator(s) if needed
function CalcLevels(ref, period)
if (period - 1 < ref:first()) then
-- not enough data
return;
end
if (ref:serial(period) == INDEX) then
-- already calculated;
return;
end
-- if we are daily or less, ignore saturdays.
if (ref:barSize() ~= "M1" and ref:barSize() ~= "W1") then
local theDate = core.dateToTable(ref:date(period));
if (theDate.wday == 7) then
-- need to ignore saturday's or it messes up the pivots.
return;
end
end
local prev_i = period;
INDEX = ref:serial(period);
P = (ref.high[prev_i] + ref.close[prev_i] + ref.low[prev_i]) / 3;
end
function ExtUpdate(id, source, period)
iSLowStoch:update(core.UpdateLast)
if core.crossesOver(iSlowStoch.k, iSlowStoch.D, period) and p > gSource.close[period] then
--BUY SIGNAL
end
if core.crossesUnder(iSlowStoch.k, iSlowStoch.D, period) and p < gSource.close[period]then
--SELL SIGNAL
end
end
--===========================================================================--
-- TRADING UTILITY FUNCTIONS --
--============================================================================--
function BUY()
if AllowTrade then
if CloseOnOpposite and haveTrades("S") then
-- close on opposite signal
exitSpecific("S");
Signal ("Close Short");
end
if ALLOWEDSIDE == "Sell" then
-- we are not allowed buys.
return;
end
enter("B");
else
Signal ("Buy Signal");
end
end
function SELL ()
if AllowTrade then
if CloseOnOpposite and haveTrades("B") then
-- close on opposite signal
exitSpecific("B");
Signal ("Close Long");
end
if ALLOWEDSIDE == "Buy" then
-- we are not allowed sells.
return;
end
enter("S");
else
Signal ("Sell Signal");
end
end
function Signal (Label)
if ShowAlert then
terminal:alertMessage(instance.bid:instrument(), instance.bid[NOW], Label, instance.bid:date(NOW));
end
if SoundFile ~= nil then
terminal:alertSound(SoundFile, RecurrentSound);
end
if Email ~= nil then
terminal:alertEmail(Email, Label, profile:id() .. "(" .. instance.bid:instrument() .. ")" .. instance.bid[NOW]..", " .. Label..", " .. instance.bid:date(NOW));
end
end
function checkReady(table)
local rc;
if Account == "TESTACC_ID" then
-- run under debugger/simulator
rc = true;
else
rc = core.host:execute("isTableFilled", table);
end
return rc;
end
function tradesCount(BuySell)
local enum, row;
local count = 0;
enum = core.host:findTable("trades"):enumerator();
row = enum:next();
while row ~= nil do
if row.AccountID == Account and row.OfferID == Offer and row.QTXT == CustomID and (row.BS == BuySell or BuySell == nil) then
count = count + 1;
end
row = enum:next();
end
return count;
end
function haveTrades(BuySell)
local enum, row;
local found = false;
enum = core.host:findTable("trades"):enumerator();
row = enum:next();
while (row ~= nil) do
if row.AccountID == Account and row.OfferID == Offer and row.QTXT == CustomID and (row.BS == BuySell or BuySell == nil) then
found = true;
break;
end
row = enum:next();
end
return found;
end
-- enter into the specified direction
function enter(BuySell)
-- do not enter if position in the specified direction already exists
if (tradesCount(BuySell) >= MaxNumberOfPosition
or (tradesCount(nil) >= MaxNumberOfPositionInAnyDirection))
and PositionCap
then
return true;
end
-- send the alert after the checks to see if we can trade.
if (BuySell == "S") then
Signal ("Sell Signal");
else
Signal ("Buy Signal");
end
return MarketOrder(BuySell);
end
-- enter into the specified direction
function MarketOrder(BuySell)
local valuemap, success, msg;
valuemap = core.valuemap();
valuemap.Command = "CreateOrder";
valuemap.OrderType = "OM";
valuemap.OfferID = Offer;
valuemap.AcctID = Account;
valuemap.Quantity = Amount * BaseSize;
valuemap.BuySell = BuySell;
valuemap.CustomID = CustomID;
-- add stop/limit
valuemap.PegTypeStop = "O";
if SetStop then
if BuySell == "B" then
valuemap.PegPriceOffsetPipsStop = -Stop;
else
valuemap.PegPriceOffsetPipsStop = Stop;
end
end
if TrailingStop then
valuemap.TrailStepStop = 1;
end
valuemap.PegTypeLimit = "O";
if SetLimit then
if BuySell == "B" then
valuemap.PegPriceOffsetPipsLimit = Limit;
else
valuemap.PegPriceOffsetPipsLimit = -Limit;
end
end
if (not CanClose) then
valuemap.EntryLimitStop = 'Y'
end
success, msg = terminal:execute(200, valuemap);
if not(success) then
terminal:alertMessage(instance.bid:instrument(), instance.bid[instance.bid:size() - 1], "Open order failed" .. msg, instance.bid:date(instance.bid:size() - 1));
return false;
end
return true;
end
-- exit from the specified trade using the direction as a key
function exitSpecific(BuySell)
-- we have to loop through to exit all trades in each direction instead
-- of using the net qty flag because we may be running multiple strategies on the same account.
local enum, row;
local found = false;
enum = core.host:findTable("trades"):enumerator();
row = enum:next();
while (not found) and (row ~= nil) do
-- for every trade for this instance.
if row.AccountID == Account and row.OfferID == Offer and row.QTXT == CustomID and (row.BS == BuySell or BuySell == nil) then
exitTrade(row);
end
row = enum:next();
end
end
-- exit from the specified direction
function exitTrade(tradeRow)
if not(AllowTrade) then
return true;
end
local valuemap, success, msg;
valuemap = core.valuemap();
-- switch the direction since the order must be in oppsite direction
if tradeRow.BS == "B" then
BuySell = "S";
else
BuySell = "B";
end
valuemap.OrderType = "CM";
valuemap.OfferID = Offer;
valuemap.AcctID = Account;
if (CanClose) then
-- Non-FIFO can close each trade independantly.
valuemap.TradeID = tradeRow.TradeID;
valuemap.Quantity = tradeRow.Lot;
else
-- FIFO.
valuemap.NetQtyFlag = "Y"; -- this forces all trades to close in the opposite direction.
end
valuemap.BuySell = BuySell;
valuemap.CustomID = CustomID;
success, msg = terminal:execute(201, valuemap);
if not(success) then
terminal:alertMessage(instance.bid:instrument(), instance.bid[instance.bid:size() - 1], "Close order failed" .. msg, instance.bid:date(instance.bid:size() - 1));
return false;
end
return true;
end
dofile(core.app_path() .. "\\strategies\\standard\\include\\helper.lua");