Jumper-Clown commited on
Commit
0789d79
·
1 Parent(s): 9f633b0

add paper trading back testing

Browse files
__pycache__/bidder.cpython-312.pyc ADDED
Binary file (1.54 kB). View file
 
__pycache__/calculator.cpython-312.pyc CHANGED
Binary files a/__pycache__/calculator.cpython-312.pyc and b/__pycache__/calculator.cpython-312.pyc differ
 
__pycache__/page_symbol_details.cpython-312.pyc CHANGED
Binary files a/__pycache__/page_symbol_details.cpython-312.pyc and b/__pycache__/page_symbol_details.cpython-312.pyc differ
 
__pycache__/trends.cpython-312.pyc CHANGED
Binary files a/__pycache__/trends.cpython-312.pyc and b/__pycache__/trends.cpython-312.pyc differ
 
__pycache__/ui.cpython-312.pyc CHANGED
Binary files a/__pycache__/ui.cpython-312.pyc and b/__pycache__/ui.cpython-312.pyc differ
 
bidder.py ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+
3
+ #test
4
+ import streamlit as st
5
+
6
+ def buy_and_hold(init_val, symbol_closes):
7
+ shares = init_val/symbol_closes[0]
8
+ trade_val = shares*symbol_closes[-1]
9
+ return trade_val
10
+
11
+ def buy_rule(init_value, transact_dates, transact_percents, dates, symbol_closes):
12
+ close_values = [symbol_closes[dates.index(transact_date)] for transact_date in transact_dates]
13
+ wallet = init_value
14
+ shares = 0.0
15
+ for close_value, transact_percent in zip(close_values, transact_percents):
16
+ is_buy = transact_percent > 0
17
+ if is_buy:
18
+ transact_val = wallet*transact_percent/100
19
+ transact_shares = transact_val/close_value
20
+ wallet -= transact_val
21
+ shares += transact_shares
22
+
23
+ # st.write(f"buy: R{transact_val} = {transact_shares}shares. Remaining: R{wallet} and {shares}shares")
24
+ else:
25
+ transact_shares = shares*-transact_percent/100
26
+ transact_val = transact_shares*close_value
27
+ shares -= transact_shares
28
+ wallet += transact_val
29
+
30
+ # st.write(f"sell: R{transact_val} = {transact_shares}shares. Remaining: R{wallet} and {shares}shares")
31
+
32
+ share_value = shares*symbol_closes[-1]
33
+ return wallet + share_value
calculator.py CHANGED
@@ -2,6 +2,8 @@ import numpy as np
2
  import scipy as sp
3
  from datetime import datetime
4
 
 
 
5
 
6
  def linear_regression_line(dates, y_list):
7
  if not any(dates):
@@ -64,4 +66,15 @@ def normalize(data_list, high=1.0, low=-1.0):
64
  new_delta = high - low
65
 
66
  data = ((data - min_val) * new_delta / delta) + low
67
- return data
 
 
 
 
 
 
 
 
 
 
 
 
2
  import scipy as sp
3
  from datetime import datetime
4
 
5
+ # test
6
+ import streamlit as st
7
 
8
  def linear_regression_line(dates, y_list):
9
  if not any(dates):
 
66
  new_delta = high - low
67
 
68
  data = ((data - min_val) * new_delta / delta) + low
69
+ return data
70
+
71
+ def intercepts(data1, data2):
72
+ intercept_indices = []
73
+ prev_data1_is_above = True
74
+ for index, (data1_v, data2_v) in enumerate(zip(data1, data2)):
75
+ data1_is_above = data1_v - data2_v >= 0.0
76
+ if index is not 0 and (not any(intercept_indices) or index is not intercept_indices[-1] + 1) and prev_data1_is_above is not data1_is_above:
77
+ intercept_indices.append(index)
78
+ prev_data1_is_above = data1_is_above
79
+
80
+ return intercept_indices
page_symbol_details.py CHANGED
@@ -8,6 +8,7 @@ import calculator
8
  import data_retriever
9
  import trends
10
  import ui
 
11
 
12
 
13
  def run():
@@ -52,58 +53,94 @@ def run():
52
  # symbol candlestick graph
53
  candleFigure = make_subplots(rows=1, cols=1)
54
  ui.create_candlestick(candleFigure, dates, symbol_prices, symbol, 'Price')
