ml-finance-python
python scripts for finance machine learning
git clone https://9o.is/git/ml-finance-python.git
basic_pairs_trading_template.py
(2969B)
1 """
2 This is a basic pairs trading algorithm for use at Quantopian Workshops.
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 By Delaney Granizo-Mackenzie
7 """
8 import numpy as np
9
10 def initialize(context):
11 """
12 Called once at the start of the algorithm.
13 """
14 # Check status of the pair every day 2 minutes before we rebalance
15 # The 2 minutes is just because we want to be safe, and 1 minutes
16 # is cutting it close
17 schedule_function(check_pair_status, date_rules.every_day(), time_rules.market_close(minutes=60))
18
19 context.stock1 = symbol('ABGB')
20 context.stock2 = symbol('FSLR')
21
22 # Our threshold for trading on the z-score
23 context.entry_threshold = 0.2
24 context.exit_threshold = 0.1
25
26 # Moving average lengths
27 context.long_ma_length = 30
28 context.short_ma_length = 1
29
30 # Flags to tell us if we're currently in a trade
31 context.currently_long_the_spread = False
32 context.currently_short_the_spread = False
33
34
35 def check_pair_status(context, data):
36
37 # For notational convenience
38 s1 = context.stock1
39 s2 = context.stock2
40
41 # Get pricing history
42 prices = data.history([s1, s2], "price", context.long_ma_length, '1d')
43
44 # Try debugging me here to see what the price
45 # data structure looks like
46 # To debug, click on the line number to the left of the
47 # next command. Line numbers on blank lines or comments
48 # won't work.
49 short_prices = prices.iloc[-context.short_ma_length:]
50
51 # Get the long mavg
52 long_ma = np.mean(prices[s1] - prices[s2])
53 # Get the std of the long window
54 long_std = np.std(prices[s1] - prices[s2])
55
56
57 # Get the short mavg
58 short_ma = np.mean(short_prices[s1] - short_prices[s2])
59
60 # Compute z-score
61 if long_std > 0:
62 zscore = (short_ma - long_ma)/long_std
63
64 # Our two entry cases
65 if zscore > context.entry_threshold and \
66 not context.currently_short_the_spread:
67 order_target_percent(s1, -0.5) # short top
68 order_target_percent(s2, 0.5) # long bottom
69 context.currently_short_the_spread = True
70 context.currently_long_the_spread = False
71
72 elif zscore < -context.entry_threshold and \
73 not context.currently_long_the_spread:
74 order_target_percent(s1, 0.5) # long top
75 order_target_percent(s2, -0.5) # short bottom
76 context.currently_short_the_spread = False
77 context.currently_long_the_spread = True
78
79 # Our exit case
80 elif abs(zscore) < context.exit_threshold:
81 order_target_percent(s1, 0)
82 order_target_percent(s2, 0)
83 context.currently_short_the_spread = False
84 context.currently_long_the_spread = False
85
86 record('zscore', zscore)