goldhand 14.2__py3-none-any.whl → 15.1__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/backtest.py +14 -5
- goldhand/strategy_goldhand_line.py +34 -16
- goldhand/strategy_rsi.py +21 -21
- goldhand/tw.py +4 -2
- {goldhand-14.2.dist-info → goldhand-15.1.dist-info}/METADATA +1 -1
- goldhand-15.1.dist-info/RECORD +11 -0
- goldhand-14.2.dist-info/RECORD +0 -11
- {goldhand-14.2.dist-info → goldhand-15.1.dist-info}/WHEEL +0 -0
- {goldhand-14.2.dist-info → goldhand-15.1.dist-info}/top_level.txt +0 -0
goldhand/backtest.py
CHANGED
|
@@ -16,13 +16,24 @@ class Backtest:
|
|
|
16
16
|
|
|
17
17
|
def add_trades(self):
|
|
18
18
|
self.trades = self.strategy_function(self.data, **self.additional_params)
|
|
19
|
+
self.trades['ticker'] = self.data['ticker'].iloc[0]
|
|
20
|
+
|
|
21
|
+
# order columns
|
|
22
|
+
all_col = self.trades.columns.tolist()
|
|
23
|
+
first = ['ticker']
|
|
24
|
+
first.extend([x for x in all_col if x not in first])
|
|
25
|
+
self.trades = self.trades[first]
|
|
19
26
|
|
|
20
27
|
|
|
21
28
|
def summary_of_trades(self):
|
|
22
29
|
self.trades_summary = {
|
|
30
|
+
'ticker' : self.data['ticker'].iloc[0],
|
|
23
31
|
'number_of_trades' : self.trades.shape[0],
|
|
24
|
-
|
|
32
|
+
'win_ratio(%)' : round(((sum(self.trades['result'] >1) / self.trades.shape[0])*100),2),
|
|
25
33
|
'average_res(%)' : round(((self.trades['result'].mean()-1)*100),2),
|
|
34
|
+
'average_trade_len(days)' : round(self.trades['days_in_trade'].mean(), 0),
|
|
35
|
+
|
|
36
|
+
|
|
26
37
|
'median_res(%)': round(((self.trades['result'].median()-1)*100),2),
|
|
27
38
|
'cumulative_result': list(np.cumprod(self.trades['result'], axis=0))[-1],
|
|
28
39
|
'trade_results': ' # '.join([ str(round(((x-1)*100),2)) for x in self.trades['result']]),
|
|
@@ -37,11 +48,9 @@ class Backtest:
|
|
|
37
48
|
'looser_trades_mean' : round((( np.mean([x for x in self.trades['result'] if x<1])-1)*100),2),
|
|
38
49
|
'looser_trades_median' : round((( np.median([x for x in self.trades['result'] if x<1])-1)*100),2),
|
|
39
50
|
|
|
40
|
-
|
|
41
|
-
'average_trade_len(days)' : self.trades['days_in_trade'].mean(),
|
|
42
51
|
'median_trade_len(days)' : self.trades['days_in_trade'].median(),
|
|
43
52
|
|
|
44
|
-
|
|
53
|
+
|
|
45
54
|
'number_of_win_trades': sum(self.trades['result'] >1),
|
|
46
55
|
'number_of_lost_trades': (self.trades.shape[0] - sum(self.trades['result'] >1)),
|
|
47
56
|
|
|
@@ -107,6 +116,6 @@ class Backtest:
|
|
|
107
116
|
|
|
108
117
|
|
|
109
118
|
def summarize_strategy(self):
|
|
110
|
-
display(pd.DataFrame(self.trades_summary, index=['Strategy summary']).T)
|
|
119
|
+
display(pd.DataFrame(self.trades_summary, index=['Strategy summary']).T )
|
|
111
120
|
self.show_trades().show()
|
|
112
121
|
display(self.trades)
|
|
@@ -9,6 +9,13 @@ from goldhand import *
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
def goldhand_line_strategy(data):
|
|
12
|
+
"""
|
|
13
|
+
This function implements the goldhand line strategy.
|
|
14
|
+
Parameters:
|
|
15
|
+
data (pandas.DataFrame): The dataframe containing the data.
|
|
16
|
+
Returns:
|
|
17
|
+
res_df (pandas.DataFrame): The dataframe containing the results.
|
|
18
|
+
"""
|
|
12
19
|
|
|
13
20
|
data['hl2'] = (data['high'] + data['low'])/2
|
|
14
21
|
|
|
@@ -91,7 +98,18 @@ def goldhand_line_strategy(data):
|
|
|
91
98
|
return(res_df)
|
|
92
99
|
|
|
93
100
|
|
|
94
|
-
def show_indicator_goldhand_line_strategy(ticker, plot_title = '', ndays=0, plot_height=
|
|
101
|
+
def show_indicator_goldhand_line_strategy(ticker, plot_title = '', ndays=0, plot_height=1000, add_strategy_summary = True):
|
|
102
|
+
"""
|
|
103
|
+
This function shows the goldhand line strategy on a plotly candlestick chart.
|
|
104
|
+
Parameters:
|
|
105
|
+
ticker (str): The ticker of the stock or ETF.
|
|
106
|
+
plot_title (str): The title of the plot.
|
|
107
|
+
ndays (int): The number of days to show. If 0, all data will be shown.
|
|
108
|
+
plot_height (int): The height of the plot.
|
|
109
|
+
add_strategy_summary (bool): If True, the strategy summary will be added to the plot.
|
|
110
|
+
Returns:
|
|
111
|
+
fig (plotly.graph_objects.Figure): The plotly figure.
|
|
112
|
+
"""
|
|
95
113
|
|
|
96
114
|
data = GoldHand(ticker).df
|
|
97
115
|
|
|
@@ -237,21 +255,21 @@ def show_indicator_goldhand_line_strategy(ticker, plot_title = '', ndays=0, plot
|
|
|
237
255
|
fig.update_layout(showlegend=False, plot_bgcolor='white', height=plot_height, title=plot_title)
|
|
238
256
|
fig.update(layout_xaxis_rangeslider_visible=False)
|
|
239
257
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
258
|
+
if add_strategy_summary:
|
|
259
|
+
t= backtest.trades_summary
|
|
260
|
+
trade_text = f"Trades: {t['number_of_trades']}<br>"\
|
|
261
|
+
f"Win ratio: {t['win_ratio(%)']}%<br>"\
|
|
262
|
+
f"Average result: {t['average_res(%)']}%<br>"\
|
|
263
|
+
f"Median result: {t['median_res(%)']}%<br>"\
|
|
264
|
+
f"Average trade lenght: {round(t['average_trade_len(days)'], 0)} days<br>"\
|
|
265
|
+
f"Cumulative result: {round(t['cumulative_result'], 2)}x<br>"\
|
|
266
|
+
f"Profitable trades mean: {t['profitable_trades_mean']}%<br>"\
|
|
267
|
+
f"Profitable trades median: {t['profitable_trades_median']}%<br>"\
|
|
268
|
+
f"Looser trades mean: {t['looser_trades_mean']}%<br>"\
|
|
269
|
+
f"Looser trades median: {t['looser_trades_median']}%<br>"
|
|
270
|
+
|
|
271
|
+
# Add a larger textbox using annotations
|
|
272
|
+
fig.add_annotation( go.layout.Annotation( x=tex_loc[0], y=tex_loc[1], xref='paper', yref='paper', text=trade_text, showarrow=True, arrowhead=4, ax=0, ay=0, bordercolor='black', borderwidth=2, bgcolor='white', align='left', font=dict(size=14, color='black')))
|
|
255
273
|
|
|
256
274
|
# Show the plot
|
|
257
275
|
return (fig)
|
goldhand/strategy_rsi.py
CHANGED
|
@@ -57,6 +57,7 @@ def rsi_strategy(data, buy_threshold = 30, sell_threshold = 70):
|
|
|
57
57
|
all_trades.append(temp_trade)
|
|
58
58
|
|
|
59
59
|
res_df = pd.DataFrame(all_trades)
|
|
60
|
+
|
|
60
61
|
# change orders
|
|
61
62
|
|
|
62
63
|
all_col = res_df.columns.tolist()
|
|
@@ -67,14 +68,14 @@ def rsi_strategy(data, buy_threshold = 30, sell_threshold = 70):
|
|
|
67
68
|
|
|
68
69
|
|
|
69
70
|
|
|
70
|
-
def show_indicator_rsi_strategy(ticker, buy_threshold = 30, sell_threshold = 70, plot_title = '', ndays=0, plot_height=
|
|
71
|
+
def show_indicator_rsi_strategy(ticker, buy_threshold = 30, sell_threshold = 70, plot_title = '', ndays=0, plot_height=1000, add_strategy_summary = True):
|
|
71
72
|
|
|
72
73
|
tdf = GoldHand(ticker).df
|
|
73
74
|
backtest = Backtest( tdf, rsi_strategy, buy_threshold=buy_threshold, sell_threshold=sell_threshold)
|
|
74
75
|
trades =backtest.trades
|
|
75
76
|
|
|
76
|
-
if ndays
|
|
77
|
-
tdf =
|
|
77
|
+
if ndays > 0:
|
|
78
|
+
tdf = tdf.tail(ndays)
|
|
78
79
|
trades = trades.loc[trades['buy_date']>tdf.date.min()]
|
|
79
80
|
|
|
80
81
|
if tdf['high'].max() == max(tdf['high'][0:50]):
|
|
@@ -85,7 +86,7 @@ def show_indicator_rsi_strategy(ticker, buy_threshold = 30, sell_threshold = 70,
|
|
|
85
86
|
|
|
86
87
|
|
|
87
88
|
# Create subplots with shared x-axis and custom heights
|
|
88
|
-
fig = make_subplots(rows=2, cols=1, shared_xaxes=True, vertical_spacing=0.1, subplot_titles=[
|
|
89
|
+
fig = make_subplots(rows=2, cols=1, shared_xaxes=True, vertical_spacing=0.1, subplot_titles=['', "RSI"], row_heights=[0.7, 0.3])
|
|
89
90
|
|
|
90
91
|
# Add OHLC candlestick chart
|
|
91
92
|
fig.add_trace(go.Ohlc(x=tdf['date'], open=tdf['open'], high=tdf['high'], low=tdf['low'], close=tdf['close']), row=1, col=1)
|
|
@@ -150,7 +151,7 @@ def show_indicator_rsi_strategy(ticker, buy_threshold = 30, sell_threshold = 70,
|
|
|
150
151
|
font=dict(size=13, color=triangle_color, family="Times New Roman")))
|
|
151
152
|
|
|
152
153
|
# Update layout
|
|
153
|
-
fig.update_layout(showlegend=False, plot_bgcolor='white', height=
|
|
154
|
+
fig.update_layout(showlegend=False, plot_bgcolor='white', height=plot_height, title=plot_title)
|
|
154
155
|
fig.update(layout_xaxis_rangeslider_visible=False)
|
|
155
156
|
|
|
156
157
|
# Update x-axes and y-axes for the main chart
|
|
@@ -161,22 +162,21 @@ def show_indicator_rsi_strategy(ticker, buy_threshold = 30, sell_threshold = 70,
|
|
|
161
162
|
fig.update_xaxes(mirror=True, ticks='outside', showline=True, linecolor='black', gridcolor='lightgrey', row=2, col=1)
|
|
162
163
|
fig.update_yaxes(mirror=True, ticks='outside', showline=True, linecolor='black', gridcolor='lightgrey', row=2, col=1)
|
|
163
164
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
165
|
+
if add_strategy_summary:
|
|
166
|
+
t= backtest.trades_summary
|
|
167
|
+
trade_text = f"Trades: {t['number_of_trades']}<br>"\
|
|
168
|
+
f"Win ratio: {t['win_ratio(%)']}%<br>"\
|
|
169
|
+
f"Average result: {t['average_res(%)']}%<br>"\
|
|
170
|
+
f"Median result: {t['median_res(%)']}%<br>"\
|
|
171
|
+
f"Average trade length: {round(t['average_trade_len(days)'], 0)} days<br>"\
|
|
172
|
+
f"Cumulative result: {round(t['cumulative_result'], 2)}x<br>"\
|
|
173
|
+
f"Profitable trades mean: {t['profitable_trades_mean']}%<br>"\
|
|
174
|
+
f"Profitable trades median: {t['profitable_trades_median']}%<br>"\
|
|
175
|
+
f"Looser trades mean: {t['looser_trades_mean']}%<br>"\
|
|
176
|
+
f"Looser trades median: {t['looser_trades_median']}%<br>"
|
|
177
|
+
|
|
178
|
+
# Add a larger textbox using annotations
|
|
179
|
+
fig.add_annotation( go.layout.Annotation( x=tex_loc[0], y=tex_loc[1], xref='paper', yref='paper', text=trade_text, showarrow=True, arrowhead=4, ax=0, ay=0, bordercolor='black', borderwidth=2, bgcolor='white', align='left', font=dict(size=14, color='black')))
|
|
180
180
|
|
|
181
181
|
|
|
182
182
|
# Add RSI line
|
goldhand/tw.py
CHANGED
|
@@ -92,7 +92,9 @@ class Tw:
|
|
|
92
92
|
|
|
93
93
|
secdf.rename(columns = {'description': 'Company'}, inplace=True)
|
|
94
94
|
|
|
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')
|
|
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
|
+
|
|
97
|
+
fig = px.bar(secdf, x='name', y='market_cap_basic', title = self.get_plotly_title(ticker), labels={'market_cap_basic':'Market kapitalization'}, text='Company')
|
|
96
98
|
|
|
97
99
|
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)
|
|
98
100
|
fig.update_layout(showlegend=False, plot_bgcolor='white', height=600)
|
|
@@ -110,7 +112,7 @@ class Tw:
|
|
|
110
112
|
|
|
111
113
|
inddf.rename(columns = {'description': 'Company'}, inplace=True)
|
|
112
114
|
|
|
113
|
-
fig = px.bar(inddf, x='name', y='market_cap_basic', title =
|
|
115
|
+
fig = px.bar(inddf, x='name', y='market_cap_basic', title = self.get_plotly_title(ticker), labels={'market_cap_basic':'Market kapitalization'}, text='Company')
|
|
114
116
|
|
|
115
117
|
|
|
116
118
|
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)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
goldhand/__init__.py,sha256=2D68nqSZuv6sqyLJbOXnWIeeFpNgpYc90rHa2Fo70lk,152
|
|
2
|
+
goldhand/backtest.py,sha256=haK0c7wbUv02DUU5LcrvDSC1i0h1nDX7HHYzD9abhb8,6456
|
|
3
|
+
goldhand/helpers.py,sha256=l9yn0kVTiwfUR8sI5nH1QFx6dYikaUQgRA227Ox7hs0,6130
|
|
4
|
+
goldhand/stocks.py,sha256=wizTmZ8ybH76CSHuWbNu0hkbwH95Mw4LWSblb5jl9ro,11680
|
|
5
|
+
goldhand/strategy_goldhand_line.py,sha256=dsOzCsVtvhNJ42-r2rsPVV4YFuNto31ylqQ3Il4XYOw,11341
|
|
6
|
+
goldhand/strategy_rsi.py,sha256=eswHKmswX408Cf9xjny7DqxSkJ_FemtxHHQ2V69vbP0,8918
|
|
7
|
+
goldhand/tw.py,sha256=zyB-Pb0KVns7bMrr6NFwDQlu6-PpFn-xWt9BRmmMMTs,8456
|
|
8
|
+
goldhand-15.1.dist-info/METADATA,sha256=oaImadJh7nYeTavHKtXrwty7OQUXLuMJnnk-Nbapwyg,1952
|
|
9
|
+
goldhand-15.1.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
|
10
|
+
goldhand-15.1.dist-info/top_level.txt,sha256=siEJ2_a_Fx_7hqRI4Ms6SzCelbXrK_1H_eOF8KAaMdA,9
|
|
11
|
+
goldhand-15.1.dist-info/RECORD,,
|
goldhand-14.2.dist-info/RECORD
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
goldhand/__init__.py,sha256=2D68nqSZuv6sqyLJbOXnWIeeFpNgpYc90rHa2Fo70lk,152
|
|
2
|
-
goldhand/backtest.py,sha256=KrZXXaQw3ZPxE3tY0MOCa2qPJX374pVMLwM_VIOKy5Y,6105
|
|
3
|
-
goldhand/helpers.py,sha256=l9yn0kVTiwfUR8sI5nH1QFx6dYikaUQgRA227Ox7hs0,6130
|
|
4
|
-
goldhand/stocks.py,sha256=wizTmZ8ybH76CSHuWbNu0hkbwH95Mw4LWSblb5jl9ro,11680
|
|
5
|
-
goldhand/strategy_goldhand_line.py,sha256=Ulq_wcUOzzQBjtwq45R3_9QbFXHSbkZTtkwOczQC43I,10501
|
|
6
|
-
goldhand/strategy_rsi.py,sha256=Ja2jomY4lw6K_VMLTNcUomn80T2iY3XwL40H2JUdAFY,8802
|
|
7
|
-
goldhand/tw.py,sha256=K8MwMDkW5JtBFBG0qcPzj8OVx2OhDjrOH2UGo6nwtSs,8375
|
|
8
|
-
goldhand-14.2.dist-info/METADATA,sha256=KlD3Z6LQt-MCaGGXPATHgNYP1h3n0oI0QbL_Ewu2NfA,1952
|
|
9
|
-
goldhand-14.2.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
|
10
|
-
goldhand-14.2.dist-info/top_level.txt,sha256=siEJ2_a_Fx_7hqRI4Ms6SzCelbXrK_1H_eOF8KAaMdA,9
|
|
11
|
-
goldhand-14.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|