goldhand 15.5__tar.gz → 15.7__tar.gz
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-15.5 → goldhand-15.7}/PKG-INFO +1 -1
- {goldhand-15.5 → goldhand-15.7}/goldhand/backtest.py +24 -0
- {goldhand-15.5 → goldhand-15.7}/goldhand/stocks.py +29 -31
- {goldhand-15.5 → goldhand-15.7}/goldhand/strategy_goldhand_line.py +20 -16
- {goldhand-15.5 → goldhand-15.7}/goldhand/strategy_rsi.py +19 -0
- {goldhand-15.5 → goldhand-15.7}/goldhand/tw.py +83 -49
- {goldhand-15.5 → goldhand-15.7}/goldhand.egg-info/PKG-INFO +1 -1
- {goldhand-15.5 → goldhand-15.7}/setup.py +1 -2
- {goldhand-15.5 → goldhand-15.7}/README.md +0 -0
- {goldhand-15.5 → goldhand-15.7}/goldhand/__init__.py +0 -0
- {goldhand-15.5 → goldhand-15.7}/goldhand/helpers.py +0 -0
- {goldhand-15.5 → goldhand-15.7}/goldhand.egg-info/SOURCES.txt +0 -0
- {goldhand-15.5 → goldhand-15.7}/goldhand.egg-info/dependency_links.txt +0 -0
- {goldhand-15.5 → goldhand-15.7}/goldhand.egg-info/requires.txt +0 -0
- {goldhand-15.5 → goldhand-15.7}/goldhand.egg-info/top_level.txt +0 -0
- {goldhand-15.5 → goldhand-15.7}/setup.cfg +0 -0
|
@@ -6,6 +6,15 @@ import plotly.express as px
|
|
|
6
6
|
|
|
7
7
|
class Backtest:
|
|
8
8
|
def __init__(self, data, strategy_function, plot_title='', **kwargs):
|
|
9
|
+
"""
|
|
10
|
+
Backtest class to test strategies on historical data to see how they would have performed.
|
|
11
|
+
|
|
12
|
+
Parameters:
|
|
13
|
+
- data: pandas DataFrame with historical data
|
|
14
|
+
- strategy_function: function that takes in the data and returns a DataFrame of trades
|
|
15
|
+
- plot_title: title for the plot
|
|
16
|
+
- kwargs: additional parameters to be passed to the strategy function
|
|
17
|
+
"""
|
|
9
18
|
self.data = data
|
|
10
19
|
self.plot_title = plot_title
|
|
11
20
|
self.strategy_function = strategy_function
|
|
@@ -15,6 +24,9 @@ class Backtest:
|
|
|
15
24
|
|
|
16
25
|
|
|
17
26
|
def add_trades(self):
|
|
27
|
+
"""
|
|
28
|
+
Calculate the trades using the strategy function and the data provided
|
|
29
|
+
"""
|
|
18
30
|
self.trades = self.strategy_function(self.data, **self.additional_params)
|
|
19
31
|
self.trades['ticker'] = self.data['ticker'].iloc[0]
|
|
20
32
|
|
|
@@ -26,6 +38,9 @@ class Backtest:
|
|
|
26
38
|
|
|
27
39
|
|
|
28
40
|
def summary_of_trades(self):
|
|
41
|
+
"""
|
|
42
|
+
Calculate the summary of the trades
|
|
43
|
+
"""
|
|
29
44
|
self.trades_summary = {
|
|
30
45
|
'ticker' : self.data['ticker'].iloc[0],
|
|
31
46
|
'number_of_trades' : self.trades.shape[0],
|
|
@@ -68,6 +83,9 @@ class Backtest:
|
|
|
68
83
|
self.trades_summary.update(self.additional_params)
|
|
69
84
|
|
|
70
85
|
def show_trades(self):
|
|
86
|
+
"""
|
|
87
|
+
Plot the trades of the strategy on the data provided
|
|
88
|
+
"""
|
|
71
89
|
tdf = self.data
|
|
72
90
|
fig = go.Figure(data=go.Ohlc(x=tdf['date'], open=tdf['open'], high=tdf['high'], low=tdf['low'],close=tdf['close']))
|
|
73
91
|
fig.add_trace( go.Scatter(x=tdf['date'], y=tdf['sma_50'], opacity =0.5, line=dict(color='lightblue', width = 2) , name = 'SMA 50') )
|
|
@@ -121,6 +139,12 @@ class Backtest:
|
|
|
121
139
|
|
|
122
140
|
|
|
123
141
|
def summarize_strategy(self):
|
|
142
|
+
"""
|
|
143
|
+
Display the summary of the strategy:
|
|
144
|
+
- Summary of trades
|
|
145
|
+
- Trades in interactive plot
|
|
146
|
+
- Trades in DataFrame
|
|
147
|
+
"""
|
|
124
148
|
display(pd.DataFrame(self.trades_summary, index=['Strategy summary']).T )
|
|
125
149
|
self.show_trades().show()
|
|
126
150
|
display(self.trades)
|
|
@@ -13,12 +13,12 @@ class GoldHand:
|
|
|
13
13
|
def __init__(self, ticker, ad_ticker=True, range='18y', interval='1d'):
|
|
14
14
|
"""
|
|
15
15
|
GoldHand class to download and analyze stock data
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
|
|
17
|
+
Paramseters:
|
|
18
|
+
- ticker: str, ticker symbol of the stocks or crypto or ETF
|
|
19
|
+
- ad_ticker: bool, add ticker column to the DataFrame
|
|
20
|
+
- range: str, time range to download data for example 5y,1y, 1mo, 1d, 1h
|
|
21
|
+
- interval: str, interval to download data for example 1d, 1h, 5m
|
|
22
22
|
"""
|
|
23
23
|
self.scraper = cloudscraper.create_scraper()
|
|
24
24
|
self.ad_ticker = ad_ticker
|
|
@@ -31,8 +31,8 @@ class GoldHand:
|
|
|
31
31
|
|
|
32
32
|
def get_olhc(self):
|
|
33
33
|
"""
|
|
34
|
-
Download historical stock data
|
|
35
|
-
|
|
34
|
+
Download historical stock, crypto or ETF data from yahoo finance
|
|
35
|
+
API documentation location: https://cryptocointracker.com/yahoo-finance/yahoo-finance-api
|
|
36
36
|
"""
|
|
37
37
|
#scraper = cloudscraper.create_scraper()
|
|
38
38
|
response = self.scraper.get(f"https://query1.finance.yahoo.com/v8/finance/chart/{self.ticker}?interval={self.interval}&range={self.range}")
|
|
@@ -46,13 +46,13 @@ class GoldHand:
|
|
|
46
46
|
|
|
47
47
|
def smma(self, data, window, colname):
|
|
48
48
|
"""
|
|
49
|
-
Calculate Smoothed Moving Average (SMMA)
|
|
50
|
-
|
|
51
|
-
data:
|
|
52
|
-
window: int, window size
|
|
53
|
-
colname: str, name of the column to add to the
|
|
54
|
-
|
|
55
|
-
|
|
49
|
+
Calculate Smoothed Simple Moving Average (SMMA)
|
|
50
|
+
Parameters:
|
|
51
|
+
- data: Pandas DataFrame
|
|
52
|
+
- window: int, window size
|
|
53
|
+
- colname: str, name of the column to add to the DataFrame
|
|
54
|
+
|
|
55
|
+
Return: DataFrame with added column
|
|
56
56
|
"""
|
|
57
57
|
hl2 = data['hl2'].values
|
|
58
58
|
smma_values = [hl2[0]]
|
|
@@ -68,7 +68,7 @@ class GoldHand:
|
|
|
68
68
|
|
|
69
69
|
def download_historical_data(self):
|
|
70
70
|
"""
|
|
71
|
-
Download historical stock
|
|
71
|
+
Download historical stock, crypto or ETF data
|
|
72
72
|
"""
|
|
73
73
|
# Download historical stock data for the last year
|
|
74
74
|
self.df = self.get_olhc()
|
|
@@ -173,13 +173,12 @@ class GoldHand:
|
|
|
173
173
|
def plotly_last_year(self, plot_title, plot_height=900, ndays=500, ad_local_min_max=True):
|
|
174
174
|
"""
|
|
175
175
|
Plot last year interactive plot of a stock analyzing the local minimums and maximums
|
|
176
|
-
|
|
177
|
-
plot_title: str, title of the plot
|
|
178
|
-
plot_height: int, height of the plot
|
|
179
|
-
ndays: int, number of days to plot
|
|
180
|
-
ad_local_min_max: bool, add local min max to the plot
|
|
181
|
-
|
|
182
|
-
fig: plotly figure
|
|
176
|
+
Parameters:
|
|
177
|
+
- plot_title: str, title of the plot
|
|
178
|
+
- plot_height: int, height of the plot
|
|
179
|
+
- ndays: int, number of days to plot
|
|
180
|
+
- ad_local_min_max: bool, add local min max to the plot
|
|
181
|
+
Return: plotly figure
|
|
183
182
|
"""
|
|
184
183
|
tdf = self.df.tail(ndays)
|
|
185
184
|
|
|
@@ -208,14 +207,13 @@ class GoldHand:
|
|
|
208
207
|
|
|
209
208
|
def plot_goldhand_line(self, plot_title, plot_height=900, ndays=800, ad_local_min_max=True):
|
|
210
209
|
"""
|
|
211
|
-
Plot last year interactive plot of a stock analyzing the local minimums and maximums using the
|
|
212
|
-
|
|
213
|
-
plot_title: str, title of the plot
|
|
214
|
-
plot_height: int, height of the plot
|
|
215
|
-
ndays: int, number of days to plot
|
|
216
|
-
ad_local_min_max: bool, add local min max to the plot
|
|
217
|
-
|
|
218
|
-
fig: plotly figure
|
|
210
|
+
Plot last year interactive plot of a stock analyzing the local minimums and maximums using the GoldHandLine indicator
|
|
211
|
+
Parameters:
|
|
212
|
+
- plot_title: str, title of the plot
|
|
213
|
+
- plot_height: int, height of the plot
|
|
214
|
+
- ndays: int, number of days to plot
|
|
215
|
+
- ad_local_min_max: bool, add local min max to the plot
|
|
216
|
+
Return: plotly figure
|
|
219
217
|
"""
|
|
220
218
|
|
|
221
219
|
data = self.df.copy()
|
|
@@ -10,13 +10,14 @@ from goldhand import *
|
|
|
10
10
|
|
|
11
11
|
def goldhand_line_strategy(data, buy_at='gold', sell_at='grey'):
|
|
12
12
|
"""
|
|
13
|
-
This function implements the
|
|
13
|
+
This function implements the GoldHandLine strategy.
|
|
14
|
+
|
|
14
15
|
Parameters:
|
|
15
|
-
data (pandas
|
|
16
|
-
buy_at (str): The color of the line to buy at. Default is 'gold'.
|
|
17
|
-
sell_at (str): The color of the line to sell at. Default is 'grey'.
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
- data (pandas DataFrame) : The DataFrame containing the data.
|
|
17
|
+
- buy_at (str): The color of the line to buy at. Default is 'gold'.
|
|
18
|
+
- sell_at (str): The color of the line to sell at. Default is 'grey'.
|
|
19
|
+
|
|
20
|
+
Returns: The trades of the GoldHandLine strategy.
|
|
20
21
|
"""
|
|
21
22
|
|
|
22
23
|
data['hl2'] = (data['high'] + data['low'])/2
|
|
@@ -112,15 +113,18 @@ def goldhand_line_strategy(data, buy_at='gold', sell_at='grey'):
|
|
|
112
113
|
|
|
113
114
|
def show_indicator_goldhand_line_strategy(ticker, plot_title = '', buy_at='gold', sell_at='grey', ndays=0, plot_height=1000, add_strategy_summary = True):
|
|
114
115
|
"""
|
|
115
|
-
This function shows the
|
|
116
|
+
This function shows the GoldHandLine strategy on a plotly chart including the price, trades, strategy summary and GoldHandLine indicator.
|
|
117
|
+
|
|
116
118
|
Parameters:
|
|
117
|
-
ticker (str): The ticker of the stock or ETF.
|
|
118
|
-
plot_title (str): The title of the plot.
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
119
|
+
- ticker (str): The ticker of the stock or crypto or ETF.
|
|
120
|
+
- plot_title (str): The title of the plot.
|
|
121
|
+
- buy_at (str): The color of the line to buy at. Default is 'gold'.
|
|
122
|
+
- sell_at (str): The color of the line to sell at. Default is 'grey'.
|
|
123
|
+
- ndays (int): The number of days to show. If 0, all data will be shown.
|
|
124
|
+
- plot_height (int): The height of the plot.
|
|
125
|
+
- add_strategy_summary (bool): If True, the strategy summary will be added to the plot.
|
|
126
|
+
|
|
127
|
+
Returns: The plot including the price, trades, strategy summary and GoldHandLine indicator.
|
|
124
128
|
"""
|
|
125
129
|
|
|
126
130
|
data = GoldHand(ticker).df
|
|
@@ -159,10 +163,10 @@ def show_indicator_goldhand_line_strategy(ticker, plot_title = '', buy_at='gold'
|
|
|
159
163
|
# Create a 'group' column and increase the value only when there's a color change
|
|
160
164
|
data['group'] = (data['color_change']).cumsum()
|
|
161
165
|
|
|
162
|
-
##### data
|
|
166
|
+
##### data preparation end
|
|
163
167
|
|
|
164
168
|
##### backtest
|
|
165
|
-
backtest = Backtest( data, goldhand_line_strategy, plot_title =plot_title, buy_at=
|
|
169
|
+
backtest = Backtest( data, goldhand_line_strategy, plot_title =plot_title, buy_at= buy_at, sell_at=sell_at)
|
|
166
170
|
trades =backtest.trades
|
|
167
171
|
|
|
168
172
|
if ndays!=0:
|
|
@@ -9,6 +9,14 @@ from goldhand import *
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
def rsi_strategy(data, buy_threshold = 30, sell_threshold = 70):
|
|
12
|
+
"""
|
|
13
|
+
RSI strategy for backtesting with Backtest class
|
|
14
|
+
|
|
15
|
+
Parameters:
|
|
16
|
+
- data: pandas DataFrame with columns: date, open, high, low, close, volume and rsi
|
|
17
|
+
- buy_threshold: int, default 30, buy when RSI is below this value
|
|
18
|
+
- sell_threshold: int, default 70, sell when RSI is above this value
|
|
19
|
+
"""
|
|
12
20
|
|
|
13
21
|
in_trade = False # Flag to track if already in a trade
|
|
14
22
|
trade_id = 1
|
|
@@ -78,6 +86,17 @@ def rsi_strategy(data, buy_threshold = 30, sell_threshold = 70):
|
|
|
78
86
|
|
|
79
87
|
|
|
80
88
|
def show_indicator_rsi_strategy(ticker, buy_threshold = 30, sell_threshold = 70, plot_title = '', ndays=0, plot_height=1000, add_strategy_summary = True):
|
|
89
|
+
"""
|
|
90
|
+
Show RSI strategy result in one plot: candlestick chart, SMA lines, trades, RSI indicator, summary of the strategy on the left side of the plot
|
|
91
|
+
Parameters:
|
|
92
|
+
- ticker: str, ticker symbol
|
|
93
|
+
- buy_threshold: int, default 30, buy when RSI is below this value
|
|
94
|
+
- sell_threshold: int, default 70, sell when RSI is above this value
|
|
95
|
+
- plot_title: str, default '', title of the plot
|
|
96
|
+
- ndays: int, default 0, number of days to show, if 0, show all data
|
|
97
|
+
- plot_height: int, default 1000, height of the plot
|
|
98
|
+
- add_strategy_summary: bool, default True, add strategy summary to the plot
|
|
99
|
+
"""
|
|
81
100
|
|
|
82
101
|
tdf = GoldHand(ticker).df
|
|
83
102
|
backtest = Backtest( tdf, rsi_strategy, buy_threshold=buy_threshold, sell_threshold=sell_threshold)
|
|
@@ -10,7 +10,7 @@ import json
|
|
|
10
10
|
class Tw:
|
|
11
11
|
def __init__(self):
|
|
12
12
|
"""
|
|
13
|
-
Get all
|
|
13
|
+
Get all stock, crypto and ETF data from TradingView
|
|
14
14
|
"""
|
|
15
15
|
self.stock = pd.DataFrame()
|
|
16
16
|
self.crypto = pd.DataFrame()
|
|
@@ -22,8 +22,9 @@ class Tw:
|
|
|
22
22
|
|
|
23
23
|
def get_all_stock(self):
|
|
24
24
|
"""
|
|
25
|
-
Get all stocks from TradingView
|
|
25
|
+
Get all stocks data from TradingView
|
|
26
26
|
"""
|
|
27
|
+
|
|
27
28
|
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]}'
|
|
28
29
|
response = requests.post('https://scanner.tradingview.com/america/scan', data=data_query)
|
|
29
30
|
data = response.json()
|
|
@@ -35,8 +36,9 @@ class Tw:
|
|
|
35
36
|
|
|
36
37
|
def get_all_crypto(self):
|
|
37
38
|
"""
|
|
38
|
-
Get all
|
|
39
|
+
Get all crypto data from TradingView
|
|
39
40
|
"""
|
|
41
|
+
|
|
40
42
|
data_query = '{"columns":["base_currency","base_currency_desc","base_currency_logoid","update_mode","type","typespecs","exchange","crypto_total_rank","close","pricescale","minmov","fractional","minmove2","currency","24h_close_change|5","market_cap_calc","fundamental_currency_code","24h_vol_cmc","circulating_supply","crypto_common_categories","crypto_blockchain_ecosystems"],"ignore_unknown_fields":false,"options":{"lang":"en"},"range":[0,300],"sort":{"sortBy":"crypto_total_rank","sortOrder":"asc"},"markets":["coin"]}'
|
|
41
43
|
response = requests.post('https://scanner.tradingview.com/coin/scan', data=data_query)
|
|
42
44
|
data = response.json()
|
|
@@ -49,7 +51,7 @@ class Tw:
|
|
|
49
51
|
|
|
50
52
|
def get_all_etf(self):
|
|
51
53
|
"""
|
|
52
|
-
Get all
|
|
54
|
+
Get all ETFs from TradingView
|
|
53
55
|
"""
|
|
54
56
|
data_query = '{"columns":["name","description","logoid","update_mode","type","typespecs","close","pricescale","minmov","fractional","minmove2","currency","change","Value.Traded","relative_volume_10d_calc","aum","fundamental_currency_code","nav_total_return.5Y","expense_ratio","asset_class.tr","focus.tr","nav_discount_premium","category.tr","brand.tr","niche.tr"],"ignore_unknown_fields":false,"options":{"lang":"en"},"price_conversion":{"to_symbol":true},"range":[0,3000],"sort":{"sortBy":"aum","sortOrder":"desc"},"markets":["america"],"filter2":{"operator":"and","operands":[{"operation":{"operator":"or","operands":[{"operation":{"operator":"and","operands":[{"expression":{"left":"typespecs","operation":"has","right":["etn"]}}]}},{"operation":{"operator":"and","operands":[{"expression":{"left":"typespecs","operation":"has","right":["etf"]}}]}}]}}]}}'
|
|
55
57
|
response = requests.post('https://scanner.tradingview.com/america/scan', data=data_query)
|
|
@@ -58,27 +60,42 @@ class Tw:
|
|
|
58
60
|
self.etf = pd.DataFrame(list_elements)
|
|
59
61
|
self.etf.columns = json.loads(data_query)['columns']
|
|
60
62
|
self.etf = self.etf[self.etf['name'].str.contains('\\.')!=True]
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def moneystring( self, money):
|
|
66
|
+
"""
|
|
67
|
+
Convert money to string with unit
|
|
68
|
+
Parameters:
|
|
69
|
+
- money: money to convert
|
|
70
|
+
Return: string with unit
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
if money > 1_000_000_000_000:
|
|
74
|
+
money_str = f"{round(money / 1_000_000_000_000, 2)} Trillion"
|
|
75
|
+
elif money>1_000_000_000:
|
|
76
|
+
money_str = f"{round(money / 1_000_000_000, 2)} Billion"
|
|
77
|
+
else:
|
|
78
|
+
money_str = f"{round(money / 1_000_000, 2)} Million"
|
|
79
|
+
return money_str
|
|
61
80
|
|
|
62
81
|
|
|
63
82
|
def get_one_stock_info(self, ticker):
|
|
64
83
|
"""
|
|
65
84
|
Get info about one stock
|
|
66
|
-
|
|
67
|
-
|
|
85
|
+
Parameters:
|
|
86
|
+
- ticker: ticker of the stock
|
|
87
|
+
Return: type dictioanry
|
|
68
88
|
"""
|
|
89
|
+
|
|
69
90
|
ticker = ticker.upper()
|
|
70
91
|
one_row = self.stock.loc[self.stock['name']==ticker,].iloc[0]
|
|
71
92
|
tsec = self.stock.loc[self.stock['sector']==one_row['sector']].reset_index(drop=True)
|
|
72
93
|
tind = self.stock.loc[self.stock['industry']== one_row['industry']].reset_index(drop=True)
|
|
73
|
-
if one_row['market_cap_basic'] <100_000_000:
|
|
74
|
-
market_cap = f"💲{round(one_row['market_cap_basic']/1_000_000, 2):,} Million"
|
|
75
|
-
else:
|
|
76
|
-
market_cap = f"💲{round(one_row['market_cap_basic']/1_000_000):,} Million"
|
|
77
94
|
return({'ticker': one_row['name'],
|
|
78
95
|
'price': one_row['close'],
|
|
79
96
|
'market_cap': one_row['market_cap_basic'] ,
|
|
80
97
|
'n_emp': one_row['number_of_employees'],
|
|
81
|
-
'market_cap_text':
|
|
98
|
+
'market_cap_text': self.moneystring(one_row['market_cap_basic']),
|
|
82
99
|
'name': one_row['description'],
|
|
83
100
|
'sector': one_row['sector'],
|
|
84
101
|
'industry': one_row['industry'],
|
|
@@ -91,85 +108,102 @@ class Tw:
|
|
|
91
108
|
def get_top_n_stocks_by_sector(self,percent=10):
|
|
92
109
|
"""
|
|
93
110
|
Get top n % stocks by sector
|
|
94
|
-
|
|
95
|
-
|
|
111
|
+
Parameters:
|
|
112
|
+
- percent: percent of stocks to return
|
|
113
|
+
Return: Pandas DataFrame
|
|
96
114
|
"""
|
|
97
|
-
|
|
98
|
-
|
|
115
|
+
|
|
116
|
+
return (
|
|
99
117
|
self.stock.groupby('sector')
|
|
100
118
|
.apply(lambda x: x.nlargest(int(len(x) * round((percent/100),2) ), 'market_cap_basic'))
|
|
101
119
|
.reset_index(drop=True)
|
|
102
|
-
|
|
120
|
+
|
|
103
121
|
)
|
|
104
|
-
|
|
122
|
+
|
|
105
123
|
|
|
106
124
|
def get_plotly_title(self, ticker):
|
|
107
125
|
"""
|
|
108
126
|
Get plotly title for stock or crypto
|
|
109
|
-
|
|
110
|
-
|
|
127
|
+
Parameters:
|
|
128
|
+
- ticker: ticker of the stock
|
|
129
|
+
Return: Summary of the stock or crypto to be used as plotly title
|
|
111
130
|
"""
|
|
112
131
|
|
|
113
132
|
if '-USD' in ticker:
|
|
133
|
+
# crypto
|
|
114
134
|
coin = self.crypto.loc[self.crypto['ticker']==ticker].iloc[0]
|
|
115
|
-
plotly_title = f"{coin['base_currency_desc']} ({coin['base_currency']})<br>💲{
|
|
135
|
+
plotly_title = f"{coin['base_currency_desc']} ({coin['base_currency']})<br>💲{self.moneystring(coin['market_cap_calc'])} | {', '.join(coin['crypto_common_categories'])}"
|
|
136
|
+
|
|
137
|
+
elif ticker in self.etf['name'].tolist() :
|
|
138
|
+
# ETF
|
|
139
|
+
t = self.etf.loc[self.etf['name']==ticker].iloc[0]
|
|
140
|
+
plotly_title = f"{t['description']} ({t['name']}) | 💲{round(t['close'], 2)} <br>AUM:💲{self.moneystring(t['aum'])} | {t['focus.tr']} | Expense ratio {t['expense_ratio']}"
|
|
116
141
|
else:
|
|
142
|
+
# stock
|
|
117
143
|
t = self.get_one_stock_info(ticker)
|
|
118
|
-
plotly_title = f"{t['name']} ({t['ticker']}) | 💲{round(t['price'], 2)} | {t['sector']} | {t['industry']} <br
|
|
144
|
+
plotly_title = f"{t['name']} ({t['ticker']}) | 💲{round(t['price'], 2)} | {t['sector']} | {t['industry']} <br>💲{t['market_cap_text']} | 👨💼 {round(t['n_emp']):,} <br>Sector location: {t['sec_loc']} | Industry location: {t['ind_loc']}"
|
|
119
145
|
return(plotly_title)
|
|
120
146
|
|
|
147
|
+
|
|
121
148
|
def get_sec_plot(self, ticker):
|
|
122
149
|
"""
|
|
123
|
-
Get plotly figure for a ticker showing the sector location of the
|
|
124
|
-
|
|
125
|
-
|
|
150
|
+
Get plotly figure for a ticker showing the sector location of the stock
|
|
151
|
+
Parameters:
|
|
152
|
+
- ticker: ticker of the stock
|
|
153
|
+
Return: plotly figure showing the sector location of the stock
|
|
126
154
|
"""
|
|
155
|
+
|
|
156
|
+
if ticker in self.etf['name'].tolist():
|
|
157
|
+
return f"{ticker} is ETF use get_etf_plot"
|
|
127
158
|
row_df = self.stock.loc[self.stock['name']==ticker]
|
|
128
159
|
row_df.rename(columns = {'description': 'Company'}, inplace=True)
|
|
129
160
|
secdf = self.stock.loc[ (self.stock['sector'] ==row_df['sector'].iloc[0] ) ].reset_index(drop=True)
|
|
130
|
-
if row_df['market_cap_basic'].iloc[0] <100_000_000:
|
|
131
|
-
market_cap = f"💲{round(row_df['market_cap_basic'].iloc[0]/1_000_000, 2):,} Million"
|
|
132
|
-
else:
|
|
133
|
-
market_cap = f"💲{round(row_df['market_cap_basic'].iloc[0]/1_000_000):,} Million"
|
|
134
|
-
|
|
135
|
-
|
|
136
161
|
secdf.rename(columns = {'description': 'Company'}, inplace=True)
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
fig = px.bar(secdf, x='name', y='market_cap_basic', title = self.get_plotly_title(ticker), labels={'market_cap_basic':'Market kapitalization'}, text='Company')
|
|
141
|
-
|
|
142
|
-
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)
|
|
162
|
+
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')
|
|
163
|
+
fig = px.bar(secdf, x='name', y='market_cap_basic', title = self.get_plotly_title(ticker), labels={'market_cap_basic':'Market Capitalization'}, text='Company')
|
|
164
|
+
fig.add_annotation( x=row_df['name'].iloc[0], y=row_df['market_cap_basic'].iloc[0], text= f"{self.moneystring(row_df['market_cap_basic'].iloc[0])}", 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)
|
|
143
165
|
fig.update_layout(showlegend=False, plot_bgcolor='white', height=600)
|
|
144
166
|
return (fig)
|
|
145
167
|
|
|
168
|
+
|
|
146
169
|
def get_ind_plot(self, ticker):
|
|
147
170
|
"""
|
|
148
|
-
Get plotly figure for a ticker showing the industry location of the
|
|
149
|
-
|
|
150
|
-
|
|
171
|
+
Get plotly figure for a ticker showing the industry location of the stock
|
|
172
|
+
Parameters:
|
|
173
|
+
- ticker: ticker of the stock
|
|
174
|
+
Return: plotly figure showing the industry location of the stock
|
|
151
175
|
"""
|
|
152
|
-
|
|
176
|
+
|
|
177
|
+
if ticker in self.etf['name'].tolist():
|
|
178
|
+
return f"{ticker} is ETF use get_etf_plot"
|
|
153
179
|
row_df = self.stock.loc[self.stock['name']==ticker]
|
|
154
180
|
inddf = self.stock.loc[ (self.stock['industry'] ==row_df['industry'].iloc[0] ) ].reset_index(drop=True)
|
|
155
181
|
row_df.rename(columns = {'description': 'Company'}, inplace=True)
|
|
156
|
-
|
|
157
|
-
if row_df['market_cap_basic'].iloc[0] <100_000_000:
|
|
158
|
-
market_cap = f"💲{round(row_df['market_cap_basic'].iloc[0]/1_000_000, 2):,} Million"
|
|
159
|
-
else:
|
|
160
|
-
market_cap = f"💲{round(row_df['market_cap_basic'].iloc[0]/1_000_000):,} Million"
|
|
161
|
-
|
|
162
182
|
inddf.rename(columns = {'description': 'Company'}, inplace=True)
|
|
163
|
-
|
|
164
|
-
fig
|
|
183
|
+
fig = px.bar(inddf, x='name', y='market_cap_basic', title = self.get_plotly_title(ticker), labels={'market_cap_basic':'Market Capitalization'}, text='Company')
|
|
184
|
+
fig.add_annotation( x=row_df['name'].iloc[0], y=row_df['market_cap_basic'].iloc[0], text= f"{self.moneystring(row_df['market_cap_basic'].iloc[0])}", 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)
|
|
185
|
+
fig.update_layout(showlegend=False, plot_bgcolor='white', height=600)
|
|
186
|
+
return (fig)
|
|
165
187
|
|
|
166
188
|
|
|
167
|
-
|
|
189
|
+
def get_etf_plot(self, ticker):
|
|
190
|
+
"""
|
|
191
|
+
Get plotly figure for a ETF showing the ETF location with the same focus
|
|
192
|
+
Parameters:
|
|
193
|
+
- ticker: ticker of the ETF
|
|
194
|
+
Return: plotly figure showing the ETF location with the same focus
|
|
195
|
+
|
|
196
|
+
"""
|
|
197
|
+
row_df = self.etf.loc[self.etf['name']==ticker]
|
|
198
|
+
focdf = self.etf.loc[ (self.etf['focus.tr'] ==row_df['focus.tr'].iloc[0] ) ].reset_index(drop=True)
|
|
199
|
+
fig = px.bar(focdf, x='name', y='aum', title = self.get_plotly_title(ticker), labels={'aum':'Assets Under Management'}, text='description')
|
|
200
|
+
fig.add_annotation( x=row_df['name'].iloc[0], y=row_df['aum'].iloc[0], text= f"{self.moneystring(row_df['aum'].iloc[0])}", 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)
|
|
168
201
|
fig.update_layout(showlegend=False, plot_bgcolor='white', height=600)
|
|
169
202
|
return (fig)
|
|
170
203
|
|
|
171
204
|
|
|
172
205
|
|
|
206
|
+
|
|
173
207
|
#tw = Tw()
|
|
174
208
|
#print(tw.stock.head(1).T)
|
|
175
209
|
#print(tw.crypto.head(1).T)
|
|
@@ -8,7 +8,7 @@ long_description = (this_directory / "README.md").read_text()
|
|
|
8
8
|
|
|
9
9
|
setup(
|
|
10
10
|
name="goldhand",
|
|
11
|
-
version="15.
|
|
11
|
+
version="15.7",
|
|
12
12
|
author="Mihaly",
|
|
13
13
|
author_email="ormraat.pte@gmail.com",
|
|
14
14
|
description="A package working with financial data",
|
|
@@ -20,6 +20,5 @@ setup(
|
|
|
20
20
|
# other arguments omitted
|
|
21
21
|
long_description=long_description,
|
|
22
22
|
long_description_content_type='text/markdown'
|
|
23
|
-
|
|
24
23
|
)
|
|
25
24
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|