Page 1 of 1

Backtesting - Period Problem

Posted: Tue Oct 13, 2020 11:55 am
by herac
Hi guys,

Does anyone know why my strategy scripts are not executing on some historical data? For example, I can backtest my strategy on all of the available daily bars within FX pairs/crypto, but when I try to backtest the same strategy, for example, on SP:SPX or TVC:GOLD it does not work as it should. In the SPX I get data from all the beginning 1879 but it stops working at the end of 2009, it is not coded into my script so I do not understand.

Thanks,
Simon

PS: Here is the strategy script I want to backtest.

Code: Select all

// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © SystemFollower

//@version=4
strategy("Final - Conqueror L", shorttitle="Final S4/L", overlay = true, default_qty_type = strategy.percent_of_equity, default_qty_value = 1)

// //INPUTS
// Backtesting range
from_month  = input(defval = 1,       title = "From Month",      type = input.integer, minval = 1, maxval = 12)
from_day    = input(defval = 1,       title = "From Day",        type = input.integer, minval = 1, maxval = 31)
from_year   = input(defval = 2010,    title = "From Year",       type = input.integer, minval = 1600)
thru_month  = input(defval = 1,       title = "Thru Month",      type = input.integer, minval = 1, maxval = 12)
thru_day    = input(defval = 1,       title = "Thru Day",        type = input.integer, minval = 1, maxval = 31)
thru_year   = input(defval = 2020,    title = "Thru Year",       type = input.integer, minval = 1610)

entry_time  = input('0000-0000',      title = "Entry Time",      type = input.session)  
exit_time   = input('0000-0000',      title = "Exit Time",       type = input.session)

// Conqueror
ma_type = input(title = "MA Type", type = input.string, defval = "SMA", options = ["SMA", "EMA"])
ma_length = input(title="Length -MA", type = input.integer, defval = 10, minval=1)
ma_source = input(title="Source - MA", type = input.source, defval = close)
ma_previous_period = input(title = "MA x days back", type = input.integer, defval = 10)
close_previous_period = input(title = "Close of -x day", type = input.integer, defval = 40)

// ATR

atr_length = input(title = "ATR Length", type = input.integer, defval = 14, minval = 1)
trail_stop = input(title = "Use Trailing Stop?", type = input.bool, defval = true)
atr_mult = input(title = "ATR multiple?", type = input.float, defval = 2.0)
longs = input(title = "Long trades", type = input.bool, defval = true)


// //Calculations
// Backtesting Range
is_date() =>                                                      
    start  = timestamp(from_year, from_month, from_day, 00, 00)     
    finish = timestamp(thru_year, thru_month, thru_day, 23, 59)     
    is_date = time >= start and time <= finish                    

is_time(_position) =>                                             
    range  = time(timeframe.period, _position + ':1234567')  

// Conqueror
ma = ma_type == "SMA" ? sma(ma_source, ma_length) : ema(ma_source, ma_length)
ma_previous = ma[ma_previous_period]
close_previous = close[close_previous_period]
long_signal = close >= ma and ma >= ma_previous and close >= close_previous

two_conditions = (close >= ma and ma >= ma_previous and close < close_previous) or 
 (close >= ma and ma < ma_previous and close >= close_previous) or 
 (close < ma and ma >= ma_previous and close >= close_previous) 

one_condition = (close >= ma and ma < ma_previous and close < close_previous) or 
 (close < ma and ma < ma_previous and close >= close_previous) or 
 (close < ma and ma >= ma_previous and close < close_previous)

sl_val = atr_mult * atr(atr_length)
atr = atr(atr_length)

longStop = close - sl_val
var longStopSaved = 0.0
var longTrailSaved = 0.0
var longEntrySaved = 0.0
var longTrailSaved2 = 0.0
if long_signal and strategy.position_size == 0
    longStopSaved := longStop
    longEntrySaved := close

var higher_close = 0.0
if strategy.position_size > 0 or strategy.position_size == 0
    higher_close := strategy.position_size > 0 ? close > longEntrySaved ? max(close, higher_close) : max(higher_close, longEntrySaved): close


roundtick(x) => 
    round(x / syminfo.mintick) * syminfo.mintick
    
var initial_stop = 0.0
if strategy.position_size == 0 and long_signal
    initial_stop := close - sl_val

var trailing_sl_from_close = 0.0
if strategy.position_size == 0 or strategy.position_size > 0
    trailing_sl_from_close := long_signal and strategy.position_size == 0 ? initial_stop : long_signal ? higher_close - sl_val : two_conditions ? higher_close - atr * 4/3 : one_condition ? higher_close - atr * 2/3: close

stops_total = long_signal and strategy.position_size == 0 ? roundtick(initial_stop) : roundtick(trailing_sl_from_close)

// // PLOT

plot(ma, color=color.blue, title="SMA - 4", offset=0)
plot(ma_previous, transp = 30, style = plot.style_line, linewidth = 1, trackprice = true, offset = -9999, color = color.green, title = "MA x days back", display = display.all ) 
plot(close_previous, transp = 30, style = plot.style_line, linewidth = 1, trackprice = true, offset = -9999, color = color.aqua, title = "Close of -x Day") 
plotshape(long_signal, style=shape.triangleup, location=location.abovebar, color=color.green, title = "Long Conditions -> 4", transp = 0) 

// // Strategy 
strategy.entry(id = "Long", long = strategy.long, when = is_date() and is_time(entry_time) and long_signal and long_signal[1] != true and strategy.position_size == 0)

strategy.exit(id = "Long Exit", from_entry = "Long", when = is_date() and is_time(exit_time), stop = stops_total)

plot(strategy.position_size > 0 ? roundtick(trailing_sl_from_close) : strategy.position_size > 0 or (long_signal and long_signal[1]!= true and strategy.position_size == 0) ? roundtick(stops_total): na, color = color.red, style = plot.style_linebr)

Re: Backtesting - Period Problem

Posted: Fri Oct 16, 2020 5:18 am
by Matthew
Hmm that's an interesting issue herac, I'll look into it over the weekend if I get time. It's difficult to be able to guess what might be causing that without playing around with the code a fair bit. At first glance I can't see what would cause that to happen :concerned: