goldhand 10.0__py3-none-any.whl → 12.7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of goldhand might be problematic. Click here for more details.

goldhand/__init__.py CHANGED
@@ -1,5 +1,5 @@
1
1
  from .tw import *
2
2
  from .stocks import *
3
3
  from .helpers import *
4
- from .video import *
5
-
4
+ from .backtest import *
5
+ from .strategy_rsi import *
goldhand/backtest.py ADDED
@@ -0,0 +1,112 @@
1
+ from IPython.display import display
2
+ import numpy as np
3
+ import pandas as pd
4
+ import plotly.graph_objects as go
5
+ import plotly.express as px
6
+
7
+ class Backtest:
8
+ def __init__(self, data, strategy_function, **kwargs):
9
+ self.data = data
10
+ self.strategy_function = strategy_function
11
+ self.additional_params = kwargs
12
+ self.add_trades()
13
+ self.summary_of_trades()
14
+
15
+
16
+ def add_trades(self):
17
+ self.trades = self.strategy_function(self.data, **self.additional_params)
18
+
19
+
20
+ def summary_of_trades(self):
21
+ self.trades_summary = {
22
+ 'number_of_trades' : self.trades.shape[0],
23
+
24
+ 'average_res(%)' : round(((self.trades['result'].mean()-1)*100),2),
25
+ 'median_res(%)': round(((self.trades['result'].median()-1)*100),2),
26
+ 'cumulative_result': list(np.cumprod(self.trades['result'], axis=0))[-1],
27
+ 'trade_results': ' # '.join([ str(round(((x-1)*100),2)) for x in self.trades['result']]),
28
+
29
+ 'profitable_trade_results': ' # '.join([ str(round(((x-1)*100),2)) for x in self.trades['result'] if x>=1]),
30
+
31
+ 'profitable_trades_mean' : round((( np.mean([x for x in self.trades['result'] if x>=1]) -1)*100),2),
32
+ 'profitable_trades_median' : round((( np.median([x for x in self.trades['result'] if x>=1])-1)*100),2),
33
+
34
+ 'looser_trade_results': ' # '.join([ str(round(((x-1)*100),2)) for x in self.trades['result'] if x<1]),
35
+
36
+ 'looser_trades_mean' : round((( np.mean([x for x in self.trades['result'] if x<1])-1)*100),2),
37
+ 'looser_trades_median' : round((( np.median([x for x in self.trades['result'] if x<1])-1)*100),2),
38
+
39
+
40
+ 'average_trade_len(days)' : self.trades['days_in_trade'].mean(),
41
+ 'median_trade_len(days)' : self.trades['days_in_trade'].median(),
42
+
43
+ 'win_ratio(%)' : round(((sum(self.trades['result'] >1) / self.trades.shape[0])*100),2),
44
+ 'number_of_win_trades': sum(self.trades['result'] >1),
45
+ 'number_of_lost_trades': (self.trades.shape[0] - sum(self.trades['result'] >1)),
46
+
47
+ 'max_gain(%)' : round(((self.trades['result'].max()-1)*100),2),
48
+ 'max_lost(%)' : round(((self.trades['result'].min()-1)*100),2),
49
+
50
+ 'first_trade_buy' : min(self.trades['buy_date'])
51
+
52
+ }
53
+ self.trades_summary.update(self.additional_params)
54
+
55
+ def show_trades(self):
56
+ tdf = self.data
57
+ fig = go.Figure(data=go.Ohlc(x=tdf['date'], open=tdf['open'], high=tdf['high'], low=tdf['low'],close=tdf['close']))
58
+ fig.add_trace( go.Scatter(x=tdf['date'], y=tdf['sma_50'], opacity =0.5, line=dict(color='lightblue', width = 2) , name = 'SMA 50') )
59
+ fig.add_trace( go.Scatter(x=tdf['date'], y=tdf['sma_200'], opacity =0.7, line=dict(color='red', width = 2.5) , name = 'SMA 200') )
60
+ fig.update_layout(showlegend=False, plot_bgcolor='white', height=800, title= f"Closed trades" )
61
+ fig.update(layout_xaxis_rangeslider_visible=False)
62
+ fig.update_xaxes( mirror=True, ticks='outside', showline=True, linecolor='black', gridcolor='lightgrey')
63
+ fig.update_yaxes( mirror=True, ticks='outside', showline=True, linecolor='black', gridcolor='lightgrey')
64
+
65
+ for index, row in self.trades.iterrows():
66
+ buy_date= row['buy_date']
67
+ sell_date= row['sell_date']
68
+ buy_price = row['buy_price']
69
+ sell_price = row['sell_price']
70
+ trade_id = row['trade_id']
71
+ status = row['status']
72
+ triangle_color = 'green' if row['result'] >1 else 'red'
73
+
74
+ rise = (row['result'] -1)*100
75
+
76
+ if rise>100:
77
+ if status =='closed':
78
+ result = f'Up:{round(((rise+100)/100), 2)}x'
79
+ else:
80
+ result = f'Up:{round(((rise+100)/100), 2)}x <br> Still open'
81
+ else:
82
+ if status =='closed':
83
+ result = f"{round(((row['result']-1)*100),2) }%"
84
+ else:
85
+ result = f"{round(((row['result']-1)*100),2) }% <br> Still open"
86
+
87
+
88
+ # add buy
89
+ buy_point=(buy_date, buy_price)
90
+ triangle_trace = go.Scatter(x=[buy_point[0]], y=[buy_point[1]], mode='markers', marker=dict(symbol='triangle-up', size=16, color=triangle_color))
91
+ fig.add_trace(triangle_trace)
92
+ fig.add_annotation( x=buy_date, y=buy_price, text=f"Buy: ${round(buy_price, 2)}<br>#{trade_id}", hovertext = f"Buy: ${round(buy_price, 2)}<br>#{trade_id}", showarrow=True, align="center", bordercolor="#c7c7c7", font=dict(family="Courier New, monospace", size=12, color= triangle_color ), borderwidth=2, borderpad=4, bgcolor="#f4fdff", opacity=0.8, arrowhead=2, arrowsize=1, arrowwidth=1, ax=30,ay=30)
93
+
94
+ # add sell
95
+ sell_point=(sell_date, sell_price)
96
+ triangle_trace = go.Scatter(x=[sell_point[0]], y=[sell_point[1]], mode='markers', marker=dict(symbol='triangle-down', size=16, color=triangle_color))
97
+ fig.add_trace(triangle_trace)
98
+ fig.add_annotation( x=sell_date, y=sell_price, text=f"Sell: ${round(sell_price, 2)}<br>#{trade_id}, {result}", hovertext = f"Sell: ${round(sell_price, 2)}<br>#{trade_id}, {result}" ,showarrow=True, align="center", bordercolor="#c7c7c7", font=dict(family="Courier New, monospace", size=12, color= triangle_color ), borderwidth=2, borderpad=4, bgcolor="#f4fdff", opacity=0.8, arrowhead=2, arrowsize=1, arrowwidth=1, ax=-30,ay=-30)
99
+
100
+ # add reactangle
101
+ fig.add_shape(type="rect", x0=buy_point[0], y0=buy_point[1], x1=sell_point[0], y1=sell_point[1],line=dict(color= triangle_color ,width=2,),fillcolor="LightSkyBlue", opacity=0.3, label=dict( text=f"{result}<br>{row['days_in_trade']} days", textposition="bottom center", font=dict(size=13, color =triangle_color, family="Times New Roman")))
102
+
103
+ # set size
104
+ fig.update_layout(showlegend=False, plot_bgcolor='white', )
105
+
106
+ return(fig)
107
+
108
+
109
+ def summarize_strategy(self):
110
+ display(pd.DataFrame(self.trades_summary, index=['Strategy summary']).T)
111
+ self.show_trades().show()
112
+ display(self.trades)
goldhand/stocks.py CHANGED
@@ -10,31 +10,46 @@ import json
10
10
  import cloudscraper