55
- # # indicators
56
- # indicator_datasets = indicators.create_indicators(dates, symbol_prices)
57
- # ui.create_indicators(fig1, indicator_datasets)
58
- # trend lines
59
- # sigma_multiplier = st.slider(label='min trend deviation', min_value=1.0, max_value=10.0, value=3.0, step=0.1)
60
- # sigma_dates, sigma_values = trends.trend_line(symbol_prices_backtest.index, np.array(symbol_prices_backtest['Close']), min_trend_size=21, sigma_multiplier=sigma_multiplier)
61
- # ui.create_markers(candleFigure, sigma_dates, sigma_values, f"{sigma_multiplier} Deviations from regression line", 'Deviations')
62
-
63
- # # vwap
64
- # vwap = trends.vwap(symbol_prices_backtest)
65
- # ui.create_line(candleFigure, backtest_dates, vwap, "Volume Weighted Average Price (VWAP)", "VWAP")
66
-
67
- # # bollinger bands
68
- # bollinger_dates, bollinger_low, bollinger_high = trends.bollinger_bands(backtest_dates, symbol_prices_backtest)
69
- # ui.create_fill_area(candleFigure, bollinger_dates, bollinger_low, bollinger_high, "Bollinger Bands")
70
-
71
- normalization_factor = 0.20*(max(symbol_prices['Close']) - min(symbol_prices['Close']))
72
-
73
- # trend deviation area
74
- period = 7
75
- trend_deviation = trends.trend_deviation(symbol_prices['Close'][:], period=period)
76
- trend_deviation_norm = calculator.normalize(trend_deviation, low=0.0, high=normalization_factor)
77
- price_offset_low = [price - vol for price, vol in zip(symbol_prices['Close'][period:], trend_deviation_norm)]
78
- price_offset_high = [price + vol for price, vol in zip(symbol_prices['Close'][period:], trend_deviation_norm)]
79
- ui.create_fill_area(candleFigure, dates[period:], price_offset_low, price_offset_high, "Trend Deviation", color="rgba(0,50,50,0.3)")
80
-
81
- # trade volume area
82
- volume_norm = calculator.normalize(symbol_prices['Volume'], low=0.0, high=normalization_factor)
83
- log_volume_offset_low = [price - vol for price, vol in
84
- zip(symbol_prices['Close'], volume_norm)]
85
- log_volume_offset_high = [price + vol for price, vol in
86
- zip(symbol_prices['Close'], volume_norm)]
87
- ui.create_fill_area(candleFigure, dates, log_volume_offset_low, log_volume_offset_high, "Volume Bands", color="rgba(100,20,0,0.3)")
88
-
89
- sma_dates, deltas_sma = trends.sma(dates, symbol_prices['Close'], period)
90
- ui.create_line(candleFigure, sma_dates, deltas_sma, f"Close price {period} day SMA")
91
 
92
  # plot all
93
  candleFigure.update_layout(title="Symbol Ticker",
94
  xaxis_title='Date',
95
  yaxis_title="Price per Share",
96
  template='plotly_dark')
97
- selected_points = plotly_events(candleFigure, click_event=True, hover_event=False, select_event=False, key='3')
98
 
99
- if st.checkbox('Tests'):
100
- # testFigure = make_subplots(rows=1, cols=1)
101
- # ui.create_line(testFigure, dates, symbol_prices['Volume'], "Volume")
102
- # ui.add_mouse_indicator(testFigure, selected_points, min=np.min(symbol_prices['Volume']),
103
- # max=np.max(symbol_prices['Volume']))
104
- # testFigure.update_layout(title="Volume")
105
- # test_id = st.plotly_chart(testFigure, use_container_width=True, key='test')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106
 
 
107
  deltas = [cur - symbol_prices['Close'][max(0, idx - 1)] for idx, cur in enumerate(symbol_prices['Close'])]
108
  testFigure2 = make_subplots(rows=1, cols=1)
109
  ui.create_line(testFigure2, dates, deltas, "Deltas")
 
8
  import data_retriever
9
  import trends
10
  import ui
11
+ import bidder
12
 
13
 
14
  def run():
 
53
  # symbol candlestick graph
54
  candleFigure = make_subplots(rows=1, cols=1)
55
  ui.create_candlestick(candleFigure, dates, symbol_prices, symbol, 'Price')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
 
57
  # plot all
58
  candleFigure.update_layout(title="Symbol Ticker",
59
  xaxis_title='Date',
60
  yaxis_title="Price per Share",
61
  template='plotly_dark')
 
62
 
