You could switch this to minutely data and give it a whirl:
import numpy
trailingStopPeriods = 10
stdMultiplier = 5.0
periodsToConsider = 4
minimumPercentThreshold = .01
trailingStops = {}
def initialize(context):
context.stocks = symbols("XLB","XLE","XLF","XLI","XLK","XLP","XLU","XLV","XLY","AGG")
for stock in context.stocks:
trailingStops[stock] = None
set_benchmark(symbol('SPY'))
set_commission(commission.PerTrade(cost=1.0))
set_slippage(TradeAtTheOpenSlippageModel(.1))
def handle_data(context, data):
historic = {}
historic["low"] = history(trailingStopPeriods, "1d", "low")
historic["close"] = history(trailingStopPeriods, "1d", "close_price")
prices = history(periodsToConsider + 1, '1d', 'close_price')
# Clean up the stocks that have missing prices
prices = prices.dropna(axis=1)
# Construct period over period returns
returns = prices / prices.shift(1) - 1
returns = returns.dropna()
eligibleStocks = []
inEligibleStocks = []
for stock in context.stocks:
if (not data[stock]):
continue
# Set the stop - will be used to exit as needed
SetTrailingStop(context, stock, historic)
# Position retained - stop loss set and untriggered
if (trailingStops[stock]):
eligibleStocks.append(stock)
# Entry - if all of the returns are positive and total return is > threshold
if (not any(returnVal < 0 for returnVal in returns[stock]) and sum(returns[stock]) >= minimumPercentThreshold):
if (not stock in eligibleStocks):
eligibleStocks.append(stock)
# Exits
if (not stock in eligibleStocks):
inEligibleStocks.append(stock)
for stock in inEligibleStocks:
order_target_percent(stock, 0)
if (eligibleStocks):
eligibleFraction = 1.0 / float(len(eligibleStocks))
for stock in eligibleStocks:
order_target_percent(stock, eligibleFraction)
if (trailingStops[context.stocks[0]]):
record(price = prices[context.stocks[0]].iloc[-1], stop=trailingStops[context.stocks[0]])
def SetTrailingStop(context, stock, historic):
# Use the standard deviation of the close to buffer the trailing stop
std = numpy.std(historic["close"][stock]) * stdMultiplier
# Process for exit: low is less than the trailing stop price?
if (context.portfolio.positions[stock].amount):
if (historic["low"][stock][-1] < trailingStops[stock]):
trailingStops[stock] = None
else:
trailingStops[stock] = max(trailingStops[stock], historic["low"][stock][-1] - std)
########################################################
class TradeAtTheOpenSlippageModel(slippage.SlippageModel):
def __init__(this, fractionOfOpenCloseRange):
this.fractionOfOpenCloseRange = fractionOfOpenCloseRange
def process_order(this, trade_bar, order):
openPrice = trade_bar.open_price
closePrice = trade_bar.price
ocRange = closePrice - openPrice
ocRange = ocRange * this.fractionOfOpenCloseRange
targetExecutionPrice = openPrice + ocRange
return slippage.create_transaction(trade_bar, order, targetExecutionPrice, order.amount)