11
11
 
12
12
  class GoldHand:
13
- def __init__(self, ticker, static_plot =False):
13
+ def __init__(self, ticker, ad_ticker=True, range='18y', interval='1d'):
14
14
  self.scraper = cloudscraper.create_scraper()
15
+ self.ad_ticker = ad_ticker
16
+ self.range = range
17
+ self.interval = interval
15
18
  self.ticker = ticker
16
19
  self.df = None
17
- self.static_plot = static_plot
18
20
  self.download_historical_data()
19
21
 
20
22
 
21
- def get_olhc(self, ticker, scraper = cloudscraper.create_scraper(), ad_ticker=False, range='18y', interval='1d'):
22
- response = scraper.get(f"https://query1.finance.yahoo.com/v8/finance/chart/{ticker}?interval={interval}&range={range}")
23
+ def get_olhc(self):
24
+ #scraper = cloudscraper.create_scraper()
25
+ response = self.scraper.get(f"https://query1.finance.yahoo.com/v8/finance/chart/{self.ticker}?interval={self.interval}&range={self.range}")
23
26
  t= response.json()
24
27
  df = pd.DataFrame(t['chart']['result'][0]['indicators']['quote'][0])
25
28
  df['date'] = pd.to_datetime(t['chart']['result'][0]['timestamp'], unit='s').date
26
29
  df = df[['date', 'open', 'low', 'high', 'close', 'volume']]
27
- if ad_ticker:
28
- df['ticker'] = ticker
30
+ if self.ad_ticker:
31
+ df['ticker'] = self.ticker
29
32
  return(df)
33
+
34
+ def smma(self, data, window, colname):
35
+ hl2 = data['hl2'].values
36
+ smma_values = [hl2[0]]
37
+
38
+ for i in range(1, len(hl2)):
39
+ smma_val = (smma_values[-1] * (window - 1) + hl2[i]) / window
40
+ smma_values.append(smma_val)
41
+
42
+ data[colname] = smma_values
43
+ return data
30
44
 
31
45
 
32
46
 
33
47
  def download_historical_data(self):
34
48
  # Download historical stock data for the last year
35
- self.df = self.get_olhc(self.ticker, self.scraper)
49
+ self.df = self.get_olhc()
36
50
  self.df.columns = self.df.columns.str.lower()