63
+ # use this to add markers on other graphs for click points on this graph
64
+ selected_points = []
65
+ # selected_points = plotly_events(candleFigure, click_event=True, hover_event=False, select_event=False, key='3', override_height=800)
66
+
67
+ st.plotly_chart(candleFigure, use_container_width=True)
68
+
69
+ if st.checkbox('Trends'):
70
+ period = st.slider(label='period', min_value=7, max_value=140, value=14, step=7)
71
+
72
+ indicatorFigure = make_subplots(rows=1, cols=1)
73
+ ui.create_line(indicatorFigure, dates, symbol_prices['Close'], "Close price", color="red")
74
+
75
+ # # indicators
76
+ # indicator_datasets = indicators.create_indicators(dates, symbol_prices)
77
+ # ui.create_indicators(fig1, indicator_datasets)
78
+ # trend lines
79
+ # sigma_multiplier = st.slider(label='min trend deviation', min_value=1.0, max_value=10.0, value=3.0, step=0.1)
80
+ # sigma_dates, sigma_values = trends.trend_line(symbol_prices_backtest.index, np.array(symbol_prices_backtest['Close']), min_trend_size=21, sigma_multiplier=sigma_multiplier)
81
+ # ui.create_markers(candleFigure, sigma_dates, sigma_values, f"{sigma_multiplier} Deviations from regression line", 'Deviations')
82
+
83
+ # vwap
84
+ vwap = trends.vwap(symbol_prices_backtest)
85
+ ui.create_line(candleFigure, backtest_dates, vwap, "Volume Weighted Average Price (VWAP)", "VWAP")
86
+
87
+ # bollinger bands
88
+ bollinger_dates, bollinger_low, bollinger_high = trends.bollinger_bands(backtest_dates, symbol_prices_backtest)
89
+ ui.create_fill_area(candleFigure, bollinger_dates, bollinger_low, bollinger_high, "Bollinger Bands")
90
+
91
+ # trend
92
+ trend = trends.linear_regression_trend(symbol_prices['Close'][:], period=period)
93
+ ui.create_line(indicatorFigure, dates[period:], trend, f"Trend: {period} day", color='blue')
94
+
95
+ # trend deviation area
96
+ price_deviation_from_trend = [price - trend_val for price, trend_val in
97
+ zip(symbol_prices['Close'][period:], trend)]
98
+ deviation_price_offset = [price + dev for price, dev in
99
+ zip(symbol_prices['Close'][period:], price_deviation_from_trend)]
100
+ ui.create_fill_area(indicatorFigure, dates[period:], trend, deviation_price_offset,
101
+ f"Trend Deviation: {period} day trend", color="rgba(100,0,100,0.3)")
102
+
103
+ # sma line
104
+ deltas_sma = trends.sma(symbol_prices['Close'], period)
105
+ ui.create_line(indicatorFigure, dates[period:], deltas_sma, f"SMA {period} day", color='green')
106
+
107
+ # bids
108
+ init_val = 1000.0
109
+ buy_and_hold_val = bidder.buy_and_hold(init_val, symbol_prices['Close'])
110
+ st.write(f"BUY AND HOLD: {buy_and_hold_val}")
111
+
112
+ bid_dates, bid_vals = trends.bids(dates, symbol_prices, period)
113
+ strat_val = bidder.buy_rule(init_val, bid_dates, bid_vals, dates, symbol_prices['Close'])
114
+
115
+ ui.create_markers(indicatorFigure, bid_dates, bid_vals, "Bids", "Price")
116
+ st.write(f"STRAT: {strat_val}")
117
+
118
+ indicatorFigure.update_layout(title="Indicators",
119
+ xaxis_title='Date',
120
+ yaxis_title="Price",
121
+ template='plotly_dark')
122
+ st.plotly_chart(indicatorFigure, use_container_width=True)
123
+
124
+ # doxy
125
+ st.markdown(
126
+ f"Trend deviation: indicates the extent by which the price is deviating from its current trajectory. "
127
+ f"The trajectory is the linear regression of the price over {period} days.")
128
+ st.markdown('''<ol><li>mark all intercepts between the SMA and the price.</li>
129
+ <li>calculate the cum-sum of trend deviations. the cum-sum is reset when an intercept occurs.</li>
130
+ <li>when there is an intercept, and the cum-sum above a threshold, then a price reversal is imminent.</li></ol>''', unsafe_allow_html=True)
131
+
132
+ st.markdown('''<ol><li>if the trend intersects SMA, then reset.</li>
133
+ <li>when the trend intersects the price, place a bid. if the previous intercept is lower, then buy.</li></ol>''')
134
+ # volumeFig = make_subplots(rows=1, cols=1)
135
+ # ui.create_line(volumeFig, dates, symbol_prices['Volume'], "Volume")
136
+ # st.plotly_chart(volumeFig, use_container_width=True)
137
+ # st.markdown(
138
+ # "Trade Volume: a measure of investor belief. "
139
+ # "A high volume means that investors have a strong belief that the price will change. "
140
+ # "The volume does not indicate whether the price will go up or down.")
141
+
142
 
143
+ if st.checkbox('Tests'):
144
  deltas = [cur - symbol_prices['Close'][max(0, idx - 1)] for idx, cur in enumerate(symbol_prices['Close'])]
