# Mean reversion with Kalman Filter as Dynamic Linear Regression # # Following algorithm trades based on mean reversion logic of spread # between cointegrated securities by using Kalman Filter as # Dynamic Linear Regression. Kalman filter is used here to estimate hedge (beta) # # Kalman Filter structure # # - measurement equation (linear regression): # y= beta*x+err # err is a guassian noise # # - Prediction model: # beta(t) = beta(t-1) + w(t-1) # w is a guassian noise # Beta is here our hedge unit. # # - Prediction section # beta_hat(t|t-1)=beta_hat(t-1|t-1) # beta_hat is expected value of beta # P(t|t-1)=P(t-1|t-1) + V_w # prediction error, which is cov(beta-beta_hat) # y_hat(t)=beta_hat(t|t-1)*x(t) # measurement prediction # err(t)=y(t)-y_hat(t) # forecast error # Q(t)=x(t)'*P(t|t-1)*x(t) + V_e # variance of forecast error, var(err(t)) # # - Update section # K(t)=R(t|t-1)*x(t)/Q(t) # Kalman filter between 0 and 1 # beta_hat(t|t)=beta_hat(t|t-1)+ K*err(t) # State update # P(t|t)=P(t|t-1)(1-K*x(t)) # State covariance update # # Deniz Turan, (denizstij AT gmail DOT com), 19-Jan-2014 # import numpy as np # Initialization logic def initialize(context): context.x=sid(14517) # EWC context.y=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)) # between 0 and 1 where 1 means fastes change in beta, #whereas small values indicates liniar regression delta = 0.0001 context.Vw=delta/(1-delta)*np.eye(2); # default peridiction error variance context.Ve=0.001; # beta, holds slope and intersection context.beta=np.zeros((2,1)); context.postBeta=np.zeros((2,1)); # previous beta # covariance of error between projected beta and beta # cov (beta-priorBeta) = E[(beta-priorBeta)(beta-priorBeta)'] context.P=np.zeros((2,2)); context.priorP=np.ones((2,2)); context.started=False; context.warmupPeriod=3 context.warmupCount=0 context.long=False; context.short=False; # Will be called on every trade event for the securities specified. def handle_data(context, data): ########################################## # Prediction ########################################## if context.started: # state prediction context.beta=context.postBeta; #prior P prediction context.priorP=context.P+context.Vw else: context.started=True; xpx=np.mat([[1,data[context.x].price]]) ypx=data[context.y].price # projected y yhat=np.dot(xpx,context.beta)[0,0] # prediction error err=(ypx-yhat); # variance of err, var(err) Q=(np.dot(np.dot(xpx,context.priorP),xpx.T)+context.Ve)[0,0] # Kalman gain K=(np.dot(context.priorP,xpx.T)/Q)[0,0] ########################################## # Update section ########################################## context.postBeta=context.beta + np.dot(K,err) context.warmupCount+=1 if context.warmupPeriod > context.warmupCount: return #order(sid(24), 50) message='started: {st}, xprice: {xpx}, yprice: {ypx},\ yhat:{yhat} beta: {b}, postBeta: {pBeta} err: {e}, Q: {Q}, K: {K}' message= message.format(st=context.started,xpx=xpx,ypx=ypx,\ yhat=yhat, b=context.beta, \ pBeta=context.postBeta, e=err, Q=Q, K=K) log.info(message) # record(xpx=data[context.x].price, ypx=data[context.y].price,err=err, yhat=yhat, beta=context.beta[1,0]) ########################################## # Trading section # Spread (y-beta*x) is traded ########################################## QTY=1000 qtyX=-context.beta[1,0]*xpx[0,1]*QTY; qtyY=ypx*QTY; # similar to zscore in bollinger band stdQ=np.sqrt(Q) if err < -stdQ and canEnterLong(context): # enter long the spread order(context.y, qtyY) order(context.x, qtyX) context.long=True if err > -stdQ and canExitLong(context): # exit long the spread order(context.y, -qtyY) order(context.x, -qtyX) context.long=False if err > stdQ and canEnterShort(context): # enter short the spread order(context.y, -qtyY) order(context.x, -qtyX) context.short=True if err < stdQ and canExitShort(context): # exit short the spread order(context.y,qtyY) order(context.x,qtyX) context.short=False record(cash=context.portfolio.cash, stock=context.portfolio.positions_value) 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 canExitLong(context): if 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.long and not context.short: return True else: return False def canExitShort(context): if context.short and not context.long: return True else: return False
Showing posts with label source code. Show all posts
Showing posts with label source code. Show all posts
Sunday, January 19, 2014
Mean reversion with Kalman Filter as Dynamic Linear Regression for Spread Trading within Python
Following code demonstrates how to utilize to kalman filter to estimate hedge ratio for spread trading. The code can be back tested at Quantopian.com
Wednesday, August 19, 2009
Pricing European Options by using Binomial Model
Binomial Model is one of the simplest pricing model for European options. Below you can find an implementation of Cox-Ross-Rubinstein (CRR) approach [1] in java for pricing of put and call European options.
With following parameters, sensitivity of the binomial pricing model as function of number of time steps can be seen in figure 1. With high number of time steps, binomial model with CRR approach converges with optimal Black-Scholes formula (e.x: 30.741 for call option)
With following parameters, sensitivity of the binomial pricing model as function of number of time steps can be seen in figure 1. With high number of time steps, binomial model with CRR approach converges with optimal Black-Scholes formula (e.x: 30.741 for call option)
1: package com.denizstij.finance.pricing;
2:
3: import java.util.ArrayList;
4: import java.util.List;
5:
6: /**
7: *
8: * Estimate European Option price based on Cox, Ross and Rubinstein model
9: * @author denizstij (http://denizstij.blogspot.com/)
10: *
11: */
12: public strictfp class EuropeanOptionPricingByBinomial {
13:
14: /**
15: * Estimate European Option price based on Cox, Ross and Rubinstein model
16: *
17: * @param asset Current Asset Price
18: * @param strike Exercise Price
19: * @param volatility Annual volatility
20: * @param intRate Annual interest rate
21: * @param expiry: Time to maturity (in terms of year)
22: * @param steps : Number of steps
23: * @return Put and call price of european options based on Cox, Ross and Rubinstein model
24: */
25: public List<Double> estimatePrice(double asset,
26: double strike,
27: double volatility,
28: double intRate,
29: double expiry,
30: int steps) {
31: List<Double> results = new ArrayList<Double>();
32:
33: List<Double> stockPrices = new ArrayList<Double>();
34: List<Double> callOptionPrices = new ArrayList<Double>();
35: List<Double> putOptionPrices = new ArrayList<Double>();
36:
37: double time_step = (expiry) / steps;
38: double R = Math.exp(intRate * time_step);
39: double dF = 1 / R; // discount Factor
40:
41: double u = Math.exp(volatility * Math.sqrt(time_step)); // up boundary
42: double d = 1 / u; // down boundary (Cox, Ross and Rubinstein constraint)
43: // at leaf node, price difference factor between each node
44: double uu = u * u; // (u*d)
45: double p_up = (R - d) / (u - d); // up probability
46: double p_down = 1 - p_up; // down probability
47:
48: // initiliaze stock prices
49: for (int i = 0; i <= steps; i++) {
50: stockPrices.add(i, 0.0d);
51: }
52:
53: double sDown = asset * Math.pow(d, steps);
54: stockPrices.set(0, sDown);
55:
56: // Estimate stock prices in leaf nodes
57: for (int i = 1; i <= steps; i++) {
58: double sD = uu * stockPrices.get(i - 1);
59: stockPrices.set(i, sD);
60: }
61:
62: // estimate option's intrinsic values at leaf nodes
63: for (int i = 0; i <= steps; i++) {
64: double callOptionPrice = callPayOff(stockPrices.get(i), strike);
65: callOptionPrices.add(i, callOptionPrice);
66: double putOptionPrice = putPayOff(stockPrices.get(i), strike);
67: putOptionPrices.add(i, putOptionPrice);
68: }
69:
70: // and lets estimate option prices
71: for (int i = steps; i > 0; i--) {
72: for (int j = 0; j <= i - 1; j++) {
73: double callV = dF*(p_up * callOptionPrices.get(j + 1) +
74: p_down* callOptionPrices.get(j));
75: callOptionPrices.set(j, callV);
76: double putV = dF*(p_up * putOptionPrices.get(j + 1) +
77: p_down * putOptionPrices.get(j));
78: putOptionPrices.set(j, putV);
79: }
80: }
81:
82: // first elements holds option's price
83: results.add(callOptionPrices.get(0));
84: results.add(putOptionPrices.get(0));
85: return results;
86: }
87:
88: // Pay off method for put options
89: private double putPayOff(double stockPrice, double strike) {
90: return Math.max(strike - stockPrice, 0);
91: }
92:
93: // Pay off method for call options
94: private double callPayOff(double stockPrice, double strike) {
95: return Math.max(stockPrice - strike, 0);
96: }
97:
98: public static void main(String args[]) {
99:
100: EuropeanOptionPricingByBinomial euOptionPricing = new EuropeanOptionPricingByBinomial();
101: List<Double> results = euOptionPricing.estimatePrice(
102: 230,
103: 210,
104: 0.25,
105: 0.04545,
106: 0.5, // In terms of year
107: 10);
108: Double callOptionPrice = results.get(0);
109: Double putOptionPrice = results.get(1);
110: System.out.println("call Option Price:" + callOptionPrice);
111: System.out.println("put Option Price:" + putOptionPrice);
112: }
113: }
114:
Labels:
algorithms,
derivatives,
finance,
java,
options,
pricing,
source code
Subscribe to:
Posts (Atom)