37
-
51
+ self.df['hl2'] = (self.df['high'] + self.df['low'])/2
52
+
38
53
  # Rsi
39
54
  self.df['rsi'] = ta.rsi(self.df['close'], 14)
40
55
 
@@ -102,50 +117,30 @@ class GoldHand:
102
117
 
103
118
  states = self.df[self.df['local']!='']['local'].index.to_list()
104
119
 
105
- if self.static_plot:
106
-
107
- for i in range(1,len(states)):
108
- prev = self.df.loc[states[i-1], 'local']
109
- current= self.df.loc[states[i], 'local']
110
- prev_high = self.df.loc[states[i-1], 'high']
111
- prev_low = self.df.loc[states[i-1], 'low']
112
- current_high = self.df.loc[states[i], 'high']
113
- current_low = self.df.loc[states[i], 'low']
114
- if current == 'maximum':
115
- # rise
116
- rise = (current_high/ prev_low -1)*100
117
- if rise>100:
118
- self.df.loc[states[i], 'local_text'] = f'Up:{round(((rise+100)/100), 2)}x<br>${round(current_high, 2)}'
119
- else:
120
- self.df.loc[states[i], 'local_text'] = f'Up:{round(rise, 2)}%<br>${round(current_high, 2)}'
120
+
121
+ for i in range(1,len(states)):
122
+ prev = self.df.loc[states[i-1], 'local']
123
+ current= self.df.loc[states[i], 'local']
124
+ prev_high = self.df.loc[states[i-1], 'high']
125
+ prev_low = self.df.loc[states[i-1], 'low']
126
+ current_high = self.df.loc[states[i], 'high']
127
+ current_low = self.df.loc[states[i], 'low']
128
+ if current == 'maximum':
129
+ # rise
130
+ rise = (current_high/ prev_low -1)*100
131
+ if rise>100:
132
+ self.df.loc[states[i], 'local_text'] = f'🚀🌌{round(((rise+100)/100), 2)}x<br>${round(current_high, 2)}'
121
133
  else:
122
- fall = round((1-(current_low / prev_high))*100, 2)
123
- self.df.loc[states[i], 'local_text'] = f'Down:{fall}%<br>${round(current_low, 2)}'
124
- else:
125
-
126
- for i in range(1,len(states)):
127
- prev = self.df.loc[states[i-1], 'local']
128
- current= self.df.loc[states[i], 'local']
129
- prev_high = self.df.loc[states[i-1], 'high']
130
- prev_low = self.df.loc[states[i-1], 'low']
131
- current_high = self.df.loc[states[i], 'high']
132
- current_low = self.df.loc[states[i], 'low']
133
- if current == 'maximum':
134
- # rise
135
- rise = (current_high/ prev_low -1)*100
136
- if rise>100:
137
- self.df.loc[states[i], 'local_text'] = f'🚀🌌{round(((rise+100)/100), 2)}x<br>${round(current_high, 2)}'
138
- else:
139
- self.df.loc[states[i], 'local_text'] = f'🚀{round(rise, 2)}%<br>${round(current_high, 2)}'
134
+ self.df.loc[states[i], 'local_text'] = f'🚀{round(rise, 2)}%<br>${round(current_high, 2)}'
135
+ else:
136
+ fall = round((1-(current_low / prev_high))*100, 2)
137
+ if fall < 30:
138
+ temj = '💸'
139
+ elif fall < 50:
140
+ temj = '💸'
140
141
  else:
141
- fall = round((1-(current_low / prev_high))*100, 2)
142
- if fall < 30:
143
- temj = '💸'
144
- elif fall < 50:
145
- temj = '💸'
146
- else:
147
- temj = '😭💔'
148
- self.df.loc[states[i], 'local_text'] = f'{temj}{fall}%<br>${round(current_low, 2)}'
142
+ temj = '😭💔'
143
+ self.df.loc[states[i], 'local_text'] = f'{temj}{fall}%<br>${round(current_low, 2)}'
149
144
 
150
145
 
151
146
  def plotly_last_year(self, plot_title, plot_height=900):
@@ -160,51 +155,77 @@ class GoldHand:
160
155
  min_price = row['low']
161
156
  max_price = row['high']
162
157
  if direction == 'maximum':
163
- fig.add_annotation( x=tdate, y=max_price, text=local_text, showarrow=True,
164
- align="center", bordercolor="#c7c7c7",
165
- font=dict(family="Courier New, monospace", size=16, color="#214e34" ), borderwidth=2,
166
- borderpad=4,
167
- bgcolor="#f4fdff",
168
- opacity=0.8,
169
- arrowhead=2,
170
- arrowsize=1,
171
- arrowwidth=1,
172
- ax=-45,ay=-45)
158
+ fig.add_annotation( x=tdate, y=max_price, text=local_text, showarrow=True, align="center", bordercolor="#c7c7c7", font=dict(family="Courier New, monospace", size=16, color="#214e34" ), borderwidth=2, borderpad=4, bgcolor="#f4fdff", opacity=0.8, arrowhead=2, arrowsize=1, arrowwidth=1, ax=-45,ay=-45)
173
159
 
