1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
import json
import datetime
# pull stock data from json files
# timestamps_file = open('timestamps.json', 'r')
# timestamps_file_data = timestamps_file.read()
# timestamps = json.loads(timestamps_file_data)
# timestamps = [datetime.datetime.fromtimestamp(t) for t in timestamps]
# prices_file = open('close_prices.json', 'r')
# prices = json.loads(prices_file.read())
# print('timestamps:\t', timestamps, '\nprices:\t', prices)
# make the line data for the 5 day exponential moving average (EMA)
def calc_first_sma(period, prices):
prices_sum = 0
for i in range(0, period):
prices_sum += prices[i] # 0, 1, 2, 3 ("popping" order)
# print('prices_sum:\t', prices_sum)
return prices_sum / period
def calc_emas(period, prices):
weighted_multiplier = 2.0 / (period + 1.0)
# calculate the first ema
first_ema = calc_first_sma(period, prices)
# calculate the rest ema's using that first
emas = [first_ema] * period
for i in range(period + 1, len(prices)): # 4, 5, 6, ... , last
last_ema = emas[-1]
next_ema = prices[i] * weighted_multiplier + last_ema * (1 - weighted_multiplier)
emas.append(next_ema)
return emas
def interpolate_intersection(intersection_indices, timestamps, prices1, prices2):
left_index = intersection_indices[0]
right_index = intersection_indices[1]
if right_index == -1:
return timestamps[left_index]
y_1 = prices1[left_index]
y_2 = prices1[right_index] # first line
v_1 = prices2[left_index]
v_2 = prices2[right_index] # second line
x_1 = 0 # take this as zero the simplify the algebra
x_diff = timestamps[right_index] - timestamps[left_index] # same for both lines
# find intersection between those lines
x_diff = x_diff.total_seconds()
m_1 = (y_2 - y_1) / x_diff # slope of line 1
m_2 = (v_2 - v_1) / x_diff
x_interpolated = (v_1 - y_1) / (m_1 - m_2)
y_interpolated = m_1 * (x_interpolated) + y_1
# add back the time we subtracted to make x_1=0
x_interpolated = datetime.timedelta(seconds = x_interpolated) + timestamps[left_index]
return (x_interpolated, y_interpolated)
"""
Returns the indices of where two arrays' values intersects
"""
def find_intersections(prices1, prices2, offset=0):
if len(prices1) != len(prices2):
print("ERROR IN find_intersections: len of arrs not the same")
return []
prev_p1 = prices1[0]
prev_p2 = prices2[0]
intersection_indices = set()
for i in range(1 + offset, len(prices1)):
next_p1 = prices1[i]
next_p2 = prices2[i]
# if the sign (negative to positive) changes, then there was an intersection between these pts
sub_prev = prev_p1 - prev_p2
sub_next = next_p1 - next_p2
if (sub_prev > 0 and sub_next < 0) or (sub_prev < 0 and sub_next > 0):
intersection_indices.add((i-1, i))
if sub_next == 0:
intersection_indices.add((i, -1))
prev_p1 = next_p1
prev_p2 = next_p2
return intersection_indices
def calculate_profit(buy_line, sell_line, prices, timestamps, offset=0, starting_money=10000):
if len(buy_line) != len(sell_line):
print("ERROR IN find_intersections: len of arrs not the same")
return []
is_bought = False
curr_money = 10000
shares_owned = 0
buy_info = []
sell_info = []
for i in range(offset, len(buy_line)):
current_b1 = buy_line[i]
current_sl = sell_line[i]
# if the sign is positive, we want to hold, if it's negative, we want to sell
sign_signal = current_b1 - current_sl
if sign_signal > 0:
if not is_bought:
# buy the stock
shares_owned = curr_money / prices[i]
curr_money = 0
buy_info.append((timestamps[i], prices[i], i))
is_bought = True
if sign_signal < 0:
if is_bought:
# selling the stock
curr_money = prices[i] * shares_owned
shares_owned = 0
sell_info.append((timestamps[i], prices[i], i))
is_bought = False
# TODO: consider end interval
total_assets = prices[-1] * shares_owned + curr_money
percent_gain = (total_assets - starting_money) / starting_money
return (percent_gain, total_assets, buy_info, sell_info)
|