ml-finance-python
python scripts for finance machine learning
git clone https://9o.is/git/ml-finance-python.git
basic_pairs_trade_optimize_template.py
(3897B)
1 """
2 This is a basic pairs trading algorithm that uses the optimize
3 WARNING: THIS IS A LEARNING EXAMPLE ONLY. DO NOT TRY TO TRADE SOMETHING THIS SIMPLE.
4 https://www.quantopian.com/workshops
5 https://www.quantopian.com/lectures
6
7 For any questions, email max@quantopian.com
8 """
9 import numpy as np
10 import pandas as pd
11 import quantopian.experimental.optimize as opt
12 import quantopian.algorithm as algo
13
14 MAX_GROSS_LEVERAGE = 1.0 # Set leverage constraint constant value for optimizer
15
16 def initialize(context):
17 """
18 Called once at the start of the algorithm.
19 """
20 # Check status of the pair every day 2 minutes before we rebalance
21 # The 2 minutes is just because we want to be safe, and 1 minutes
22 # is cutting it close
23 schedule_function(check_pair_status, date_rules.every_day(), time_rules.market_close(minutes=60))
24
25 context.stock1 = symbol('ABGB')
26 context.stock2 = symbol('FSLR')
27 context.stocks = [context.stock1, context.stock2]
28
29 # Our threshold for trading on the z-score
30 context.entry_threshold = 0.2
31 context.exit_threshold = 0.1
32
33 # Create a variable to store our target weights
34 context.target_weights = pd.Series(index=context.stocks, data=0.0)
35
36 # Moving average lengths
37 context.long_ma_length = 30
38 context.short_ma_length = 1
39
40 # Flags to tell us if we're currently in a trade
41 context.currently_long_the_spread = False
42 context.currently_short_the_spread = False
43
44
45 def check_pair_status(context, data):
46
47 # For notational convenience
48 s1 = context.stock1
49 s2 = context.stock2
50
51 # Get pricing history
52 prices = data.history([s1, s2], "price", context.long_ma_length, '1d')
53
54 # Try debugging me here to see what the price
55 # data structure looks like
56 # To debug, click on the line number to the left of the
57 # next command. Line numbers on blank lines or comments
58 # won't work.
59 short_prices = prices.iloc[-context.short_ma_length:]
60
61 # Get the long mavg
62 long_ma = np.mean(prices[s1] - prices[s2])
63 # Get the std of the long window
64 long_std = np.std(prices[s1] - prices[s2])
65
66
67 # Get the short mavg
68 short_ma = np.mean(short_prices[s1] - short_prices[s2])
69
70 # Compute z-score
71 if long_std > 0:
72 zscore = (short_ma - long_ma)/long_std
73
74 # Our two entry cases
75 if zscore > context.entry_threshold and \
76 not context.currently_short_the_spread:
77 context.target_weights[s1] = -0.5 # short top
78 context.target_weights[s2] = 0.5 # long bottom
79 context.currently_short_the_spread = True
80 context.currently_long_the_spread = False
81
82 elif zscore < -context.entry_threshold and \
83 not context.currently_long_the_spread:
84 context.target_weights[s1] = 0.5 # long top
85 context.target_weights[s2] = -0.5 # short bottom
86 context.currently_short_the_spread = False
87 context.currently_long_the_spread = True
88
89 # Our exit case
90 elif abs(zscore) < context.exit_threshold:
91 context.target_weights[s1] = 0 # close out
92 context.target_weights[s2] = 0 # close out
93 context.currently_short_the_spread = False
94 context.currently_long_the_spread = False
95 record('zscore', zscore)
96
97 # Call the optimizer
98 allocate(context, data)
99
100
101 def allocate(context, data):
102 # Set objective to match target weights as closely as possible, given constraints
103 objective = opt.TargetPortfolioWeights(context.target_weights)
104
105 # Define constraints
106 constraints = []
107 constraints.append(opt.MaxGrossLeverage(MAX_GROSS_LEVERAGE))
108
109 algo.order_optimal_portfolio(
110 objective=objective,
111 constraints=constraints,
112 universe=context.stocks
113 )