174
160
  if direction == 'minimum':
175
- fig.add_annotation( x=tdate, y=min_price, text=local_text, showarrow=True,
176
- align="center", bordercolor="#c7c7c7",
177
- font=dict(family="Courier New, monospace", size=16, color="red" ), borderwidth=2,
178
- borderpad=4,
179
- bgcolor="#f4fdff",
180
- opacity=0.8,
181
- arrowhead=2,
182
- arrowsize=1,
183
- arrowwidth=1,
184
- ax=45,ay=45)
185
-
186
- fig.update_layout(showlegend=False, plot_bgcolor='white', height=plot_height, title= plot_title)
187
-
188
- fig.update_xaxes(
189
- mirror=True,
190
- ticks='outside',
191
- showline=True,
192
- linecolor='black',
193
- gridcolor='lightgrey'
194
- )
195
- fig.update_yaxes(
196
- mirror=True,
197
- ticks='outside',
198
- showline=True,
199
- linecolor='black',
200
- gridcolor='lightgrey'
201
- )
161
+ fig.add_annotation( x=tdate, y=min_price, text=local_text, showarrow=True, align="center", bordercolor="#c7c7c7", font=dict(family="Courier New, monospace", size=16, color="red" ), borderwidth=2, borderpad=4, bgcolor="#f4fdff", opacity=0.8, arrowhead=2, arrowsize=1, arrowwidth=1, ax=45,ay=45)
162
+
163
+ fig.update_layout(showlegend=False, plot_bgcolor='white', height=plot_height, title= plot_title)
164
+
165
+ fig.update_xaxes( mirror=True, ticks='outside', showline=True, linecolor='black', gridcolor='lightgrey' )
166
+ fig.update_yaxes( mirror=True, ticks='outside', showline=True, linecolor='black', gridcolor='lightgrey')
202
167
  fig.update(layout_xaxis_rangeslider_visible=False)
203
168
  fig.add_trace( go.Scatter(x=tdf['date'], y=tdf['sma_50'], opacity =0.5, line=dict(color='lightblue', width = 2) , name = 'SMA 50') )
204
169
  fig.add_trace( go.Scatter(x=tdf['date'], y=tdf['sma_200'], opacity =0.7, line=dict(color='red', width = 2.5) , name = 'SMA 200') )
205
170
  return(fig)
206
171
 
172
+ def plot_goldhand_line(self, plot_title, plot_height=900):
173
+
174
+ data = self.df.copy()
175
+ # Apply SMMA to the dataframe
176
+ data = self.smma(data, 15, 'v1')
177
+ data = self.smma(data, 19, 'v2')
178
+ data = self.smma(data, 25, 'v3')
179
+ data = self.smma(data, 29, 'v4')
180
+
181
+ data['color'] = 'grey' # Set default color to grey
182
+
183
+ # Update color based on conditions
184
+ data.loc[(data['v4'] < data['v3']) & (data['v3'] < data['v2']) & (data['v2'] < data['v1']), 'color'] = 'gold'
185
+ data.loc[(data['v1'] < data['v2']) & (data['v2'] < data['v3']) & (data['v3'] < data['v4']), 'color'] = 'blue'
186
+
187
+ # Identify rows where color changes compared to the previous row
188
+ data['color_change'] = data['color'] != data['color'].shift(1)
189
+
190
+ # Create a 'group' column and increase the value only when there's a color change
191
+ data['group'] = (data['color_change']).cumsum()
192
+
193
+ tdf = data.tail(800)
207
194
 
195
+ fig = go.Figure(data=go.Ohlc(x=tdf['date'], open=tdf['open'], high=tdf['high'], low=tdf['low'],close=tdf['close']))
196
+
197
+ fig.update_xaxes( mirror=True, ticks='outside', showline=True, linecolor='black', gridcolor='lightgrey' )
198
+ fig.update_yaxes( mirror=True, ticks='outside', showline=True, linecolor='black', gridcolor='lightgrey')
199
+ fig.update(layout_xaxis_rangeslider_visible=False)
200
+
201
+ for group_id in tdf['group'].unique():
202
+ if group_id ==tdf['group'].unique().max():
203
+ indices = tdf[tdf['group'] == group_id].index.to_list()
204
+ else:
205
+ indices = tdf[tdf['group'] == group_id].index.to_list()
206
+ indices.append(indices[-1]+1)
207
+
208
+
209
+ group_df = tdf.loc[indices]
210
+
211
+ group_color = group_df['color'].iloc[0]
212
+ color_dict = {'gold' : 'rgba(255, 215, 0, 0.4)' , 'grey' : 'rgba(128, 128 ,128, 0.4)' , 'blue' : 'rgba(0, 0, 255, 0.4)' }
213
+
214
+ # Create v1 and v4 traces
215
+ trace_v1 = go.Scatter(x=group_df['date'], y=group_df['v1'], mode='lines', name='v1', line=dict(color=color_dict[group_color]) )
216
+ trace_v4 = go.Scatter(x=group_df['date'], y=group_df['v4'], mode='lines', name='v4', line=dict(color=color_dict[group_color]), fill='tonexty', fillcolor =color_dict[group_color])
217
+
218
+ # Add candlestick trace and additional lines to the figure
219
+ fig.add_trace(trace_v1)
220
+ fig.add_trace(trace_v4)
221
+
222
+ fig.update_layout(showlegend=False, plot_bgcolor='white', height=plot_height, title= plot_title)
223
+ return(fig)
224
+
225
+
226
+
227
+
208
228
  # https://stackoverflow.com/questions/71411995/pandas-plotly-secondary-graph-needs-to-be-to-rsi
