1
+ import pandas as pd
2
+ import matplotlib
3
+ import matplotlib .pyplot as plt
4
+ import math
5
+ import quandl
6
+
7
+ def variance_calculator (series , series_average , win_len ):
8
+ sma = win_len
9
+ temp = series .subtract (series_average ) # Difference a-b
10
+ temp2 = temp .apply (lambda x :x ** 2 ) # Square them.. (a-b)^2
11
+ temp3 = temp2 .rolling (sma - 1 ).mean () # Summation (a-b)^2 / (sma - 1)
12
+ sigma = temp3 .apply (lambda x : math .sqrt (x ))
13
+ return sigma
14
+
15
+ def fetch_data (string1 , string2 , string3 , filename ):
16
+ w = quandl .get (string1 , authtoken = string2 , start_date = string3 )
17
+ w .to_csv (filename )
18
+ w = pd .read_csv (filename )
19
+ return w
20
+
21
+ # The Data pulled from quandl and stored locally for faster execution
22
+ Data = fetch_data ("CHRIS/CME_SP1" , "" , "2017-07-31" , "local_future.csv" )
23
+ Data1 = fetch_data ("CHRIS/SPX_PC" , "" , "2017-07-31" , "local_data.csv" )
24
+
25
+ Data ['future' ] = Data1 ['Last' ]
26
+ Data ['PCR' ] = Data ['S&P PUT-CALL RATIO' ]
27
+
28
+ # Variables
29
+
30
+ sma = 20 # Moving Average Window length
31
+ k = 1.5 # Constant representing 'k' times sigma away from moving average (fir Bollinger bands)
32
+ l = 2 # cons.representing 'l' times sigma away from Bollinger band (for stoploss band)
33
+ pro = 0 # Profit Variable
34
+ flag = 1 # Flag is there for begin first transaction -- transaction should start with LBB/UBB crossing only
35
+ buy_flag = False
36
+ sell_flag = False
37
+ transaction_start_price = 0
38
+ abs_SL = 25 # Absolute Stoploss Variable
39
+ mtm = list ()
40
+ order_details = list ()
41
+ order = list () #list which contains the orders: BUY / SELL / Do Nothing
42
+ profit = list ()
43
+ buy_sell = list ()
44
+ stoploss = list ()
45
+ trade_cause = list ()
46
+
47
+ Data ['mAvg' ] = Data ['PCR' ].rolling (sma ).mean () # Calculating the moving average of the PCR
48
+ Data ['PCR_prev' ] = Data ['PCR' ].shift (1 )
49
+
50
+ sigma = variance_calculator (Data ['PCR' ], Data ['mAvg' ], sma ) # Calculating the standard deviation
51
+ k_sigma = k * sigma
52
+ l_sigma = l * sigma
53
+
54
+ Data ['UBB' ] = Data ['mAvg' ].add (k_sigma ) # Upper Bollinger Band
55
+ Data ['LBB' ] = Data ['mAvg' ].subtract (k_sigma ) # Lower Bollinger Band
56
+ Data ['USL' ] = Data ['UBB' ].add (l_sigma ) # Upper Stoploss Band
57
+ Data ['LSL' ] = Data ['LBB' ].subtract (l_sigma ) # Lower Stoploss Band
58
+ Data ['order' ] = pd .Series () # list which contains the orders: BUY / SELL / Do Nothing
59
+
60
+ s = Data ['PCR' ].size # Total Number of Data point
61
+
62
+ for i in range (s ):
63
+
64
+ pro = 0 # Profit at each trade
65
+ future_cost = Data ['future' ][i ] # Cost of big S&P 500 futures bought
66
+ PCR = Data ['PCR' ][i ] # Put Call ratio
67
+ PCR_prev = Data ['PCR_prev' ][i ] # Previous day's put call ratio
68
+ LBB = Data ['LBB' ][i ] # Lower Bollinger Band
69
+ UBB = Data ['UBB' ][i ] # # Upper Bollinger Band
70
+ mAvg = Data ['mAvg' ][i ] # Moving Average
71
+ USL = Data ['USL' ][i ] # Upper Stoploss Band
72
+ LSL = Data ['LSL' ][i ] # Lower Stoploss Band
73
+
74
+ # Comparisons stores as boolean variables a to place order accordingly
75
+ UBB_cross = (PCR > UBB ) and (PCR_prev < UBB ) # Check if PCR crosses Upper Bollinger Band
76
+ LBB_cross = (PCR < LBB ) and (PCR_prev > LBB ) # Check if PCR crosses Lower Bollinger Band
77
+ mAvg_cross_up = (PCR > mAvg ) and (PCR_prev < mAvg ) # Check if PCR crosses moving average from low to high
78
+ mAvg_cross_down = (PCR < mAvg ) and (PCR_prev > mAvg ) # Check if PCR crosses moving average from high to low
79
+ USL_cross = (PCR > USL ) and (PCR_prev < USL ) # Check if PCR Crosses upper stoploss band
80
+ LSL_cross = (PCR < LSL ) and (PCR_prev > LSL ) # Check if PCR Crosses lower stoploss band
81
+
82
+
83
+ # Strategy
84
+ if (UBB_cross and (not buy_flag ) and flag == 1 ): # Places "BUY" order if PCR crosses upper Bollinger band to open trade
85
+ flag = 0
86
+ buy_flag = True
87
+ sell_flag = False
88
+ transaction_start_price = future_cost # Price at which s&P 500 future bought when the order is placed
89
+ order_details = [1 , "Buy" , "UBB Crossed" , "0" , "Position taken" ]
90
+
91
+ elif (LBB_cross and (not sell_flag ) and flag == 1 ):
92
+ flag = 0
93
+ sell_flag = True
94
+ buy_flag = False
95
+ transaction_start_price = future_cost
96
+ order_details = [- 1 , "Sell" , "LBB Crossed" , "0" , "Position taken" ]
97
+
98
+ elif (mAvg_cross_up and (not buy_flag ) and flag == 0 ): # Places "BUY" order if PCR crosses mAvg from low to high to close a trade
99
+ flag = 1
100
+ buy_flag = False
101
+ sell_flag = False
102
+ pro = future_cost - transaction_start_price
103
+ order_details = [1 , "Buy" , "mAvg Crossed" , "0" , "Position Closed" ]
104
+
105
+ elif (LSL_cross and (not buy_flag ) and flag == 0 ): # Places "BUY" order if PCR crosses lower stoploss band to close a trade
106
+ flag = 1
107
+ buy_flag = False
108
+ sell_flag = False
109
+ pro = future_cost - transaction_start_price
110
+ order_details = [1 , "Buy" , "LSB Crossed" , "Stoploss Executed" , "Position Closed" ]
111
+
112
+ elif ((future_cost - transaction_start_price ) > abs_SL and (not buy_flag ) and flag == 0 ): # Places "BUY" order if PCR crosses lower stoploss absolute value
113
+ flag = 0
114
+ buy_flag = False
115
+ sell_flag = False
116
+ pro = future_cost - transaction_start_price
117
+ order_details = [1 , "Buy" , "LSB Crossed" , "Stoploss Executed" , "Position Closed" ]
118
+
119
+ elif (mAvg_cross_down and (not sell_flag ) and flag == 0 ): # Places "Sell" order if PCR crosses mAvg from high to low to close a trade
120
+ flag = 1
121
+ buy_flag = False
122
+ sell_flag = False
123
+ pro = - (future_cost - transaction_start_price )
124
+ order_details = [- 1 , "Sell" , "mAvg Crossed (H to L)" , "0" , "Position Closed" ]
125
+
126
+ elif (USL_cross and (not sell_flag ) and flag == 0 ): # Places "Sell" order if PCR crosses Upper stoploss band to close a trade
127
+ flag = 1
128
+ buy_flag = False
129
+ sell_flag = False
130
+ pro = - (future_cost - transaction_start_price )
131
+ order_details = [- 1 , "Sell" , "USB Crossed" , "Stoploss Executed" , "Position Closed" ]
132
+
133
+ elif ( (- future_cost - transaction_start_price ) > abs_SL and (not sell_flag ) and flag == 0 ): # Places "SELL" order if PCR crosses Upper stoploss absolute value
134
+ flag = 1
135
+ buy_flag = False
136
+ sell_flag = False
137
+ pro = - (future_cost - transaction_start_price )
138
+ order_details = [- 1 , "Sell" , "USB Crossed" , "Abs Stoploss Executed" , "Position Closed" ]
139
+
140
+ else :
141
+ if (buy_flag == 0 and sell_flag == 0 ):
142
+ tempo = "0"
143
+ else :
144
+ if (buy_flag == 1 and sell_flag == 0 ):
145
+ tempo = (Data ['future' ][i ] - transaction_start_price ) * 500
146
+ if (buy_flag == 0 and sell_flag == 1 ):
147
+ tempo = (- Data ['future' ][i ] + transaction_start_price ) * 500
148
+ order_details = [0 , "No Trade" , "No Trade" , "0" , tempo ]
149
+
150
+ profit .append (pro )
151
+ order .append (order_details [0 ])
152
+ buy_sell .append (order_details [1 ])
153
+ trade_cause .append (order_details [2 ])
154
+ stoploss .append (order_details [3 ])
155
+ mtm .append (order_details [4 ])
156
+
157
+ Data ['placed_order' ] = pd .Series (order ) # Converting list into Panda Series
158
+ Data ['cost' ] = - (Data ['placed_order' ].multiply (Data ['future' ])) * 500 # Cost of each transaction
159
+ Data ['out' ] = Data ['cost' ].cumsum () # Out is the cumulative cost profit / loss after transaction till now
160
+ Data ['buy_sell' ] = pd .Series (buy_sell )
161
+ Data ['profit' ] = - pd .Series (profit ) * 500
162
+ Data ['stoploss' ] = pd .Series (stoploss )
163
+ Data ['trade_cause' ] = pd .Series (trade_cause )
164
+ Data ['mtm' ] = pd .Series (mtm )
165
+
166
+ print (Data ['out' ])
167
+
168
+ output = pd .DataFrame () # Final output to be stored in excel file
169
+ output ['date' ] = Data ['Date' ]
170
+ output ['Close' ] = Data ['future' ]
171
+ output ['PCR' ] = Data ['PCR' ]
172
+ output ['placed_order' ] = Data ['placed_order' ]
173
+ output ['buy_sell' ] = Data ['buy_sell' ]
174
+ output ['trade_cause' ] = Data ['trade_cause' ]
175
+ output ['PnL' ] = Data ['profit' ]
176
+ output ['mtm' ] = Data ['mtm' ]
177
+ output ['stoploss' ] = Data ['stoploss' ]
178
+ output ['Cash Account' ] = Data ['out' ]
179
+
180
+ output .to_excel ('PCR_SL_output.xlsx' , sheet_name = 'Sheet1' )
181
+
182
+
183
+ # Plot
184
+ plt .plot (Data ['PCR' ])
185
+ plt .plot (Data ['mAvg' ])
186
+ plt .plot (Data ['UBB' ])
187
+ plt .plot (Data ['LBB' ])
188
+ plt .show ()
0 commit comments