diff options
author | loit <michael.foiani@gmail.com> | 2025-07-28 19:47:49 -0400 |
---|---|---|
committer | loit <michael.foiani@gmail.com> | 2025-07-28 19:47:49 -0400 |
commit | 1ed62b0e315ca1fc97b3ba8752db24e0bebd706f (patch) | |
tree | aa8fa98027d0b6b3588d4a06bde699964d26f4c7 | |
parent | 8907c286e857b622af171c2d8ac9040b05970549 (diff) |
add calculations that determine the percent gain and loss from using this algorithm
-rw-r--r-- | analysis.py | 43 | ||||
-rw-r--r-- | app.py | 56 |
2 files changed, 77 insertions, 22 deletions
diff --git a/analysis.py b/analysis.py index 2b5ed59..644fe93 100644 --- a/analysis.py +++ b/analysis.py @@ -68,21 +68,21 @@ def interpolate_intersection(intersection_indices, timestamps, prices1, prices2) """ Returns the indices of where two arrays' values intersects """ -def find_intersections(prices1, prices2): +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, len(prices1)): + 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): # TODO, consider on the 0 case + 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: @@ -92,3 +92,40 @@ def find_intersections(prices1, prices2): 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) + +
\ No newline at end of file @@ -1,24 +1,11 @@ from dash import Dash, dcc, html, Input, Output -from analysis import calc_emas, find_intersections, interpolate_intersection +from analysis import calc_emas, find_intersections, interpolate_intersection, calculate_profit import plotly.graph_objects as go import json import datetime app = Dash(__name__) - -app.layout = html.Div([ - html.H4('Interactive color selection with simple Dash example'), - html.P("Select color:"), - dcc.Dropdown( - id="dropdown", - options=['Gold', 'MediumTurquoise', 'LightGreen'], - value='Gold', - clearable=False, - ), - dcc.Graph(id="graph"), -]) - # pull stock data from json files timestamps_file = open('timestamps.json', 'r') timestamps_file_data = timestamps_file.read() @@ -31,7 +18,7 @@ prices = json.loads(prices_file.read()) ema_5 = calc_emas(5, prices) ema_13 = calc_emas(13, prices) -intersection_indices = find_intersections(ema_5, ema_13) +intersection_indices = find_intersections(ema_5, ema_13, offset=13) # offset so don't calculate the SMA days interpolated_intersections = [interpolate_intersection(indices, timestamps, ema_5, ema_13) for indices in intersection_indices] intersected_x = [] intersected_y = [] @@ -39,7 +26,36 @@ for x,y in interpolated_intersections: intersected_x.append(x) intersected_y.append(y) +profit = calculate_profit(ema_5, ema_13, prices, timestamps, 13) +buy_info = profit[-2] +buy_x = [] +buy_y = [] +for x,y,_ in buy_info: + buy_x.append(x) + buy_y.append(y) +sell_info = profit[-1] +sell_x = [] +sell_y = [] +for x,y,_ in sell_info: + sell_x.append(x) + sell_y.append(y) + +print("Result Analysis:\n", "Percent gain/loss:\t", profit[0]) +percent_gain = profit[0] * 100 + +app.layout = html.Div([ + html.H4('Interactive color selection with simple Dash example'), + html.P("Select color:"), + dcc.Dropdown( + id="dropdown", + options=['Gold', 'MediumTurquoise', 'LightGreen'], + value='Gold', + clearable=False, + ), + dcc.Graph(id="graph"), + html.P("If bought and sold on these signals, the percent gain/loss would be: " + str(round(percent_gain, 4))) +]) @app.callback( Output("graph", "figure"), @@ -47,10 +63,12 @@ for x,y in interpolated_intersections: def display_color(color): fig = go.Figure( [ - go.Scatter(name='Price', x=timestamps, y=prices, line=dict(color='rgb(0, 255, 255)'), mode='lines'), # prices - go.Scatter(name='5 day EMA', x=timestamps, y=ema_5, line=dict(color='rgb(0, 255, 0)'), mode='lines'), # 5 ema line - go.Scatter(name='13 day EMA', x=timestamps, y=ema_13, line=dict(color='rgb(0, 0, 255)'), mode='lines'), # 13 ema line - go.Scatter(name='EMA Intersections', x=intersected_x, y=intersected_y, line=dict(color='rgb(255, 0, 0)'), mode='markers') # EMA intersection points + go.Scatter(name='Price', x=timestamps, y=prices, line=dict(color='rgb(0, 255, 0)'), mode='lines'), + # go.Scatter(name='5 day EMA', x=timestamps, y=ema_5, line=dict(color='rgb(0, 255, 0)'), mode='lines'), + # go.Scatter(name='13 day EMA', x=timestamps, y=ema_13, line=dict(color='rgb(0, 0, 255)'), mode='lines'), + # go.Scatter(name='EMA Intersections', x=intersected_x, y=intersected_y, line=dict(color='rgb(255, 0, 0)'), mode='markers') + go.Scatter(name='Buys', x=buy_x, y=buy_y, line=dict(color='rgb(0, 0, 255)'), mode='markers', marker_size=10), + go.Scatter(name='Sells', x=sell_x, y=sell_y, line=dict(color='rgb(255, 255, 0)'), mode='markers', marker_size=10), ] ) return fig |