# Mean reversion Spread Trading with Linear Regression
#
# Deniz Turan, (denizstij AT gmail DOT com), 19-Jan-2014
import numpy as np
from scipy.stats import linregress
R_P = 1 # refresh period in days
W_L = 30 # window length in days
def initialize(context):
context.y=sid(14517) # EWC
context.x=sid(14516) # EWA
# for long and shorting
context.max_notional = 1000000
context.min_notional = -1000000.0
# set a fixed slippage
set_slippage(slippage.FixedSlippage(spread=0.01))
context.long=False;
context.short=False;
def handle_data(context, data):
xpx=data[context.x].price
ypx=data[context.y].price
retVal=linearRegression(data,context)
# lets dont do anything if we dont have enough data yet
if retVal is None:
return None
hedgeRatio,intercept=retVal;
spread=ypx-hedgeRatio*xpx
data[context.y]['spread'] = spread
record(ypx=ypx,spread=spread,xpx=xpx)
# find moving average
rVal=getMeanStd(data, context)
# lets dont do anything if we dont have enough data yet
if rVal is None:
return
meanSpread,stdSpread = rVal
# zScore is the number of unit
zScore=(spread-meanSpread)/stdSpread;
QTY=1000
qtyX=-hedgeRatio*QTY*xpx;
qtyY=QTY*ypx;
entryZscore=1;
exitZscore=0;
if zScore < -entryZscore and canEnterLong(context):
# enter long the spread
order(context.y, qtyY)
order(context.x, qtyX)
context.long=True
context.short=False
if zScore > entryZscore and canEnterShort(context):
# enter short the spread
order(context.y, -qtyY)
order(context.x, -qtyX)
context.short=True
context.long=False
record(cash=context.portfolio.cash, stock=context.portfolio.positions_value)
@batch_transform(window_length=W_L, refresh_period=R_P)
def linearRegression(datapanel, context):
xpx = datapanel['price'][context.x]
ypx = datapanel['price'][context.y]
beta, intercept, r, p, stderr = linregress(ypx, xpx)
# record(beta=beta, intercept=intercept)
return (beta, intercept)
@batch_transform(window_length=W_L, refresh_period=R_P)
def getMeanStd(datapanel, context):
spread = datapanel['spread'][context.y]
meanSpread=spread.mean()
stdSpread=spread.std()
if meanSpread is not None and stdSpread is not None :
return (meanSpread, stdSpread)
else:
return None
def canEnterLong(context):
notional=context.portfolio.positions_value
if notional < context.max_notional and not context.long: # and not context.short:
return True
else:
return False
def canEnterShort(context):
notional=context.portfolio.positions_value
if notional > context.max_notional and not context.short: #and not context.short:
return True
else:
return False
Showing posts with label Bollinger Band. Show all posts
Showing posts with label Bollinger Band. Show all posts
Sunday, January 19, 2014
Mean reversion with Linear Regression and Bollinger Band for Spread Trading within Python
Following code demonstrates how to utilize to linear regression to estimate hedge ratio and Bollinger band for spread trading. The code can be back tested at Quantopian.com
Monday, November 18, 2013
Simple Passive Momentum Trading with Bollinger Band
Below, you can see a simple trading algorithm based on momentum and bollinger band on Quantopian.com
# Simple Passive Momentum Trading with Bollinger Band
import numpy as np
import statsmodels.api as stat
import statsmodels.tsa.stattools as ts
# globals for batch transform decorator
R_P = 1 # refresh period in days
W_L = 30 # window length in days
lookback=22
def initialize(context):
context.stock = sid(24) # Apple (ignoring look-ahead bias)
# for long and shorting
context.max_notional = 1000000
context.min_notional = -1000000.0
# set a fixed slippage
set_slippage(slippage.FixedSlippage(spread=0.01))
def handle_data(context, data):
# find moving average
rVal=getMeanStd(data)
# lets dont do anything if we dont have enough data yet
if rVal is None:
return
meanPrice,stdPrice = rVal
price=data[context.stock].price
notional = context.portfolio.positions[context.stock].amount * price
# Passive momentum trading where for trading signal, Z-score is estimated
h=((price-meanPrice)/stdPrice)
# Bollinger band, if price is out of 2 std of moving mean, than lets trade
if h>2 and notional < context.max_notional :
# long
order(context.stock,h*1000)
if h<-2 and notional > context.min_notional:
# short
order(context.stock,h*1000)
@batch_transform(window_length=W_L, refresh_period=R_P)
def getMeanStd(datapanel):
prices = datapanel['price']
meanPrice=prices.mean()
stdPrice=prices.std()
if meanPrice is not None and stdPrice is not None :
return (meanPrice, stdPrice)
else:
return None
Screen shot of the back testing result is:
Click here to run algorithm on Quantopian.com.
Labels:
Algorithmic Trading,
Bollinger Band,
finance,
Momentum Trading,
Python,
Trading
Subscribe to:
Posts (Atom)