209
229
 
210
- #https://wire.insiderfinance.io/plot-candlestick-rsi-bollinger-bands-and-macd-charts-using-yfinance-python-api-1c2cb182d147
230
+ #https://wire.insiderfinance.io/plot-candlestick-rsi-bollinger-bands-and-macd-charts-using-yfinance-python-api-1c2cb182d147
231
+
@@ -0,0 +1,166 @@
1
+ from IPython.display import display
2
+ import numpy as np
3
+ import pandas as pd
4
+ import plotly.graph_objects as go
5
+ from plotly.subplots import make_subplots
6
+ import plotly.express as px
7
+ from goldhand import *
8
+
9
+
10
+ def rsi_strategy(data, buy_threshold = 30, sell_threshold = 70):
11
+
12
+ in_trade = False # Flag to track if already in a trade
13
+ trade_id = 1
14
+ all_trades = []
15
+
16
+ temp_trade = {}
17
+
18
+ for i in range(1, len(data)):
19
+ # Check if not already in a trade
20
+ if not in_trade:
21
+ # Generate buy signal
22
+ if data['rsi'][i] < buy_threshold:
23
+
24
+ temp_trade['buy_price'] = data['close'][i]
25
+ temp_trade['trade_id'] = trade_id
26
+ temp_trade['status'] = 'open'
27
+ temp_trade.update(dict(data.iloc[i].add_prefix('buy_')))
28
+ in_trade = True # Set flag to indicate in a trade
29
+ else:
30
+ # Generate sell signal
31
+ if data['rsi'][i] > sell_threshold:
32
+
33
+ temp_trade['sell_price'] = data['close'][i]
34
+ temp_trade['trade_id'] = trade_id
35
+ temp_trade['status'] = 'closed'
36
+
37
+ temp_trade.update(dict(data.iloc[i].add_prefix('sell_')))
38
+
39
+ # calculate results
40
+ temp_trade['result'] = temp_trade['sell_price'] / temp_trade['buy_price']
41
+ temp_trade['days_in_trade'] = (temp_trade['sell_date'] - temp_trade['buy_date']).days
42
+
43
+
44
+
45
+ in_trade = False # Reset flag to indicate not in a trade
46
+ trade_id +=1
47
+ all_trades.append(temp_trade)
48
+ temp_trade = {}
49
+ if temp_trade:
50
+ temp_trade['sell_price'] = data['close'][i]
51
+ temp_trade['trade_id'] = trade_id
52
+ temp_trade['sell_date'] = data['date'][i]
53
+
54
+ temp_trade['result'] = temp_trade['sell_price'] / temp_trade['buy_price']
55
+ temp_trade['days_in_trade'] = (temp_trade['sell_date'] - temp_trade['buy_date']).days
56
+ all_trades.append(temp_trade)
57
+
58
+ res_df = pd.DataFrame(all_trades)
59
+ # change orders
60
+
61
+ all_col = res_df.columns.tolist()
62
+ first = ['result', 'buy_price', 'sell_price', 'buy_date', 'sell_date', 'days_in_trade']
63
+ first.extend([x for x in all_col if x not in first])
64
+ res_df = res_df[first]
65
+ return(res_df)
66
+
67
+
68
+
69
+ def show_indicator_rsi_strategy(ticker, buy_threshold = 30, sell_threshold = 70):
70
+
71
+ tdf = GoldHand(ticker).df
72
+ backtest = Backtest( tdf, rsi_strategy, buy_threshold=buy_threshold, sell_threshold=sell_threshold)
73
+ trades =backtest.trades
74
+
75
+ # Create subplots with shared x-axis and custom heights
76
+ fig = make_subplots(rows=2, cols=1, shared_xaxes=True, vertical_spacing=0.1, subplot_titles=["Price Chart", "RSI"], row_heights=[0.7, 0.3])
77
+
78
+ # Add OHLC candlestick chart
79
+ fig.add_trace(go.Ohlc(x=tdf['date'], open=tdf['open'], high=tdf['high'], low=tdf['low'], close=tdf['close']), row=1, col=1)
80
+
81
+ # Add SMA lines
82
+ fig.add_trace(go.Scatter(x=tdf['date'], y=tdf['sma_50'], opacity=0.5, line=dict(color='lightblue', width=2), name='SMA 50'), row=1, col=1)
83
+ fig.add_trace(go.Scatter(x=tdf['date'], y=tdf['sma_200'], opacity=0.7, line=dict(color='red', width=2.5), name='SMA 200'), row=1, col=1)
84
+
85
+ # Add trade points and annotations
86
+ for index, row in trades.iterrows():
87
+ buy_date = row['buy_date']
88
+ sell_date = row['sell_date']
89
+ buy_price = row['buy_price']
90
+ sell_price = row['sell_price']
91
+ trade_id = row['trade_id']
92
+ status = row['status']
93
+ triangle_color = 'green' if row['result'] > 1 else 'red'
94
+
95
+ rise = (row['result'] - 1) * 100
96
+
97
+ if rise > 100:
98
+ if status == 'closed':
99
+ result = f'Up:{round(((rise + 100) / 100), 2)}x'
100
+ else:
101
+ result = f'Up:{round(((rise + 100) / 100), 2)}x <br> Still open'
102
+ else:
103
+ if status == 'closed':
104
+ result = f"{round(((row['result'] - 1) * 100), 2)}%"
105
+ else:
106
+ result = f"{round(((row['result'] - 1) * 100), 2)}% <br> Still open"
107
+
108
+ # add buy
109
+ buy_point = (buy_date, buy_price)
110
+ triangle_trace = go.Scatter(x=[buy_point[0]], y=[buy_point[1]], mode='markers',
111
+ marker=dict(symbol='triangle-up', size=16, color=triangle_color))
112
+ fig.add_trace(triangle_trace)
113
+ fig.add_annotation(x=buy_date, y=buy_price, text=f"Buy: ${round(buy_price, 2)}<br>#{trade_id}",
114
+ showarrow=True, align="center", bordercolor="#c7c7c7",
115
+ font=dict(family="Courier New, monospace", size=12, color=triangle_color),
116
+ borderwidth=2, borderpad=4, bgcolor="#f4fdff", opacity=0.8,
117
+ arrowhead=2, arrowsize=1, arrowwidth=1, ax=30, ay=30,
118
+ hovertext= f"Buy: ${round(buy_price, 2)}")
119
+
120
+ # add sell
121
+ sell_point = (sell_date, sell_price)
122
+ triangle_trace = go.Scatter(x=[sell_point[0]], y=[sell_point[1]], mode='markers',
123
+ marker=dict(symbol='triangle-down', size=16, color=triangle_color))
124
+ fig.add_trace(triangle_trace)
125
+ fig.add_annotation(x=sell_date, y=sell_price,
126
+ text=f"Sell: ${round(sell_price, 2)}<br>#{trade_id}, {result}",
127
+ showarrow=True, align="center", bordercolor="#c7c7c7",
128
+ font=dict(family="Courier New, monospace", size=12, color=triangle_color),
129
+ borderwidth=2, borderpad=4, bgcolor="#f4fdff", opacity=0.8,
130
+ arrowhead=2, arrowsize=1, arrowwidth=1, ax=-30, ay=-30,
131
+ hovertext = f"Sell: ${round(sell_price, 2)}<br>#{trade_id}, {result}")
132
+
133
+ # add rectangle
134
+ fig.add_shape(type="rect", x0=buy_point[0], y0=buy_point[1], x1=sell_point[0], y1=sell_point[1],
135
+ line=dict(color=triangle_color, width=2,), fillcolor="LightSkyBlue", opacity=0.3,
136
+ label=dict(text=f"{result}<br>{row['days_in_trade']} days",
137
+ textposition="bottom center",
138
+ font=dict(size=13, color=triangle_color, family="Times New Roman")))
139
+
140
+ # Update layout
141
+ fig.update_layout(showlegend=False, plot_bgcolor='white', height=800, title=f"Closed trades")
142
+ fig.update(layout_xaxis_rangeslider_visible=False)
143
+
144
+ # Update x-axes and y-axes for the main chart
145
+ fig.update_xaxes(mirror=True, ticks='outside', showline=True, linecolor='black', gridcolor='lightgrey', row=1, col=1)
146
+ fig.update_yaxes(mirror=True, ticks='outside', showline=True, linecolor='black', gridcolor='lightgrey', row=1, col=1)
147
+
148
+ # Update x-axes and y-axes for the RSI subplot
149
+ fig.update_xaxes(mirror=True, ticks='outside', showline=True, linecolor='black', gridcolor='lightgrey', row=2, col=1)
150
+ fig.update_yaxes(mirror=True, ticks='outside', showline=True, linecolor='black', gridcolor='lightgrey', row=2, col=1)
151
+
152
+
153
+
154
+
155
+ # Add RSI line
156
+ fig.add_trace(go.Scatter(x=tdf['date'], y=tdf['rsi'], line=dict(color='green', width=2), name='RSI'), row=2, col=1)
157
+ fig.add_shape(type="line", x0=tdf['date'].min(), x1=tdf['date'].max(), y0=buy_threshold, y1=buy_threshold, line=dict(color="black", width=2, dash="dash"), row=2, col=1)
158
+ fig.add_shape(type="line", x0=tdf['date'].min(), x1=tdf['date'].max(), y0=sell_threshold, y1=sell_threshold, line=dict(color="black", width=2, dash="dash"), row=2, col=1)
159
+
160
+
161
+ # Show the plot
162
+ fig.show()
163
+
164
+
165
+ # Test
166
+ # show_indicator_rsi_strategy('TSLA', 30,80)
goldhand/tw.py CHANGED
@@ -16,7 +16,7 @@ class Tw:
16
16
  self.get_all_crypto()