145
  testFigure2 = make_subplots(rows=1, cols=1)
146
  ui.create_line(testFigure2, dates, deltas, "Deltas")
trends.py CHANGED
@@ -117,12 +117,11 @@ def vwap(symbol_price_data):
117
  return vwap_values
118
 
119
 
120
- def sma(dates, data_list, n_days=20):
121
- res_dates, res_values = [], []
122
- res_dates = dates[n_days-1:]
123
- for index in range(len(data_list) - n_days + 1):
124
- res_values.append(np.mean(data_list[index:index + n_days]))
125
- return res_dates, res_values
126
 
127
 
128
  def bollinger_bands(dates, symbol_price_data, n_days_deviation=20, deviation_multiplier=2):
@@ -144,26 +143,42 @@ def support_lines():
144
  a = 1
145
 
146
 
147
- # the volatility is the average deviation from the current trend.
148
- # this is measured by doing linear regression over each period, then calculating the deviation of values from that line.
149
- def trend_deviation(prices, period=32):
150
  np_dates = np.array([ts.timestamp() for ts in prices.index])
151
  np_values = np.array(prices)
152
 
153
  value_count = len(prices)
154
-
155
- avg_deviations = []
156
  for index in range(value_count-period):
157
  np_dates_subset = np_dates[index:index+period+1]
158
  np_values_subset = np_values[index:index+period+1]
159
- m, c = calculator.linear_regression_line(np_dates_subset, np_values_subset)
160
- predicted_values = m * np_dates_subset + c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
 
162
- deviation_sum = 0
163
- for value, predicted_value in zip(np_values_subset, predicted_values):
164
- deviation = abs(value - predicted_value)
165
- deviation_sum += deviation
166
- avg_deviation = deviation_sum/period
167
- avg_deviations.append(avg_deviation)
168
 
169
- return avg_deviations
 
117
  return vwap_values
118
 
119
 
120
+ def sma(prices, period=20):
121
+ values = []
122
+ for index in range(len(prices) - period):
123
+ values.append(np.mean(prices[index:index + period]))
124
+ return values
 
125
 
126
 
127
  def bollinger_bands(dates, symbol_price_data, n_days_deviation=20, deviation_multiplier=2):
 
143
  a = 1
144
 
145
 
146
+ # a linear regression over a period
147
+ def linear_regression_trend(prices, period=32):
 
148
  np_dates = np.array([ts.timestamp() for ts in prices.index])
149
  np_values = np.array(prices)
150
 
151
  value_count = len(prices)
152
+ trend = []
 
153
  for index in range(value_count-period):
154
  np_dates_subset = np_dates[index:index+period+1]
155
  np_values_subset = np_values[index:index+period+1]
156
+ low, high = calculator.linear_regression(np_dates_subset, np_values_subset)
157
+ trend.append(high)
158
+
159
+ return trend
160
+
161
+
162
+ def bids(dates, symbol_prices, period=14):
163
+ close_values = symbol_prices['Close']
164
+ trend = linear_regression_trend(close_values, period=period)
165
+ sma_values = sma(close_values, period=period)
166
+
167
+ # get intercepts
168
+ dates_subset = dates[period:]
169
+ close_subset = close_values[period:]
170
+
171
+ sma_intercept_indices = calculator.intercepts(sma_values, close_subset)
172
+ trend_intercept_indices = calculator.intercepts(trend, close_subset)
173
+
174
+ sma_intercept_dates = [dates_subset[index] for index in sma_intercept_indices]
175
+ bids = []
176
+ for index in sma_intercept_indices:
177
+ is_up = sma_values[index] > close_subset[index]
178
+ if is_up:
179
+ bids.append(10)
180
+ else:
181
+ bids.append(-10)
182
 
183
+ return sma_intercept_dates, bids
 
 
 
 
 
184
 
 
ui.py CHANGED
@@ -81,8 +81,8 @@ def create_markers(fig, dates, dataset, title, y_label, marker_symbol=3, marker_
81
  fig.add_trace(line)
82
 
83
 
84
- def create_line(fig, dates, dataset, title="title", y_label="values", marker_symbol=4, marker_size=15):
85
- line = go.Scatter(name=title, x=dates, y=dataset, marker_line_color="yellow")
86
  fig.add_trace(line)
87
 
88
 
 
81
  fig.add_trace(line)
82
 
83
 
84
+ def create_line(fig, dates, dataset, title="title", y_label="values", marker_symbol=4, marker_size=15, color='rgba(0,100,80,0.2)'):
85
+ line = go.Scatter(name=title, x=dates, y=dataset, marker_line_color="yellow", fillcolor=color)
86
  fig.add_trace(line)
87
 
88