Hello!
Please find below a stripped down version of my algo. I have removed the indicator and replaced with a simple rule that buys the market when a new low occurs over the last n days. It then holds the long for n/2 days.
The parameter "context.order" is a factor used to push backwards the time frame that is being scanned for the minimum prices, by "context.cycle" days. The time frame window is itself "context.cycle" length days. So when order==1 the window gets pushed back 1*context.cycle. When order ==2 it gets pushed back 2*context.cycle days etc...
In each of the loops there are outputs which are then used in the trade logic. So for instance if the price infringes the buy indicator line but does not generate a buy signal, no buy signals are allowable for a certain number of days.
The reason I want to loop through all the parameters is that they all independently generate decent returns and sharp ratios.
The parameters that I would like to loop through using "for" are context.order and context.stock.
My problem is keeping track of the outputs used in the trade logic for each parameter and stock.
It works perfectly for a single stock, with a single parameter set. But when i try and increase either stocks or parameter sets, the results are not as expected - which tells me that outputs are being mixed up.
I know my code is very nasty and procedural but is the best I can do! Any hints tips appreciated
:-)
#This algo goes long when a new n days low is made and holds for n/2 days.
import math # This will import math module
# Setup our variables
import pandas as pd
import numpy as np
def initialize(context):
set_commission(commission.PerShare(cost=0.005, min_trade_cost=1))
set_slippage(slippage.VolumeShareSlippage(volume_limit=0.025,price_impact=0.1))
context.stocks = [symbol('SPY')]
context.signal_type = 0
context.days_elapsed = 0
context.cycle=int(11)
context.order=[1]
# context.order=[1,2,3,4,5]
context.days_held=6
context.order1_infringe_counter = 0
context.signal_current = 0
schedule_function(
orderlogic,
date_rules.every_day(),
time_rules.market_close(hours=0, minutes=1)
)
def orderlogic(context, data):
for stock in context.stocks:
for order in context.order:
context.signal_current = 0
zfrac = 4
price_high = data.history(stock,"high",2*context.cycle, "1d")
price_low = data.history(stock,"low",2*context.cycle, "1d")
#if the price infringes the buy indicator line but does not generate a signal dont do any trades for days_held days.
#order 1
if context.order1_infringe_counter> 0:
context.order1_infringe_counter -=1
else:
context.order1_infringe_counter = 0
#indicator t+0
max = price_high.rolling(order*context.cycle
).max().shift(1+int(round(order*zfrac)))
min = price_low.rolling(order*context.cycle
).max().shift(1+int(round(order*zfrac)))
lower_band = min[-1]
upper_band = max[-1]
#rolling_price_min is used to see if the current low is a low in the recent period
rolling_price_min = price_low.rolling(context.days_held).min().shift(1)
low_price = data.history(stock,'low',2,"1d")
low_price_yest = data.history(stock,'low',2,"1d")[:-1]
#this counter is incremented each day, if there is a position. The coubnter is used later to decide if the position should be closed
if len(context.portfolio.positions) > 0:
context.days_elapsed += 1
#Order 1 loop trading logic
#has the order 1 band been infringed in last 1/2 cycle days?
if context.order1_infringe_counter==0:
#current
if low_price[-1] <= lower_band and low_price_yest[-1] > lower_band:
if len(context.portfolio.positions) == 0:
counter = len(context.portfolio.positions)
order_target_percent(stock, 1)
context.signal_current=1
print('BUYING Ord 1 current')
context.days_elapsed = 0
else:
pass
#Order 1
#if the price infringes a band and doesn't generate a signal, veto trading
if order == 1:
if low_price[-1] <= lower_band and context.signal_current != 1:
context.order1_infringe_counter=context.days_held
#exit positions half a cycle after they were initiated
if context.days_elapsed == context.days_held:
order_target_percent(stock, 0)
print('closing')
context.days_elapsed = 0
#printing stuff
print("low price: "+str(low_price[-1]))
print("low_price_yest: "+str(low_price_yest[-1]))
print("lower_band: "+str(lower_band))
print("days_elapsed: "+str(context.days_elapsed))
print("infringe counter: "+str(context.order1_infringe_counter))
#displaying stuff in panel
record(lower=lower_band,
low_price=low_price[-1])