17
17
 
18
18
  def get_all_stock(self):
19
- data_query = '{"filter":[{"left":"type","operation":"in_range","right":["stock","dr","fund"]},{"left":"subtype","operation":"in_range","right":["common","foreign-issuer","","etf","etf,odd","etf,otc","etf,cfd"]},{"left":"exchange","operation":"in_range","right":["AMEX","NASDAQ","NYSE"]},{"left":"is_primary","operation":"equal","right":true},{"left":"active_symbol","operation":"equal","right":true}],"options":{"lang":"en"},"markets":["america"],"symbols":{"query":{"types":[]},"tickers":[]},"columns":["logoid","name","close","change","change_abs","Recommend.All","volume","Value.Traded","market_cap_basic","price_earnings_ttm","earnings_per_share_basic_ttm","number_of_employees","sector","industry","RSI","SMA50","SMA100","SMA200","BB.lower","BB.upper","Perf.W","Perf.Y","Perf.YTD","Perf.3M","Perf.6M","Perf.1M","High.1M","High.3M","High.6M","price_52_week_high","High.All","description","type","subtype","update_mode","pricescale","minmov","fractional","minmove2","RSI[1]","currency","fundamental_currency_code"],"sort":{"sortBy":"market_cap_basic","sortOrder":"desc"},"range":[0,9000]}'
19
+ data_query = '{"filter":[{"left":"type","operation":"in_range","right":["stock","dr","fund"]},{"left":"subtype","operation":"in_range","right":["common","foreign-issuer","","etf","etf,odd","etf,otc","etf,cfd"]},{"left":"exchange","operation":"in_range","right":["AMEX","NASDAQ","NYSE"]},{"left":"is_primary","operation":"equal","right":true},{"left":"active_symbol","operation":"equal","right":true}],"options":{"lang":"en"},"markets":["america"],"symbols":{"query":{"types":[]},"tickers":[]},"columns":["logoid","name","close","change","change_abs","Recommend.All","volume","Value.Traded","market_cap_basic","price_earnings_ttm","earnings_per_share_basic_ttm","number_of_employees","sector","High.3M","Low.3M","Perf.3M","Perf.5Y","High.1M","Low.1M","High.6M","Low.6M","Perf.6M","beta_1_year","price_52_week_high","price_52_week_low","High.All","Low.All","BB.lower","BB.upper","change|1M","change_abs|1M","change|1W","change_abs|1W","change|240","country","EMA50","EMA100","EMA200","MACD.macd","MACD.signal","Mom","Perf.1M","RSI7","SMA50","SMA100","SMA200","Stoch.RSI.K","Stoch.RSI.D","Perf.W","Perf.Y","Perf.YTD","industry","Perf.All","description","type","subtype","update_mode","pricescale","minmov","fractional","minmove2","Mom[1]","RSI7[1]","Rec.Stoch.RSI","currency","fundamental_currency_code"],"sort":{"sortBy":"market_cap_basic","sortOrder":"desc"},"range":[0,8000]}'
20
20
  response = requests.post('https://scanner.tradingview.com/america/scan', data=data_query)
21
21
  data = response.json()
22
22
  list_elements = list(map(lambda x:x['d'], data['data'] ))
@@ -94,16 +94,7 @@ class Tw:
94
94
 
95
95
  fig = px.bar(secdf, x='name', y='market_cap_basic', title = f"{row_df['Company'].iloc[0]} ({row_df['name'].iloc[0]})<br>{row_df['sector'].iloc[0]} | {row_df['industry'].iloc[0]}", labels={'market_cap_basic':'Market kapitalization'}, text='Company')
96
96
 
97
- fig.add_annotation( x=row_df['name'].iloc[0], y=row_df['market_cap_basic'].iloc[0], text= f"{market_cap}", showarrow=True,
98
- align="center", bordercolor="#c7c7c7",
99
- font=dict(family="Courier New, monospace", size=16, color="#214e34" ), borderwidth=2,
100
- borderpad=4,
101
- bgcolor="#f4fdff",
102
- opacity=0.8,
103
- arrowhead=2,
104
- arrowsize=1,
105
- arrowwidth=1,
106
- ax=65,ay=-45)
97
+ fig.add_annotation( x=row_df['name'].iloc[0], y=row_df['market_cap_basic'].iloc[0], text= f"{market_cap}", showarrow=True, align="center", bordercolor="#c7c7c7", font=dict(family="Courier New, monospace", size=16, color="#214e34" ), borderwidth=2, borderpad=4, bgcolor="#f4fdff", opacity=0.8, arrowhead=2, arrowsize=1, arrowwidth=1, ax=65,ay=-45)
107
98
  fig.update_layout(showlegend=False, plot_bgcolor='white', height=600)
108
99
  fig.show()
109
100
 
@@ -122,19 +113,12 @@ class Tw:
122
113
  fig = px.bar(inddf, x='name', y='market_cap_basic', title = f"{row_df['Company'].iloc[0]} ({row_df['name'].iloc[0]})<br>{row_df['sector'].iloc[0]} | {row_df['industry'].iloc[0]}", labels={'market_cap_basic':'Market kapitalization'}, text='Company')
123
114
 
124
115
 
125
- fig.add_annotation( x=row_df['name'].iloc[0], y=row_df['market_cap_basic'].iloc[0], text= f"{market_cap}", showarrow=True,
126
- align="center", bordercolor="#c7c7c7",
127
- font=dict(family="Courier New, monospace", size=16, color="#214e34" ), borderwidth=2,
128
- borderpad=4,
129
- bgcolor="#f4fdff",
130
- opacity=0.8,
131
- arrowhead=2,
132
- arrowsize=1,
133
- arrowwidth=1,
134
- ax=65,ay=-45)
116
+ fig.add_annotation( x=row_df['name'].iloc[0], y=row_df['market_cap_basic'].iloc[0], text= f"{market_cap}", showarrow=True, align="center", bordercolor="#c7c7c7", font=dict(family="Courier New, monospace", size=16, color="#214e34" ), borderwidth=2, borderpad=4, bgcolor="#f4fdff", opacity=0.8, arrowhead=2, arrowsize=1, arrowwidth=1, ax=65,ay=-45)
135
117
  fig.update_layout(showlegend=False, plot_bgcolor='white', height=600)
136
118
  fig.show()
137
119
 
138
120
 
139
121
 
140
- tw = Tw()
122
+ #tw = Tw()
123
+ #print(tw.stock.head(1).T)
124
+ #print(tw.crypto.head(1).T)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: goldhand
3
- Version: 10.0
3
+ Version: 12.7
4
4
  Summary: A package working with financial data
5
5
  Home-page: https://github.com/misrori/goldhand
6
6
  Author: Mihaly
@@ -0,0 +1,10 @@
1
+ goldhand/__init__.py,sha256=PYVuqK8lz7FmiWuiBngkqB1SBTUxA002In9d4z1OESA,115
2
+ goldhand/backtest.py,sha256=3TTN98Yt_CIgCdt3vSLx-fmDieJZvWr2K_HvFAqgPJg,6124
3
+ goldhand/helpers.py,sha256=l9yn0kVTiwfUR8sI5nH1QFx6dYikaUQgRA227Ox7hs0,6130
4
+ goldhand/stocks.py,sha256=0MnjAex2A2c06JHinToKHBAvUJvYtDFXxtGudqBux6o,10521
5
+ goldhand/strategy_rsi.py,sha256=X38rjkjcph_D7U1CSh8Ismc8CFwhfr3rTWc7VinLIv8,7567
6
+ goldhand/tw.py,sha256=K8MwMDkW5JtBFBG0qcPzj8OVx2OhDjrOH2UGo6nwtSs,8375
7
+ goldhand-12.7.dist-info/METADATA,sha256=RYqbk7_AKvGicD-vqX6GycP9SWQ2C6PJZbyhmJDO4Mo,1952
8
+ goldhand-12.7.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
9
+ goldhand-12.7.dist-info/top_level.txt,sha256=siEJ2_a_Fx_7hqRI4Ms6SzCelbXrK_1H_eOF8KAaMdA,9
10
+ goldhand-12.7.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.41.3)
2
+ Generator: bdist_wheel (0.42.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
goldhand/test.py DELETED
@@ -1,10 +0,0 @@
1
- from tw import *
2
- from stocks import *
3
- from video import *
4
-
5
- tw =Tw()
6
- # stock_ticker = "AMD"
7
- # t = GoldHand(stock_ticker)
8
- # p = t.plotly_last_year(tw.get_plotly_title(stock_ticker))
9
- # p.update_layout(height=1080, width=1920)
10
- # p.write_image("fig2.png", )
goldhand/video.py DELETED
File without changes
@@ -1,10 +0,0 @@
1
- goldhand/__init__.py,sha256=emyQ10OQsNR6j0i7vSedLP2c-3SXr4tZKK9Xz0twW9s,85
2
- goldhand/helpers.py,sha256=l9yn0kVTiwfUR8sI5nH1QFx6dYikaUQgRA227Ox7hs0,6130
3
- goldhand/stocks.py,sha256=bmpDEXfIRMhgYOnyyOUiNRkKAxSLN1TlVZLj2hkUw1A,9085
4
- goldhand/test.py,sha256=zXeBIeaBU5GCypO1NpcqitImCBTII2xVDGmBcbYNzns,253
5
- goldhand/tw.py,sha256=U6B-DRLjlFN-cWvnBsEuw4o5XMLynhycg0c5de76uqI,8466
6
- goldhand/video.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- goldhand-10.0.dist-info/METADATA,sha256=d9YWTibKaZERt13oeWf8hKx_BqSO3AYzRpCrEn_vOeg,1952
8
- goldhand-10.0.dist-info/WHEEL,sha256=Xo9-1PvkuimrydujYJAjF7pCkriuXBpUPEjma1nZyJ0,92
9
- goldhand-10.0.dist-info/top_level.txt,sha256=siEJ2_a_Fx_7hqRI4Ms6SzCelbXrK_1H_eOF8KAaMdA,9
10
- goldhand-10.0.dist-info/RECORD,,