mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-10-27 12:40:35 +00:00
Here we merge all API Refactor related branches (#2236)
* Update api.py * Updated forex menu * refactor ycrv command * refactor ycrv command black * refactor ecocal command * Minh changes * Adding space to test pushing * title fix ecocal df * get economic calendar annotation * fix investingcom tests * refactor index command * refactor overview command * give defaults to wsj view function args * rename date args investincom * refacto bigmac command * fix ecocal typo * refactor rtps command * alphavantage gdp * alphavantage gdp per capita * alphavantage cpi * alphavantage tyld * alphavantage inf * refactor macro command * refactor macro command w helpers * refactor treasury command * fix macro on terminal * treasury labels * refactor maturities * update treasury maturities doc strings * refactor get economic calendar finhub * refactor map command api * display map filter choices * route economy api to performance map * route economy api to performance map * display group choices on valuation command * refactor performance and valuation commands * refactor spectrum model and view * add choices to spectrum controller * delete image after view * fix model tests finviz * fix finciz view tests * refactor futures * fix some tests * fix more tests * fix controller test * refactor fred series notes * update fred notes docstring * refacto fred series ids * fix pred and qa when empty datasets * refactor fred * uncomment stuff * refacto get series data * fix some tests * set defaults on args * refactor fred yield curve * black * fix spell and remove ecocal names * fix linting * linting * pylint fix * change dangerous defaults * Working through crypto fixes (#2256) * Working through crypto fixes * Continued adding crypto stuff * Added crypto overview * Added test fixes * Added fixtures * Fixed tests * Fixed charting issue * Removed broken APIs * Final adjustments * Added test fixes * map get groups and get ycrv countries into old api * exposed econdb helper funcs * remove helpers * refactor search indices * linting * refactor arg currency * pylint from currency * Started switching crpyto ascending to ascend * Merging * Portfolio model arguements, params, and docstring * Refactored for etf commands (#2292) * Refactored for etf commands * Fixed tests * Added load command * Fixed menu * Portfolio logic fixes * Added econometrics (#2260) * Added econometrics * Fixed tests * Simplified API * Added test fixes * Added test csv * Allowed examples to be loaded * Fund refactor (#2291) * Fund refactor * Changed fund_name and fund to name * Changed ascending to ascend * Stock menu refactoring for easier API usage (#2194) * Stocks refactoring for easier API usage * Linting * Refactor newly added features * Linting * Fixing tests * Refactor common files used by stocks menu * Fixing flake8 * Fix linting and tests * Linting * Fix flake8 * refactor insider_data * refactor mentions * refactor watchlist * refactor sentiment * refactor sentiment * fix yahoofinance tests * refactor load and candle * refactor get_news and display_news * refactor stocks.ins.act * candle default matplotlib * fix yahoofinance_view tests * fix ark model tests * fix ark view tests * fix business insider model * fix business insider view * refactor csimarket model * fix tests csi market model * update dd controller * fix get suppliers tests * fix dd controller tests * fix finhub tests * fix finviz tests * fix fmp tests * fix marketwatch tests * corrected argument keywords in test_bt_model * corrected argument keywords in test_bt_view * refactor fa controller * refactor marketwatch view * refactor gov controller * fix tests fa av * fix tests elect * fix dcf tests * fix polygon tests * fix fmp tests * fix quiverquant tests * fix yahoofinance fa tests * fix more fa tests * fix insider tests * fix more tests * fix more tests * fix options tests * fix stock gov tests * fix tests test_ba_controller * fix tests for test_finviz_compare_model.py * fixed 2 tests * fixed tests * fixed tests * fixed tests * fixed tests * fixed tests * fixed tests * fixed tests * fixed tests * fixed tests * fixed tests * fix final tests * fixed tests * fixed tests * Fix tests * black * forgot to black tests * fixed tests * fixed tests * fixed tests * fixed tests * flakefix * Tests + code : Stocks / Discovery * fix tests * added recorder * fixed tests * fixed tests * black * black * remove unused imports * refactor display raw * sia dicts fix * pylint * linting * remove dangerous default * fix tests * fix beta model test * black * skip screener qa test * change sector path to sectors * update tests readme * fix metric defaults * black * substitute lost ticker * defaults cpic * another round on sia * refactor cramer * reduce default tweets on sentiment * refactor yf hist, corr, volume * arkorders default * refactor income, balance, cashflow * refacto scorr, screener, getfinnhub * refactor stockgrid * ibkr refactor * another round on stockgrid * add dividens end point * refactor discovery endpoints * update docstrings with similar input * refactor messages * refactor ba * refactor regioons * refactor twitter sentiment * refactor hist * refactor regions * give default to timeframe * refactor bunch of defaults and arg names * remove leftover imports * refactor vwap * let tests run * fix tests * fix stock tests * fix stockanalysis tests * flake * MYPY * Made important changes * added fixes * Fixed big issue * Added fixes to tests * fix qa tests * fix tests * fix 1 more test * last stocks failing * fix crypto test Co-authored-by: Chavithra PARANA <chavithra@gmail.com> Co-authored-by: montezdesousa <montezdesousa@gmail.com> Co-authored-by: hjoaquim <h.joaquim@campus.fct.unl.pt> Co-authored-by: montezdesousa <79287829+montezdesousa@users.noreply.github.com> Co-authored-by: colin99d <colin99delahunty@gmail.com> * fix portfolio tests * change period to window * update ca docstrings * refactor get_similar_companies func * Fixed * Update CI * Update CI 2 * Update CI 3 * Update dependencies Co-authored-by: colin99d <colin99delahunty@gmail.com> Co-authored-by: Colin Delahunty <72827203+colin99d@users.noreply.github.com> Co-authored-by: montezdesousa <montezdesousa@gmail.com> Co-authored-by: James Simmons <simmonsj330@gmail.com> Co-authored-by: Theodore Aptekarev <aptekarev@gmail.com> Co-authored-by: minhhoang1023 <40023817+minhhoang1023@users.noreply.github.com> Co-authored-by: jose-donato <43375532+jose-donato@users.noreply.github.com> Co-authored-by: montezdesousa <79287829+montezdesousa@users.noreply.github.com> Co-authored-by: northern-64bit <75195383+northern-64bit@users.noreply.github.com> Co-authored-by: hjoaquim <h.joaquim@campus.fct.unl.pt>
This commit is contained in:
4
.github/workflows/test.yml
vendored
4
.github/workflows/test.yml
vendored
@@ -200,7 +200,7 @@ jobs:
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/conda_pkgs_dir
|
||||
key: conda-${{ runner.os }}-v1-${{ matrix.python }}-${{ hashFiles('build/conda/conda-3-9-env.yaml') }}
|
||||
key: conda-${{ runner.os }}-v1-${{ matrix.python }}-${{ hashFiles('build/conda/conda-3-9-env-full.yaml') }}
|
||||
|
||||
- name: Setup Miniconda
|
||||
uses: conda-incubator/setup-miniconda@v2
|
||||
@@ -232,7 +232,7 @@ jobs:
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ steps.pip-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-v1-3-9-pip-${{ hashFiles('requirements.txt') }}
|
||||
key: ${{ runner.os }}-v1-3-9-pip-${{ hashFiles('requirements-full.txt') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-v1-pip-
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ from openbb_terminal.helper_funcs import (
|
||||
)
|
||||
from openbb_terminal.rich_config import console
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
||||
@@ -12,4 +12,5 @@ from .mutual_funds import mutual_fund_api as funds
|
||||
from .portfolio import portfolio_api as portfolio
|
||||
from .reports import widget_helpers as widgets
|
||||
|
||||
|
||||
from .config_terminal import theme
|
||||
|
||||
@@ -12,20 +12,20 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_sentiment(ticker: str) -> pd.DataFrame:
|
||||
def get_sentiment(symbol: str) -> pd.DataFrame:
|
||||
"""Gets Sentiment analysis provided by FinBrain's API [Source: finbrain]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker : str
|
||||
Ticker to get the sentiment analysis from
|
||||
symbol : str
|
||||
Ticker symbol to get the sentiment analysis from
|
||||
|
||||
Returns
|
||||
-------
|
||||
DataFrame()
|
||||
Empty if there was an issue with data retrieval
|
||||
"""
|
||||
result = requests.get(f"https://api.finbrain.tech/v0/sentiments/{ticker}")
|
||||
result = requests.get(f"https://api.finbrain.tech/v0/sentiments/{symbol}")
|
||||
sentiment = pd.DataFrame()
|
||||
if result.status_code == 200:
|
||||
result_json = result.json()
|
||||
|
||||
@@ -34,7 +34,7 @@ def lambda_sentiment_coloring(val: float, last_val: float) -> str:
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_sentiment_analysis(
|
||||
ticker: str,
|
||||
symbol: str,
|
||||
raw: bool = False,
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
@@ -43,16 +43,16 @@ def display_sentiment_analysis(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker : str
|
||||
Ticker to get the sentiment analysis from
|
||||
raw : False
|
||||
symbol: str
|
||||
Ticker symbol to get the sentiment analysis from
|
||||
raw: False
|
||||
Display raw table data
|
||||
export : str
|
||||
export: str
|
||||
Format to export data
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
external_axes: Optional[List[plt.Axes]], optional
|
||||
External axes (1 axis is expected in the list), by default None
|
||||
"""
|
||||
sentiment = finbrain_model.get_sentiment(ticker)
|
||||
sentiment = finbrain_model.get_sentiment(symbol)
|
||||
if sentiment.empty:
|
||||
console.print("No sentiment data found.\n")
|
||||
return
|
||||
@@ -83,7 +83,7 @@ def display_sentiment_analysis(
|
||||
ax.set_ylabel("Sentiment")
|
||||
start_date = sentiment.index[-1].strftime("%Y/%m/%d")
|
||||
ax.set_title(
|
||||
f"FinBrain's Sentiment Analysis for {ticker.upper()} since {start_date}"
|
||||
f"FinBrain's Sentiment Analysis for {symbol.upper()} since {start_date}"
|
||||
)
|
||||
ax.set_ylim([-1.1, 1.1])
|
||||
senValues = np.array(pd.to_numeric(sentiment["Sentiment Analysis"].values))
|
||||
|
||||
@@ -12,13 +12,13 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_mentions(ticker: str) -> pd.DataFrame:
|
||||
def get_mentions(symbol: str) -> pd.DataFrame:
|
||||
"""Get interest over time from google api [Source: google]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker : str
|
||||
Stock ticker
|
||||
symbol: str
|
||||
Stock ticker symbol
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -26,18 +26,18 @@ def get_mentions(ticker: str) -> pd.DataFrame:
|
||||
Dataframe of interest over time
|
||||
"""
|
||||
pytrend = TrendReq()
|
||||
pytrend.build_payload(kw_list=[ticker])
|
||||
pytrend.build_payload(kw_list=[symbol])
|
||||
return pytrend.interest_over_time()
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_regions(ticker: str) -> pd.DataFrame:
|
||||
def get_regions(symbol: str) -> pd.DataFrame:
|
||||
"""Get interest by region from google api [Source: google]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker : str
|
||||
Ticker to look at
|
||||
symbol: str
|
||||
Ticker symbol to look at
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -45,18 +45,18 @@ def get_regions(ticker: str) -> pd.DataFrame:
|
||||
Dataframe of interest by region
|
||||
"""
|
||||
pytrend = TrendReq()
|
||||
pytrend.build_payload(kw_list=[ticker])
|
||||
return pytrend.interest_by_region()
|
||||
pytrend.build_payload(kw_list=[symbol])
|
||||
return pytrend.interest_by_region().sort_values([symbol], ascending=False)
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_queries(ticker: str) -> pd.DataFrame:
|
||||
def get_queries(symbol: str) -> pd.DataFrame:
|
||||
"""Get related queries from google api [Source: google]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker : str
|
||||
Stock ticker to compare
|
||||
symbol: str
|
||||
Stock ticker symbol to compare
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -64,18 +64,18 @@ def get_queries(ticker: str) -> pd.DataFrame:
|
||||
Dataframe of related queries
|
||||
"""
|
||||
pytrend = TrendReq()
|
||||
pytrend.build_payload(kw_list=[ticker])
|
||||
pytrend.build_payload(kw_list=[symbol])
|
||||
return pytrend.related_queries()
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_rise(ticker: str) -> pd.DataFrame:
|
||||
def get_rise(symbol: str) -> pd.DataFrame:
|
||||
"""Get top rising related queries with this stock's query [Source: google]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker : str
|
||||
Stock ticker
|
||||
symbol: str
|
||||
Stock ticker symbol
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -83,6 +83,6 @@ def get_rise(ticker: str) -> pd.DataFrame:
|
||||
Dataframe containing rising related queries
|
||||
"""
|
||||
pytrend = TrendReq()
|
||||
pytrend.build_payload(kw_list=[ticker])
|
||||
pytrend.build_payload(kw_list=[symbol])
|
||||
df_related_queries = pytrend.related_queries()
|
||||
return df_related_queries[ticker]["rising"]
|
||||
return df_related_queries[symbol]["rising"]
|
||||
|
||||
@@ -25,8 +25,8 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_mentions(
|
||||
ticker: str,
|
||||
start: str,
|
||||
symbol: str,
|
||||
start_date: str = "",
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
@@ -34,16 +34,16 @@ def display_mentions(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker : str
|
||||
Ticker
|
||||
start : str
|
||||
symbol : str
|
||||
Ticker symbol
|
||||
start_date : str
|
||||
Start date as YYYY-MM-DD string
|
||||
export: str
|
||||
Format to export data
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
External axes (1 axis is expected in the list), by default None
|
||||
"""
|
||||
df_interest = google_model.get_mentions(ticker)
|
||||
df_interest = google_model.get_mentions(symbol)
|
||||
|
||||
# This plot has 1 axis
|
||||
if external_axes is None:
|
||||
@@ -53,20 +53,20 @@ def display_mentions(
|
||||
else:
|
||||
return
|
||||
|
||||
ax.set_title(f"Interest over time on {ticker}")
|
||||
if start:
|
||||
df_interest = df_interest[start:] # type: ignore
|
||||
ax.bar(df_interest.index, df_interest[ticker], width=2)
|
||||
ax.set_title(f"Interest over time on {symbol}")
|
||||
if start_date:
|
||||
df_interest = df_interest[start_date:] # type: ignore
|
||||
ax.bar(df_interest.index, df_interest[symbol], width=2)
|
||||
ax.bar(
|
||||
df_interest.index[-1],
|
||||
df_interest[ticker].values[-1],
|
||||
df_interest[symbol].values[-1],
|
||||
width=theme.volume_bar_width,
|
||||
)
|
||||
else:
|
||||
ax.bar(df_interest.index, df_interest[ticker], width=1)
|
||||
ax.bar(df_interest.index, df_interest[symbol], width=1)
|
||||
ax.bar(
|
||||
df_interest.index[-1],
|
||||
df_interest[ticker].values[-1],
|
||||
df_interest[symbol].values[-1],
|
||||
width=theme.volume_bar_width,
|
||||
)
|
||||
ax.set_ylabel("Interest [%]")
|
||||
@@ -83,8 +83,8 @@ def display_mentions(
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_correlation_interest(
|
||||
ticker: str,
|
||||
df_data: pd.DataFrame,
|
||||
symbol: str,
|
||||
data: pd.DataFrame,
|
||||
words: List[str],
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
@@ -93,9 +93,9 @@ def display_correlation_interest(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker : str
|
||||
Ticker to check price
|
||||
df_data : pd.DataFrame
|
||||
symbol : str
|
||||
Ticker symbol to check price
|
||||
data : pd.DataFrame
|
||||
Data dataframe
|
||||
words : List[str]
|
||||
Words to check for interest for
|
||||
@@ -120,15 +120,15 @@ def display_correlation_interest(
|
||||
else:
|
||||
return
|
||||
ax[0].set_title(
|
||||
f"{ticker.upper()} stock price and interest over time on {','.join(words)}"
|
||||
f"{symbol.upper()} stock price and interest over time on {','.join(words)}"
|
||||
)
|
||||
ax[0].plot(
|
||||
df_data.index,
|
||||
df_data["Adj Close"].values,
|
||||
data.index,
|
||||
data["Adj Close"].values,
|
||||
c="#FCED00",
|
||||
)
|
||||
ax[0].set_ylabel("Stock Price")
|
||||
ax[0].set_xlim(df_data.index[0], df_data.index[-1])
|
||||
ax[0].set_xlim(data.index[0], data.index[-1])
|
||||
|
||||
colors = theme.get_colors()[1:]
|
||||
for idx, word in enumerate(words):
|
||||
@@ -136,7 +136,7 @@ def display_correlation_interest(
|
||||
ax[1].plot(df_interest.index, df_interest[word], "-", color=colors[idx])
|
||||
|
||||
ax[1].set_ylabel("Interest [%]")
|
||||
ax[1].set_xlim(df_data.index[0], df_data.index[-1])
|
||||
ax[1].set_xlim(data.index[0], data.index[-1])
|
||||
ax[1].legend(words)
|
||||
theme.style_primary_axis(ax[0])
|
||||
theme.style_primary_axis(ax[1])
|
||||
@@ -151,8 +151,8 @@ def display_correlation_interest(
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_regions(
|
||||
ticker: str,
|
||||
num: int = 5,
|
||||
symbol: str,
|
||||
limit: int = 5,
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
@@ -160,16 +160,16 @@ def display_regions(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker : str
|
||||
Ticker
|
||||
num: int
|
||||
symbol : str
|
||||
Ticker symbol
|
||||
limit: int
|
||||
Number of regions to show
|
||||
export: str
|
||||
Format to export data
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
External axes (1 axis is expected in the list), by default None
|
||||
"""
|
||||
df_interest_region = google_model.get_regions(ticker)
|
||||
df_interest_region = google_model.get_regions(symbol)
|
||||
|
||||
# This plot has 1 axis
|
||||
if external_axes is None:
|
||||
@@ -184,14 +184,12 @@ def display_regions(
|
||||
console.print("")
|
||||
return
|
||||
|
||||
df_interest_region = df_interest_region.sort_values([ticker], ascending=False).head(
|
||||
num
|
||||
)
|
||||
df = df_interest_region.sort_values([ticker], ascending=True)
|
||||
df_interest_region = df_interest_region.head(limit)
|
||||
df = df_interest_region.sort_values([symbol], ascending=True)
|
||||
|
||||
ax.set_title(f"Top's regions interest on {ticker}")
|
||||
ax.set_title(f"Top's regions interest on {symbol}")
|
||||
ax.barh(
|
||||
y=df.index, width=df[ticker], color=theme.get_colors(reverse=True), zorder=3
|
||||
y=df.index, width=df[symbol], color=theme.get_colors(reverse=True), zorder=3
|
||||
)
|
||||
ax.set_xlabel("Interest [%]")
|
||||
ax.set_ylabel("Region")
|
||||
@@ -204,55 +202,55 @@ def display_regions(
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_queries(ticker: str, num: int = 5, export: str = ""):
|
||||
def display_queries(symbol: str, limit: int = 5, export: str = ""):
|
||||
"""Print top related queries with this stock's query. [Source: Google]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker : str
|
||||
Ticker
|
||||
num: int
|
||||
symbol : str
|
||||
Ticker symbol
|
||||
limit: int
|
||||
Number of regions to show
|
||||
export: str
|
||||
Format to export data
|
||||
"""
|
||||
|
||||
df_related_queries = google_model.get_queries(ticker)
|
||||
df_related_queries = google_model.get_queries(symbol)
|
||||
df = df_related_queries.copy()
|
||||
df_related_queries = df_related_queries[ticker]["top"].head(num)
|
||||
df_related_queries = df_related_queries[symbol]["top"].head(limit)
|
||||
df_related_queries["value"] = df_related_queries["value"].apply(
|
||||
lambda x: str(x) + "%"
|
||||
)
|
||||
print_rich_table(
|
||||
df_related_queries,
|
||||
headers=list(df_related_queries.columns),
|
||||
title=f"Top {ticker}'s related queries",
|
||||
title=f"Top {symbol}'s related queries",
|
||||
)
|
||||
|
||||
export_data(export, os.path.dirname(os.path.abspath(__file__)), "queries", df)
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_rise(ticker: str, num: int, export: str = ""):
|
||||
def display_rise(symbol: str, limit: int = 10, export: str = ""):
|
||||
"""Print top rising related queries with this stock's query. [Source: Google]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker : str
|
||||
Ticker
|
||||
num: int
|
||||
symbol : str
|
||||
Ticker symbol
|
||||
limit: int
|
||||
Number of regions to show
|
||||
export: str
|
||||
Format to export data
|
||||
"""
|
||||
df_related_queries = google_model.get_rise(ticker)
|
||||
df = df_related_queries.copy()
|
||||
df_related_queries = df_related_queries.head(num)
|
||||
df_related_queries = google_model.get_rise(symbol)
|
||||
|
||||
print_rich_table(
|
||||
df_related_queries,
|
||||
df_related_queries.head(limit),
|
||||
headers=list(df_related_queries.columns),
|
||||
title=f"Top rising {ticker}'s related queries",
|
||||
title=f"Top rising {symbol}'s related queries",
|
||||
)
|
||||
|
||||
export_data(export, os.path.dirname(os.path.abspath(__file__)), "rise", df)
|
||||
export_data(
|
||||
export, os.path.dirname(os.path.abspath(__file__)), "rise", df_related_queries
|
||||
)
|
||||
|
||||
@@ -38,13 +38,13 @@ l_sub_reddits = [
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_watchlists(
|
||||
n_to_get: int,
|
||||
limit: int = 5,
|
||||
) -> Tuple[List[praw.models.reddit.submission.Submission], Dict, int]:
|
||||
"""Get reddit users watchlists [Source: reddit]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
n_to_get : int
|
||||
limit : int
|
||||
Number of posts to look through
|
||||
|
||||
Returns
|
||||
@@ -120,7 +120,7 @@ def get_watchlists(
|
||||
# Increment count of valid posts found
|
||||
n_flair_posts_found += 1
|
||||
subs.append(submission)
|
||||
if n_flair_posts_found > n_to_get - 1:
|
||||
if n_flair_posts_found > limit - 1:
|
||||
break
|
||||
|
||||
except ResponseException as e:
|
||||
@@ -136,15 +136,15 @@ def get_watchlists(
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_popular_tickers(
|
||||
n_top: int, posts_to_look_at: int, subreddits: str = ""
|
||||
limit: int = 10, post_limit: int = 50, subreddits: str = ""
|
||||
) -> pd.DataFrame:
|
||||
"""Get popular tickers from list of subreddits [Source: reddit]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
n_top : int
|
||||
limit : int
|
||||
Number of top tickers to get
|
||||
posts_to_look_at : int
|
||||
post_limit : int
|
||||
How many posts to analyze in each subreddit
|
||||
subreddits : str, optional
|
||||
String of comma separated subreddits.
|
||||
@@ -190,11 +190,11 @@ def get_popular_tickers(
|
||||
|
||||
for s_sub_reddit in sub_reddit_list:
|
||||
console.print(
|
||||
f"Search for latest tickers for {posts_to_look_at} '{s_sub_reddit}' posts"
|
||||
f"Search for latest tickers for {post_limit} '{s_sub_reddit}' posts"
|
||||
)
|
||||
submissions = psaw_api.search_submissions(
|
||||
subreddit=s_sub_reddit,
|
||||
limit=posts_to_look_at,
|
||||
limit=post_limit,
|
||||
filter=["id"],
|
||||
)
|
||||
|
||||
@@ -249,7 +249,7 @@ def get_popular_tickers(
|
||||
# pylint: disable=redefined-outer-name
|
||||
popular_tickers = []
|
||||
for t_ticker in lt_watchlist_sorted:
|
||||
if n_top_stocks > n_top:
|
||||
if n_top_stocks > limit:
|
||||
break
|
||||
try:
|
||||
# If try doesn't trigger exception, it means that this stock exists on finviz
|
||||
@@ -295,7 +295,7 @@ def get_popular_tickers(
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_spac_community(
|
||||
limit: int, popular: bool
|
||||
limit: int = 10, popular: bool = False
|
||||
) -> Tuple[List[praw.models.reddit.submission.Submission], Dict]:
|
||||
"""Get top tickers from r/SPACs [Source: reddit]
|
||||
|
||||
@@ -680,9 +680,9 @@ def get_due_dilligence(
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_posts_about(
|
||||
ticker: str,
|
||||
symbol: str,
|
||||
limit: int = 100,
|
||||
sort: str = "relevance",
|
||||
sortby: str = "relevance",
|
||||
time_frame: str = "week",
|
||||
subreddits: str = "all",
|
||||
) -> List[praw.models.reddit.submission.Submission]:
|
||||
@@ -690,11 +690,11 @@ def get_posts_about(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker: str
|
||||
Ticker to search for
|
||||
symbol: str
|
||||
Ticker symbol to search for
|
||||
limit: int
|
||||
Number of posts to get per subreddit
|
||||
sort: str
|
||||
sortby: str
|
||||
Search type
|
||||
Possibilities: "relevance", "hot", "top", "new", or "comments"
|
||||
time_frame: str
|
||||
@@ -745,9 +745,9 @@ def get_posts_about(
|
||||
console.print("Invalid subreddit name {sub_str}, skipping")
|
||||
continue
|
||||
submissions = subreddit.search(
|
||||
query=ticker,
|
||||
query=symbol,
|
||||
limit=limit,
|
||||
sort=sort,
|
||||
sort=sortby,
|
||||
time_filter=time_frame,
|
||||
)
|
||||
for sub in submissions:
|
||||
|
||||
@@ -94,15 +94,15 @@ def print_and_record_reddit_post(
|
||||
"API_REDDIT_PASSWORD",
|
||||
]
|
||||
)
|
||||
def display_watchlist(num: int):
|
||||
def display_watchlist(limit: int = 5):
|
||||
"""Print other users watchlist. [Source: Reddit]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
num: int
|
||||
limit: int
|
||||
Maximum number of submissions to look at
|
||||
"""
|
||||
subs, d_watchlist_tickers, n_flair_posts_found = reddit_model.get_watchlists(num)
|
||||
subs, d_watchlist_tickers, n_flair_posts_found = reddit_model.get_watchlists(limit)
|
||||
if subs:
|
||||
for sub in subs:
|
||||
print_and_record_reddit_post({}, sub)
|
||||
@@ -141,30 +141,28 @@ def display_watchlist(num: int):
|
||||
]
|
||||
)
|
||||
def display_popular_tickers(
|
||||
n_top: int = 10, posts_to_look_at: int = 50, subreddits: str = "", export: str = ""
|
||||
limit: int = 10, post_limit: int = 50, subreddits: str = "", export: str = ""
|
||||
):
|
||||
"""Print latest popular tickers. [Source: Reddit]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
n_top : int
|
||||
limit : int
|
||||
Number of top tickers to get
|
||||
posts_to_look_at : int
|
||||
post_limit : int
|
||||
How many posts to analyze in each subreddit
|
||||
subreddits : str, optional
|
||||
String of comma separated subreddits.
|
||||
export : str
|
||||
Format to export dataframe
|
||||
"""
|
||||
popular_tickers_df = reddit_model.get_popular_tickers(
|
||||
n_top, posts_to_look_at, subreddits
|
||||
)
|
||||
popular_tickers_df = reddit_model.get_popular_tickers(limit, post_limit, subreddits)
|
||||
if not popular_tickers_df.empty:
|
||||
print_rich_table(
|
||||
popular_tickers_df,
|
||||
headers=list(popular_tickers_df.columns),
|
||||
show_index=False,
|
||||
title=f"The following TOP {n_top} tickers have been mentioned",
|
||||
title=f"The following TOP {limit} tickers have been mentioned",
|
||||
)
|
||||
else:
|
||||
console.print("No tickers found")
|
||||
@@ -313,14 +311,14 @@ def display_wsb_community(limit: int = 10, new: bool = False):
|
||||
]
|
||||
)
|
||||
def display_due_diligence(
|
||||
ticker: str, limit: int = 10, n_days: int = 3, show_all_flairs: bool = False
|
||||
symbol: str, limit: int = 10, n_days: int = 3, show_all_flairs: bool = False
|
||||
):
|
||||
"""Display Reddit due diligence data for a given ticker
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker: str
|
||||
Stock ticker
|
||||
symbol: str
|
||||
Stock ticker symbol
|
||||
limit: int
|
||||
Number of posts to get
|
||||
n_days: int
|
||||
@@ -328,12 +326,12 @@ def display_due_diligence(
|
||||
show_all_flairs: bool
|
||||
Search through all flairs (apart from Yolo and Meme)
|
||||
"""
|
||||
subs = reddit_model.get_due_dilligence(ticker, limit, n_days, show_all_flairs)
|
||||
subs = reddit_model.get_due_dilligence(symbol, limit, n_days, show_all_flairs)
|
||||
if subs:
|
||||
for sub in subs:
|
||||
print_and_record_reddit_post({}, sub)
|
||||
if not subs:
|
||||
console.print(f"No DD posts found for {ticker}\n")
|
||||
console.print(f"No DD posts found for {symbol}\n")
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
@@ -347,23 +345,23 @@ def display_due_diligence(
|
||||
]
|
||||
)
|
||||
def display_reddit_sent(
|
||||
ticker: str,
|
||||
sort: str = "relevance",
|
||||
symbol: str,
|
||||
sortby: str = "relevance",
|
||||
limit: int = 100,
|
||||
graphic: bool = False,
|
||||
time_frame: str = "week",
|
||||
full_search: bool = True,
|
||||
subreddits: str = "all",
|
||||
export: str = "",
|
||||
display: bool = False,
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
"""Determine Reddit sentiment about a search term
|
||||
Parameters
|
||||
----------
|
||||
ticker: str
|
||||
The ticker being search for in Reddit
|
||||
sort: str
|
||||
symbol: str
|
||||
The ticker symbol being search for in Reddit
|
||||
sortby: str
|
||||
Type of search
|
||||
limit: str
|
||||
Number of posts to get at most
|
||||
@@ -377,16 +375,18 @@ def display_reddit_sent(
|
||||
Comma-separated list of subreddits
|
||||
display: bool
|
||||
Enable printing of raw sentiment values for each post
|
||||
export: str
|
||||
Format to export data
|
||||
external_axes: Optional[List[plt.Axes]]
|
||||
If supplied, expect 1 external axis
|
||||
"""
|
||||
|
||||
posts = reddit_model.get_posts_about(ticker, limit, sort, time_frame, subreddits)
|
||||
posts = reddit_model.get_posts_about(symbol, limit, sortby, time_frame, subreddits)
|
||||
post_data = []
|
||||
polarity_scores = []
|
||||
|
||||
if not posts:
|
||||
console.print(f"No posts for {ticker} found")
|
||||
console.print(f"No posts for {symbol} found")
|
||||
return
|
||||
|
||||
console.print("Analyzing each post...")
|
||||
@@ -417,13 +417,13 @@ def display_reddit_sent(
|
||||
return
|
||||
|
||||
sns.boxplot(x=polarity_scores, ax=ax)
|
||||
ax.set_title(f"Sentiment Score of {ticker}")
|
||||
ax.set_title(f"Sentiment Score of {symbol}")
|
||||
ax.set_xlabel("Sentiment Score")
|
||||
|
||||
if not external_axes:
|
||||
theme.visualize_output()
|
||||
|
||||
console.print(f"Sentiment Analysis for {ticker} is {avg_polarity}\n")
|
||||
console.print(f"Sentiment Analysis for {symbol} is {avg_polarity}\n")
|
||||
|
||||
export_data(
|
||||
export,
|
||||
|
||||
@@ -16,18 +16,23 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_historical(ticker: str, start: str, end: str, number: int) -> pd.DataFrame:
|
||||
"""Get hour-level sentiment data for the chosen ticker
|
||||
def get_historical(
|
||||
symbol: str,
|
||||
start_date: str = (datetime.utcnow() - timedelta(days=7)).strftime("%Y-%m-%d"),
|
||||
end_date: str = datetime.utcnow().strftime("%Y-%m-%d"),
|
||||
number: int = 100,
|
||||
) -> pd.DataFrame:
|
||||
"""Get hour-level sentiment data for the chosen symbol
|
||||
|
||||
Source: [Sentiment Investor]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker: str
|
||||
symbol: str
|
||||
Ticker to view sentiment data
|
||||
start: str
|
||||
start_date: str
|
||||
Initial date like string or unix timestamp (e.g. 12-21-2021)
|
||||
end: str
|
||||
end_date: str
|
||||
End date like string or unix timestamp (e.g. 12-21-2021)
|
||||
number : int
|
||||
Number of results returned by API call
|
||||
@@ -41,9 +46,9 @@ def get_historical(ticker: str, start: str, end: str, number: int) -> pd.DataFra
|
||||
|
||||
payload: Dict[str, Union[int, str]] = {
|
||||
"token": cfg.API_SENTIMENTINVESTOR_TOKEN,
|
||||
"symbol": ticker,
|
||||
"start": str(start),
|
||||
"end": str(end),
|
||||
"symbol": symbol,
|
||||
"start": str(start_date),
|
||||
"end": str(end_date),
|
||||
"limit": number,
|
||||
}
|
||||
|
||||
@@ -71,15 +76,15 @@ def get_historical(ticker: str, start: str, end: str, number: int) -> pd.DataFra
|
||||
return df
|
||||
|
||||
|
||||
def check_supported_ticker(ticker: str) -> bool:
|
||||
def check_supported_ticker(symbol: str) -> bool:
|
||||
"""Check if the ticker is supported
|
||||
|
||||
Source: [Sentiment Investor]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker: str
|
||||
Ticker to view sentiment data
|
||||
symbol: str
|
||||
Ticker symbol to view sentiment data
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -89,12 +94,14 @@ def check_supported_ticker(ticker: str) -> bool:
|
||||
|
||||
payload: Dict[str, str] = {
|
||||
"token": cfg.API_SENTIMENTINVESTOR_TOKEN,
|
||||
"symbol": ticker,
|
||||
"symbol": symbol,
|
||||
}
|
||||
|
||||
response = requests.get(
|
||||
"https://api.sentimentinvestor.com/v1/supported", params=payload
|
||||
)
|
||||
if response.status_code >= 500:
|
||||
return False
|
||||
response_json = response.json()
|
||||
|
||||
result = False
|
||||
@@ -105,7 +112,7 @@ def check_supported_ticker(ticker: str) -> bool:
|
||||
result = response_json["result"]
|
||||
else:
|
||||
console.print(
|
||||
f"[red]Ticker {ticker} not supported. Please try another one![/red]\n"
|
||||
f"[red]Ticker {symbol} not supported. Please try another one![/red]\n"
|
||||
)
|
||||
|
||||
elif "error" in response_json:
|
||||
@@ -117,7 +124,9 @@ def check_supported_ticker(ticker: str) -> bool:
|
||||
return result
|
||||
|
||||
|
||||
def get_trending(start: datetime, hour: int, number: int) -> pd.DataFrame:
|
||||
def get_trending(
|
||||
start_date: datetime = datetime.today(), hour: int = 0, number: int = 10
|
||||
) -> pd.DataFrame:
|
||||
"""Get sentiment data on the most talked about tickers
|
||||
within the last hour
|
||||
|
||||
@@ -125,7 +134,7 @@ def get_trending(start: datetime, hour: int, number: int) -> pd.DataFrame:
|
||||
|
||||
Parameters
|
||||
----------
|
||||
start: datetime
|
||||
start_date: datetime
|
||||
Datetime object (e.g. datetime(2021, 12, 21)
|
||||
hour: int
|
||||
Hour of the day in 24-hour notation (e.g. 14)
|
||||
@@ -140,7 +149,7 @@ def get_trending(start: datetime, hour: int, number: int) -> pd.DataFrame:
|
||||
"""
|
||||
|
||||
# type is datetime
|
||||
start_timestamp = start + timedelta(hours=hour)
|
||||
start_timestamp = start_date + timedelta(hours=hour)
|
||||
|
||||
payload: Dict[str, Union[int, str]] = {
|
||||
"token": cfg.API_SENTIMENTINVESTOR_TOKEN,
|
||||
@@ -152,6 +161,9 @@ def get_trending(start: datetime, hour: int, number: int) -> pd.DataFrame:
|
||||
response = requests.get(
|
||||
"https://api.sentimentinvestor.com/v1/trending", params=payload
|
||||
)
|
||||
if response.status_code >= 500:
|
||||
return pd.DataFrame()
|
||||
|
||||
response_json = response.json()
|
||||
|
||||
df = pd.DataFrame()
|
||||
|
||||
@@ -4,7 +4,7 @@ __docformat__ = "numpy"
|
||||
import logging
|
||||
import os
|
||||
from typing import Optional, List
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timedelta
|
||||
from matplotlib import pyplot as plt
|
||||
from matplotlib.lines import Line2D
|
||||
import pandas as pd
|
||||
@@ -29,13 +29,13 @@ logger = logging.getLogger(__name__)
|
||||
@log_start_end(log=logger)
|
||||
@check_api_key(["API_SENTIMENTINVESTOR_TOKEN"])
|
||||
def display_historical(
|
||||
ticker: str,
|
||||
start: str,
|
||||
end: str,
|
||||
export: str = "",
|
||||
symbol: str,
|
||||
start_date: str = (datetime.utcnow() - timedelta(days=7)).strftime("%Y-%m-%d"),
|
||||
end_date: str = datetime.utcnow().strftime("%Y-%m-%d"),
|
||||
number: int = 100,
|
||||
raw: bool = False,
|
||||
limit: int = 10,
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
"""Display historical sentiment data of a ticker,
|
||||
@@ -43,13 +43,13 @@ def display_historical(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker: str
|
||||
Ticker to view sentiment data
|
||||
start: str
|
||||
symbol: str
|
||||
Ticker symbol to view sentiment data
|
||||
start_date: str
|
||||
Initial date like string or unix timestamp (e.g. 2021-12-21)
|
||||
end: str
|
||||
end_date: str
|
||||
End date like string or unix timestamp (e.g. 2022-01-15)
|
||||
number : int
|
||||
number: int
|
||||
Number of results returned by API call
|
||||
Maximum 250 per api call
|
||||
raw: boolean
|
||||
@@ -57,23 +57,25 @@ def display_historical(
|
||||
limit: int
|
||||
Number of results display on the terminal
|
||||
Default: 10
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
export: str
|
||||
Format to export data
|
||||
external_axes: Optional[List[plt.Axes]], optional
|
||||
External axes (2 axes are expected in the list), by default None
|
||||
Returns
|
||||
-------
|
||||
"""
|
||||
|
||||
supported_ticker = sentimentinvestor_model.check_supported_ticker(ticker)
|
||||
supported_ticker = sentimentinvestor_model.check_supported_ticker(symbol)
|
||||
|
||||
# Check to see if the ticker is supported
|
||||
if not supported_ticker:
|
||||
logger.error("Ticker not supported")
|
||||
console.print(
|
||||
f"[red]Ticker {ticker} not supported. Please try another one![/red]\n"
|
||||
f"[red]Ticker {symbol} not supported. Please try another one![/red]\n"
|
||||
)
|
||||
return
|
||||
|
||||
df = sentimentinvestor_model.get_historical(ticker, start, end, number)
|
||||
df = sentimentinvestor_model.get_historical(symbol, start_date, end_date, number)
|
||||
|
||||
if df.empty:
|
||||
return
|
||||
@@ -144,18 +146,18 @@ def display_historical(
|
||||
@log_start_end(log=logger)
|
||||
@check_api_key(["API_SENTIMENTINVESTOR_TOKEN"])
|
||||
def display_trending(
|
||||
start: datetime,
|
||||
hour: int,
|
||||
export: str = "",
|
||||
start_date: datetime = datetime.today(),
|
||||
hour: int = 0,
|
||||
number: int = 10,
|
||||
limit: int = 10,
|
||||
export: str = "",
|
||||
):
|
||||
"""Display most talked about tickers within
|
||||
the last hour together with their sentiment data.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
start: datetime
|
||||
start_date: datetime
|
||||
Datetime object (e.g. datetime(2021, 12, 21)
|
||||
hour: int
|
||||
Hour of the day in 24-hour notation (e.g. 14)
|
||||
@@ -165,12 +167,15 @@ def display_trending(
|
||||
limit: int
|
||||
Number of results display on the terminal
|
||||
Default: 10
|
||||
-------
|
||||
Returns
|
||||
None
|
||||
export: str
|
||||
Format to export data
|
||||
"""
|
||||
|
||||
df = sentimentinvestor_model.get_trending(start, hour, number)
|
||||
# Force datetime format to be datetime(year, month, day, 0, 0)
|
||||
# 0 hours and minutes to look since day starts
|
||||
start_date = datetime(start_date.year, start_date.month, start_date.day)
|
||||
|
||||
df = sentimentinvestor_model.get_trending(start_date, hour, number)
|
||||
|
||||
if df.empty:
|
||||
return
|
||||
|
||||
@@ -13,13 +13,13 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_bullbear(ticker: str) -> Tuple[int, int, int, int]:
|
||||
def get_bullbear(symbol: str) -> Tuple[int, int, int, int]:
|
||||
"""Gets bullbear sentiment for ticker [Source: stocktwits]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker : str
|
||||
Ticker to look at
|
||||
symbol : str
|
||||
Ticker symbol to look at
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -33,7 +33,7 @@ def get_bullbear(ticker: str) -> Tuple[int, int, int, int]:
|
||||
Number of bearish statements
|
||||
"""
|
||||
result = requests.get(
|
||||
f"https://api.stocktwits.com/api/2/streams/symbol/{ticker}.json"
|
||||
f"https://api.stocktwits.com/api/2/streams/symbol/{symbol}.json"
|
||||
)
|
||||
if result.status_code == 200:
|
||||
result_json = result.json()
|
||||
@@ -52,28 +52,30 @@ def get_bullbear(ticker: str) -> Tuple[int, int, int, int]:
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_messages(ticker: str, limit: int = 30) -> List[str]:
|
||||
def get_messages(symbol: str, limit: int = 30) -> pd.DataFrame:
|
||||
"""Get last messages for a given ticker [Source: stocktwits]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker : str
|
||||
Stock ticker
|
||||
symbol : str
|
||||
Stock ticker symbol
|
||||
limit : int
|
||||
Number of messages to get
|
||||
|
||||
Returns
|
||||
-------
|
||||
List[str]
|
||||
List of messages
|
||||
pd.DataFrame
|
||||
Dataframe of messages
|
||||
"""
|
||||
result = requests.get(
|
||||
f"https://api.stocktwits.com/api/2/streams/symbol/{ticker}.json"
|
||||
f"https://api.stocktwits.com/api/2/streams/symbol/{symbol}.json"
|
||||
)
|
||||
if result.status_code == 200:
|
||||
return [message["body"] for message in result.json()["messages"][:limit]]
|
||||
return pd.DataFrame(
|
||||
[message["body"] for message in result.json()["messages"][:limit]]
|
||||
)
|
||||
|
||||
return []
|
||||
return pd.DataFrame()
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
|
||||
@@ -3,8 +3,6 @@ __docformat__ = "numpy"
|
||||
|
||||
import logging
|
||||
|
||||
import pandas as pd
|
||||
|
||||
from openbb_terminal.common.behavioural_analysis import stocktwits_model
|
||||
from openbb_terminal.decorators import log_start_end
|
||||
from openbb_terminal.helper_funcs import print_rich_table
|
||||
@@ -14,17 +12,17 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_bullbear(ticker: str):
|
||||
def display_bullbear(symbol: str):
|
||||
"""
|
||||
Print bullbear sentiment based on last 30 messages on the board.
|
||||
Also prints the watchlist_count. [Source: Stocktwits]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker: str
|
||||
Stock ticker
|
||||
symbol: str
|
||||
Stock ticker symbol
|
||||
"""
|
||||
watchlist_count, n_cases, n_bull, n_bear = stocktwits_model.get_bullbear(ticker)
|
||||
watchlist_count, n_cases, n_bull, n_bear = stocktwits_model.get_bullbear(symbol)
|
||||
console.print(f"Watchlist count: {watchlist_count}")
|
||||
if n_cases > 0:
|
||||
console.print(f"\nLast {n_cases} sentiment messages:")
|
||||
@@ -36,21 +34,21 @@ def display_bullbear(ticker: str):
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_messages(ticker: str, limit: int = 30):
|
||||
def display_messages(symbol: str, limit: int = 30):
|
||||
"""Print up to 30 of the last messages on the board. [Source: Stocktwits]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker: str
|
||||
Stock ticker
|
||||
symbol: str
|
||||
Stock ticker symbol
|
||||
limit: int
|
||||
Number of messages to get
|
||||
"""
|
||||
messages = stocktwits_model.get_messages(ticker, limit)
|
||||
messages = stocktwits_model.get_messages(symbol, limit)
|
||||
|
||||
if len(messages) > 0:
|
||||
if not messages.empty:
|
||||
print_rich_table(
|
||||
pd.DataFrame(messages),
|
||||
messages,
|
||||
headers=["MESSAGES"],
|
||||
show_index=False,
|
||||
title="Last Messages on Board",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"""Twitter Model"""
|
||||
__docformat__ = "numpy"
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
import logging
|
||||
from typing import Optional
|
||||
|
||||
@@ -20,22 +21,22 @@ analyzer = SentimentIntensityAnalyzer()
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def load_analyze_tweets(
|
||||
ticker: str,
|
||||
count: int = 100,
|
||||
start_time: Optional[str] = "",
|
||||
end_time: Optional[str] = "",
|
||||
symbol: str,
|
||||
limit: int = 100,
|
||||
start_date: Optional[str] = "",
|
||||
end_date: Optional[str] = "",
|
||||
) -> pd.DataFrame:
|
||||
"""Load tweets from twitter API and analyzes using VADER
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker: str
|
||||
Ticker to search twitter for
|
||||
count: int
|
||||
symbol: str
|
||||
Ticker symbol to search twitter for
|
||||
limit: int
|
||||
Number of tweets to analyze
|
||||
start : Optional[str]
|
||||
start_date: Optional[str]
|
||||
If given, the start time to get tweets from
|
||||
end : Optional[str]
|
||||
end_date: Optional[str]
|
||||
If given, the end time to get tweets from
|
||||
|
||||
Returns
|
||||
@@ -44,16 +45,16 @@ def load_analyze_tweets(
|
||||
Dataframe of tweets and sentiment
|
||||
"""
|
||||
params = {
|
||||
"query": rf"(\${ticker}) (lang:en)",
|
||||
"max_results": str(count),
|
||||
"query": rf"(\${symbol}) (lang:en)",
|
||||
"max_results": str(limit),
|
||||
"tweet.fields": "created_at,lang",
|
||||
}
|
||||
|
||||
if start_time:
|
||||
if start_date:
|
||||
# Assign from and to datetime parameters for the API
|
||||
params["start_time"] = start_time
|
||||
if end_time:
|
||||
params["end_time"] = end_time
|
||||
params["start_time"] = start_date
|
||||
if end_date:
|
||||
params["end_time"] = end_date
|
||||
|
||||
# Request Twitter API
|
||||
response = requests.get(
|
||||
@@ -105,7 +106,7 @@ def load_analyze_tweets(
|
||||
neu = []
|
||||
|
||||
for s_tweet in df_tweets["text"].to_list():
|
||||
tweet = clean_tweet(s_tweet, ticker)
|
||||
tweet = clean_tweet(s_tweet, symbol)
|
||||
sentiments.append(analyzer.polarity_scores(tweet)["compound"])
|
||||
pos.append(analyzer.polarity_scores(tweet)["pos"])
|
||||
neg.append(analyzer.polarity_scores(tweet)["neg"])
|
||||
@@ -117,3 +118,85 @@ def load_analyze_tweets(
|
||||
df_tweets["neutral"] = neu
|
||||
|
||||
return df_tweets
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_sentiment(
|
||||
symbol: str,
|
||||
n_tweets: int = 15,
|
||||
n_days_past: int = 2,
|
||||
):
|
||||
"""Get sentiments from symbol
|
||||
|
||||
Parameters
|
||||
----------
|
||||
symbol: str
|
||||
Stock ticker symbol to get sentiment for
|
||||
n_tweets: int
|
||||
Number of tweets to get per hour
|
||||
n_days_past: int
|
||||
Number of days to extract tweets for
|
||||
"""
|
||||
# Date format string required by twitter
|
||||
dt_format = "%Y-%m-%dT%H:%M:%SZ"
|
||||
|
||||
# Algorithm to extract
|
||||
dt_recent = datetime.utcnow() - timedelta(seconds=20)
|
||||
dt_old = dt_recent - timedelta(days=n_days_past)
|
||||
console.print(
|
||||
f"From {dt_recent.date()} retrieving {n_tweets*24} tweets ({n_tweets} tweets/hour)"
|
||||
)
|
||||
|
||||
df_tweets = pd.DataFrame(
|
||||
columns=[
|
||||
"created_at",
|
||||
"text",
|
||||
"sentiment",
|
||||
"positive",
|
||||
"negative",
|
||||
"neutral",
|
||||
]
|
||||
)
|
||||
while True:
|
||||
# Iterate until we haven't passed the old number of days
|
||||
if dt_recent < dt_old:
|
||||
break
|
||||
# Update past datetime
|
||||
dt_past = dt_recent - timedelta(minutes=60)
|
||||
|
||||
temp = load_analyze_tweets(
|
||||
symbol,
|
||||
n_tweets,
|
||||
start_date=dt_past.strftime(dt_format),
|
||||
end_date=dt_recent.strftime(dt_format),
|
||||
)
|
||||
|
||||
if temp.empty:
|
||||
return pd.DataFrame()
|
||||
|
||||
df_tweets = pd.concat([df_tweets, temp])
|
||||
|
||||
if dt_past.day < dt_recent.day:
|
||||
console.print(
|
||||
f"From {dt_past.date()} retrieving {n_tweets*24} tweets ({n_tweets} tweets/hour)"
|
||||
)
|
||||
|
||||
# Update recent datetime
|
||||
dt_recent = dt_past
|
||||
|
||||
# Sort tweets per date
|
||||
df_tweets.sort_index(ascending=False, inplace=True)
|
||||
df_tweets["cumulative_compound"] = df_tweets["sentiment"].cumsum()
|
||||
df_tweets["prob_sen"] = 1
|
||||
|
||||
# df_tweets.to_csv(r'notebooks/tweets.csv', index=False)
|
||||
df_tweets.reset_index(inplace=True)
|
||||
df_tweets["Month"] = pd.to_datetime(df_tweets["created_at"]).apply(
|
||||
lambda x: x.month
|
||||
)
|
||||
df_tweets["Day"] = pd.to_datetime(df_tweets["created_at"]).apply(lambda x: x.day)
|
||||
df_tweets["date"] = pd.to_datetime(df_tweets["created_at"])
|
||||
df_tweets = df_tweets.sort_values(by="date")
|
||||
df_tweets["cumulative_compound"] = df_tweets["sentiment"].cumsum()
|
||||
|
||||
return df_tweets
|
||||
|
||||
@@ -4,7 +4,6 @@ __docformat__ = "numpy"
|
||||
import logging
|
||||
import os
|
||||
from typing import Optional, List
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
@@ -27,19 +26,19 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_inference(ticker: str, num: int = 100, export: str = ""):
|
||||
def display_inference(symbol: str, limit: int = 100, export: str = ""):
|
||||
"""Infer sentiment from past n tweets
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker: str
|
||||
Stock ticker
|
||||
num: int
|
||||
symbol: str
|
||||
Stock ticker symbol
|
||||
limit: int
|
||||
Number of tweets to analyze
|
||||
export: str
|
||||
Format to export tweet dataframe
|
||||
"""
|
||||
df_tweets = twitter_model.load_analyze_tweets(ticker, num)
|
||||
df_tweets = twitter_model.load_analyze_tweets(symbol, limit)
|
||||
|
||||
if df_tweets.empty:
|
||||
return
|
||||
@@ -62,8 +61,8 @@ def display_inference(ticker: str, num: int = 100, export: str = ""):
|
||||
percent_neg = len(np.where(pos < neg)[0]) / len(df_tweets)
|
||||
total_sent = np.round(np.sum(df_tweets["sentiment"]), 2)
|
||||
mean_sent = np.round(np.mean(df_tweets["sentiment"]), 2)
|
||||
console.print(f"The summed compound sentiment of {ticker} is: {total_sent}")
|
||||
console.print(f"The average compound sentiment of {ticker} is: {mean_sent}")
|
||||
console.print(f"The summed compound sentiment of {symbol} is: {total_sent}")
|
||||
console.print(f"The average compound sentiment of {symbol} is: {mean_sent}")
|
||||
console.print(
|
||||
f"Of the last {len(df_tweets)} tweets, {100*percent_pos:.2f} % had a higher positive sentiment"
|
||||
)
|
||||
@@ -76,19 +75,19 @@ def display_inference(ticker: str, num: int = 100, export: str = ""):
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_sentiment(
|
||||
ticker: str,
|
||||
symbol: str,
|
||||
n_tweets: int = 15,
|
||||
n_days_past: int = 6,
|
||||
n_days_past: int = 2,
|
||||
compare: bool = False,
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
"""Plot sentiments from ticker
|
||||
"""Plot sentiments from symbol
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker: str
|
||||
Stock to get sentiment for
|
||||
symbol: str
|
||||
Stock ticker symbol to get sentiment for
|
||||
n_tweets: int
|
||||
Number of tweets to get per hour
|
||||
n_days_past: int
|
||||
@@ -97,145 +96,90 @@ def display_sentiment(
|
||||
Show corresponding change in stock price
|
||||
export: str
|
||||
Format to export tweet dataframe
|
||||
external_axes: Optional[List[plt.Axes]], optional
|
||||
External axes (1 axis is expected in the list), by default None
|
||||
"""
|
||||
# Date format string required by twitter
|
||||
dt_format = "%Y-%m-%dT%H:%M:%SZ"
|
||||
|
||||
# Algorithm to extract
|
||||
dt_recent = datetime.utcnow() - timedelta(seconds=20)
|
||||
dt_old = dt_recent - timedelta(days=n_days_past)
|
||||
console.print(
|
||||
f"From {dt_recent.date()} retrieving {n_tweets*24} tweets ({n_tweets} tweets/hour)"
|
||||
)
|
||||
df_tweets = twitter_model.get_sentiment(symbol, n_tweets, n_days_past)
|
||||
|
||||
df_tweets = pd.DataFrame(
|
||||
columns=[
|
||||
"created_at",
|
||||
"text",
|
||||
"sentiment",
|
||||
"positive",
|
||||
"negative",
|
||||
"neutral",
|
||||
]
|
||||
)
|
||||
while True:
|
||||
# Iterate until we haven't passed the old number of days
|
||||
if dt_recent < dt_old:
|
||||
break
|
||||
# Update past datetime
|
||||
dt_past = dt_recent - timedelta(minutes=60)
|
||||
if not df_tweets.empty:
|
||||
|
||||
temp = twitter_model.load_analyze_tweets(
|
||||
ticker,
|
||||
n_tweets,
|
||||
start_time=dt_past.strftime(dt_format),
|
||||
end_time=dt_recent.strftime(dt_format),
|
||||
)
|
||||
ax1, ax2, ax3 = None, None, None
|
||||
|
||||
if temp.empty:
|
||||
return
|
||||
|
||||
df_tweets = pd.concat([df_tweets, temp])
|
||||
|
||||
if dt_past.day < dt_recent.day:
|
||||
console.print(
|
||||
f"From {dt_past.date()} retrieving {n_tweets*24} tweets ({n_tweets} tweets/hour)"
|
||||
)
|
||||
|
||||
# Update recent datetime
|
||||
dt_recent = dt_past
|
||||
|
||||
# Sort tweets per date
|
||||
df_tweets.sort_index(ascending=False, inplace=True)
|
||||
df_tweets["cumulative_compound"] = df_tweets["sentiment"].cumsum()
|
||||
df_tweets["prob_sen"] = 1
|
||||
|
||||
# df_tweets.to_csv(r'notebooks/tweets.csv', index=False)
|
||||
df_tweets.reset_index(inplace=True)
|
||||
df_tweets["Month"] = pd.to_datetime(df_tweets["created_at"]).apply(
|
||||
lambda x: x.month
|
||||
)
|
||||
df_tweets["Day"] = pd.to_datetime(df_tweets["created_at"]).apply(lambda x: x.day)
|
||||
df_tweets["date"] = pd.to_datetime(df_tweets["created_at"])
|
||||
df_tweets = df_tweets.sort_values(by="date")
|
||||
df_tweets["cumulative_compound"] = df_tweets["sentiment"].cumsum()
|
||||
|
||||
ax1, ax2, ax3 = None, None, None
|
||||
|
||||
if compare:
|
||||
# This plot has 3 axes
|
||||
if external_axes is None:
|
||||
_, axes = plt.subplots(
|
||||
3, 1, sharex=False, figsize=plot_autoscale(), dpi=cfg_plot.PLOT_DPI
|
||||
)
|
||||
ax1, ax2, ax3 = axes
|
||||
elif is_valid_axes_count(external_axes, 3):
|
||||
(ax1, ax2, ax3) = external_axes
|
||||
if compare:
|
||||
# This plot has 3 axes
|
||||
if external_axes is None:
|
||||
_, axes = plt.subplots(
|
||||
3, 1, sharex=False, figsize=plot_autoscale(), dpi=cfg_plot.PLOT_DPI
|
||||
)
|
||||
ax1, ax2, ax3 = axes
|
||||
elif is_valid_axes_count(external_axes, 3):
|
||||
(ax1, ax2, ax3) = external_axes
|
||||
else:
|
||||
return
|
||||
else:
|
||||
return
|
||||
else:
|
||||
# This plot has 2 axes
|
||||
if external_axes is None:
|
||||
_, axes = plt.subplots(
|
||||
2, 1, sharex=True, figsize=plot_autoscale(), dpi=cfg_plot.PLOT_DPI
|
||||
)
|
||||
ax1, ax2 = axes
|
||||
elif is_valid_axes_count(external_axes, 2):
|
||||
(ax1, ax2) = external_axes
|
||||
else:
|
||||
return
|
||||
# This plot has 2 axes
|
||||
if external_axes is None:
|
||||
_, axes = plt.subplots(
|
||||
2, 1, sharex=True, figsize=plot_autoscale(), dpi=cfg_plot.PLOT_DPI
|
||||
)
|
||||
ax1, ax2 = axes
|
||||
elif is_valid_axes_count(external_axes, 2):
|
||||
(ax1, ax2) = external_axes
|
||||
else:
|
||||
return
|
||||
|
||||
ax1.plot(
|
||||
pd.to_datetime(df_tweets["created_at"]),
|
||||
df_tweets["cumulative_compound"].values,
|
||||
)
|
||||
ax1.set_ylabel("\nCumulative\nVADER Sentiment")
|
||||
for _, day_df in df_tweets.groupby(by="Day"):
|
||||
day_df["time"] = pd.to_datetime(day_df["created_at"])
|
||||
day_df = day_df.sort_values(by="time")
|
||||
ax1.plot(
|
||||
day_df["time"],
|
||||
day_df["sentiment"].cumsum(),
|
||||
label=pd.to_datetime(day_df["date"]).iloc[0].strftime("%Y-%m-%d"),
|
||||
pd.to_datetime(df_tweets["created_at"]),
|
||||
df_tweets["cumulative_compound"].values,
|
||||
)
|
||||
ax1.set_ylabel("\nCumulative\nVADER Sentiment")
|
||||
for _, day_df in df_tweets.groupby(by="Day"):
|
||||
day_df["time"] = pd.to_datetime(day_df["created_at"])
|
||||
day_df = day_df.sort_values(by="time")
|
||||
ax1.plot(
|
||||
day_df["time"],
|
||||
day_df["sentiment"].cumsum(),
|
||||
label=pd.to_datetime(day_df["date"]).iloc[0].strftime("%Y-%m-%d"),
|
||||
)
|
||||
ax2.bar(
|
||||
df_tweets["date"],
|
||||
df_tweets["positive"],
|
||||
color=theme.up_color,
|
||||
width=theme.volume_bar_width / 100,
|
||||
)
|
||||
ax2.bar(
|
||||
df_tweets["date"],
|
||||
df_tweets["positive"],
|
||||
color=theme.up_color,
|
||||
-1 * df_tweets["negative"],
|
||||
color=theme.down_color,
|
||||
width=theme.volume_bar_width / 100,
|
||||
)
|
||||
ax2.bar(
|
||||
df_tweets["date"],
|
||||
-1 * df_tweets["negative"],
|
||||
color=theme.down_color,
|
||||
width=theme.volume_bar_width / 100,
|
||||
)
|
||||
ax1.set_title(
|
||||
f"Twitter's {ticker} total compound sentiment over time is {round(np.sum(df_tweets['sentiment']), 2)}"
|
||||
)
|
||||
ax1.set_title(
|
||||
f"Twitter's {symbol} total compound sentiment over time is {round(np.sum(df_tweets['sentiment']), 2)}"
|
||||
)
|
||||
|
||||
theme.style_primary_axis(ax1)
|
||||
theme.style_primary_axis(ax1)
|
||||
|
||||
ax2.set_ylabel("VADER Polarity Scores")
|
||||
theme.style_primary_axis(ax2)
|
||||
ax2.set_ylabel("VADER Polarity Scores")
|
||||
theme.style_primary_axis(ax2)
|
||||
|
||||
if compare:
|
||||
# get stock end price for each corresponding day if compare == True
|
||||
closing_price_df = get_closing_price(ticker, n_days_past)
|
||||
if ax3:
|
||||
ax3.plot(
|
||||
closing_price_df["Date"],
|
||||
closing_price_df["Close"],
|
||||
label=pd.to_datetime(closing_price_df["Date"])
|
||||
.iloc[0]
|
||||
.strftime("%Y-%m-%d"),
|
||||
)
|
||||
if compare:
|
||||
# get stock end price for each corresponding day if compare == True
|
||||
closing_price_df = get_closing_price(symbol, n_days_past)
|
||||
if ax3:
|
||||
ax3.plot(
|
||||
closing_price_df["Date"],
|
||||
closing_price_df["Close"],
|
||||
label=pd.to_datetime(closing_price_df["Date"])
|
||||
.iloc[0]
|
||||
.strftime("%Y-%m-%d"),
|
||||
)
|
||||
|
||||
ax3.set_ylabel("Stock Price")
|
||||
theme.style_primary_axis(ax3)
|
||||
ax3.set_ylabel("Stock Price")
|
||||
theme.style_primary_axis(ax3)
|
||||
|
||||
if external_axes is None:
|
||||
theme.visualize_output()
|
||||
if external_axes is None:
|
||||
theme.visualize_output()
|
||||
|
||||
export_data(
|
||||
export, os.path.dirname(os.path.abspath(__file__)), "sentiment", df_tweets
|
||||
|
||||
@@ -3,6 +3,7 @@ __docformat__ = "numpy"
|
||||
|
||||
import logging
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Dict
|
||||
import requests
|
||||
from openbb_terminal import config_terminal as cfg
|
||||
@@ -14,8 +15,8 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_news(
|
||||
term: str,
|
||||
s_from: str,
|
||||
query: str,
|
||||
start_date: str = (datetime.now() - timedelta(days=7)).strftime("%Y-%m-%d"),
|
||||
show_newest: bool = True,
|
||||
sources: str = "",
|
||||
) -> Dict:
|
||||
@@ -23,9 +24,9 @@ def get_news(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
term : str
|
||||
query : str
|
||||
term to search on the news articles
|
||||
s_from: str
|
||||
start_date: str
|
||||
date to start searching articles from formatted YYYY-MM-DD
|
||||
show_newest: bool
|
||||
flag to show newest articles first
|
||||
@@ -38,7 +39,7 @@ def get_news(
|
||||
term to search on the news articles
|
||||
"""
|
||||
link = (
|
||||
f"https://newsapi.org/v2/everything?q={term}&from={s_from}&sortBy=publishedAt&language=en"
|
||||
f"https://newsapi.org/v2/everything?q={query}&from={start_date}&sortBy=publishedAt&language=en"
|
||||
f"&apiKey={cfg.API_NEWS_TOKEN}"
|
||||
)
|
||||
|
||||
@@ -53,7 +54,7 @@ def get_news(
|
||||
if response.status_code == 200:
|
||||
response_json = response.json()
|
||||
console.print(
|
||||
f"{response_json['totalResults']} news articles for {term} were found since {s_from}\n"
|
||||
f"{response_json['totalResults']} news articles for {query} were found since {start_date}\n"
|
||||
)
|
||||
|
||||
if show_newest:
|
||||
|
||||
@@ -3,6 +3,7 @@ __docformat__ = "numpy"
|
||||
|
||||
import logging
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
import pandas as pd
|
||||
|
||||
from openbb_terminal.decorators import check_api_key
|
||||
@@ -16,9 +17,9 @@ logger = logging.getLogger(__name__)
|
||||
@log_start_end(log=logger)
|
||||
@check_api_key(["API_NEWS_TOKEN"])
|
||||
def display_news(
|
||||
term: str,
|
||||
s_from: str,
|
||||
num: int = 3,
|
||||
query: str,
|
||||
start_date: str = (datetime.now() - timedelta(days=7)).strftime("%Y-%m-%d"),
|
||||
limit: int = 3,
|
||||
show_newest: bool = True,
|
||||
sources: str = "",
|
||||
):
|
||||
@@ -26,18 +27,18 @@ def display_news(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
term : str
|
||||
query : str
|
||||
term to search on the news articles
|
||||
s_from: str
|
||||
start_date: str
|
||||
date to start searching articles from formatted YYYY-MM-DD
|
||||
num : int
|
||||
limit : int
|
||||
number of articles to display
|
||||
show_newest: bool
|
||||
flag to show newest articles first
|
||||
sources: str
|
||||
sources to exclusively show news from
|
||||
"""
|
||||
articles = newsapi_model.get_news(term, s_from, show_newest, sources)
|
||||
articles = newsapi_model.get_news(query, start_date, show_newest, sources)
|
||||
|
||||
if articles:
|
||||
for idx, article in enumerate(articles):
|
||||
@@ -53,5 +54,5 @@ def display_news(
|
||||
)
|
||||
print_rich_table(table, title=article["title"])
|
||||
|
||||
if idx >= num - 1:
|
||||
if idx >= limit - 1:
|
||||
break
|
||||
|
||||
@@ -47,7 +47,7 @@ def display_arima(
|
||||
seasonal: bool,
|
||||
ic: str,
|
||||
results: bool,
|
||||
s_end_date: str = "",
|
||||
end_date: str = "",
|
||||
export: str = "",
|
||||
time_res: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
@@ -70,7 +70,7 @@ def display_arima(
|
||||
Information Criteria for model evaluation
|
||||
results : bool
|
||||
Flag to display model summary
|
||||
s_end_date : str, optional
|
||||
end_date : str, optional
|
||||
Specified end date for backtesting comparisons
|
||||
export : str, optional
|
||||
Format to export image
|
||||
@@ -82,14 +82,14 @@ def display_arima(
|
||||
|
||||
if arima_order:
|
||||
t_order = tuple(int(ord) for ord in arima_order.split(","))
|
||||
if s_end_date:
|
||||
if end_date:
|
||||
if not time_res:
|
||||
future_index = get_next_stock_market_days(
|
||||
last_stock_day=s_end_date, n_next_days=n_predict
|
||||
last_stock_day=end_date, n_next_days=n_predict
|
||||
)
|
||||
else:
|
||||
future_index = pd.date_range(
|
||||
s_end_date, periods=n_predict + 1, freq=time_res
|
||||
end_date, periods=n_predict + 1, freq=time_res
|
||||
)[1:]
|
||||
|
||||
if future_index[-1] > datetime.datetime.now():
|
||||
@@ -99,7 +99,7 @@ def display_arima(
|
||||
return
|
||||
|
||||
df_future = values[future_index[0] : future_index[-1]] # noqa: E203
|
||||
values = values[:s_end_date] # type: ignore
|
||||
values = values[:end_date] # type: ignore
|
||||
|
||||
l_predictions, model = arima_model.get_arima_model(
|
||||
values, arima_order, n_predict, seasonal, ic
|
||||
@@ -125,17 +125,17 @@ def display_arima(
|
||||
# This plot has 1 axis
|
||||
if external_axes is None:
|
||||
_, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
|
||||
elif s_end_date and not is_valid_axes_count(
|
||||
elif end_date and not is_valid_axes_count(
|
||||
external_axes,
|
||||
3,
|
||||
prefix_text="If there is s_end_date",
|
||||
prefix_text="If there is end_date",
|
||||
suffix_text="when backtesting",
|
||||
):
|
||||
return
|
||||
elif not s_end_date and not is_valid_axes_count(
|
||||
elif not end_date and not is_valid_axes_count(
|
||||
external_axes,
|
||||
1,
|
||||
prefix_text="If there is no s_end_date",
|
||||
prefix_text="If there is no end_date",
|
||||
suffix_text="when backtesting",
|
||||
):
|
||||
return
|
||||
@@ -148,7 +148,7 @@ def display_arima(
|
||||
|
||||
if arima_order:
|
||||
# BACKTESTING
|
||||
if s_end_date:
|
||||
if end_date:
|
||||
ax.set_title(
|
||||
f"BACKTESTING: ARIMA {str(t_order)} on {dataset} - {n_predict} step prediction"
|
||||
)
|
||||
@@ -158,7 +158,7 @@ def display_arima(
|
||||
)
|
||||
else:
|
||||
# BACKTESTING
|
||||
if s_end_date:
|
||||
if end_date:
|
||||
ax.set_title(
|
||||
f"BACKTESTING: ARIMA {model.order} on {dataset} - {n_predict} step prediction"
|
||||
)
|
||||
@@ -178,7 +178,7 @@ def display_arima(
|
||||
ax.vlines(values.index[-1], ymin, ymax, linestyle="--")
|
||||
|
||||
# BACKTESTING
|
||||
if s_end_date:
|
||||
if end_date:
|
||||
ax.plot(
|
||||
df_future.index,
|
||||
df_future,
|
||||
@@ -201,7 +201,7 @@ def display_arima(
|
||||
theme.visualize_output()
|
||||
|
||||
# BACKTESTING
|
||||
if s_end_date:
|
||||
if end_date:
|
||||
# This plot has 3 axes
|
||||
if external_axes is None:
|
||||
_, axes = plt.subplots(
|
||||
|
||||
@@ -38,13 +38,13 @@ warnings.filterwarnings("ignore")
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_exponential_smoothing(
|
||||
ticker: str,
|
||||
values: Union[pd.DataFrame, pd.Series],
|
||||
dataset: str,
|
||||
data: Union[pd.DataFrame, pd.Series],
|
||||
n_predict: int,
|
||||
trend: str = "N",
|
||||
seasonal: str = "N",
|
||||
seasonal_periods: int = 7,
|
||||
s_end_date: str = "",
|
||||
end_date: str = "",
|
||||
export: str = "",
|
||||
time_res: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
@@ -53,9 +53,9 @@ def display_exponential_smoothing(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker : str
|
||||
dataset : str
|
||||
Dataset being smoothed
|
||||
values : Union[pd.DataFrame, pd.Series]
|
||||
data : Union[pd.DataFrame, pd.Series]
|
||||
Raw data
|
||||
n_predict : int
|
||||
Days to predict
|
||||
@@ -65,7 +65,7 @@ def display_exponential_smoothing(
|
||||
Seasonal variable, by default "N"
|
||||
seasonal_periods : int, optional
|
||||
Number of seasonal periods, by default 5
|
||||
s_end_date : str, optional
|
||||
end_date : str, optional
|
||||
End date for backtesting, by default ""
|
||||
export : str, optional
|
||||
Format to export data, by default ""
|
||||
@@ -74,14 +74,14 @@ def display_exponential_smoothing(
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
External axes (1 axis is expected in the list), by default None
|
||||
"""
|
||||
if s_end_date:
|
||||
if end_date:
|
||||
if not time_res:
|
||||
future_index = get_next_stock_market_days(
|
||||
last_stock_day=s_end_date, n_next_days=n_predict
|
||||
last_stock_day=end_date, n_next_days=n_predict
|
||||
)
|
||||
else:
|
||||
future_index = pd.date_range(
|
||||
s_end_date, periods=n_predict + 1, freq=time_res
|
||||
end_date, periods=n_predict + 1, freq=time_res
|
||||
)[1:]
|
||||
|
||||
if future_index[-1] > datetime.datetime.now():
|
||||
@@ -91,12 +91,12 @@ def display_exponential_smoothing(
|
||||
)
|
||||
return
|
||||
|
||||
df_future = values[future_index[0] : future_index[-1]] # noqa: E203
|
||||
values = values[:s_end_date] # type: ignore
|
||||
df_future = data[future_index[0] : future_index[-1]] # noqa: E203
|
||||
data = data[:end_date] # type: ignore
|
||||
|
||||
# Get ETS model
|
||||
model, title, forecast = ets_model.get_exponential_smoothing_model(
|
||||
values, trend, seasonal, seasonal_periods, n_predict
|
||||
data, trend, seasonal, seasonal_periods, n_predict
|
||||
)
|
||||
|
||||
if not forecast:
|
||||
@@ -109,12 +109,12 @@ def display_exponential_smoothing(
|
||||
|
||||
if not time_res:
|
||||
l_pred_days = get_next_stock_market_days(
|
||||
last_stock_day=values.index[-1],
|
||||
last_stock_day=data.index[-1],
|
||||
n_next_days=n_predict,
|
||||
)
|
||||
else:
|
||||
l_pred_days = pd.date_range(
|
||||
values.index[-1], periods=n_predict + 1, freq=time_res
|
||||
data.index[-1], periods=n_predict + 1, freq=time_res
|
||||
)[1:]
|
||||
|
||||
df_pred = pd.Series(forecast, index=l_pred_days, name="Price")
|
||||
@@ -135,52 +135,52 @@ def display_exponential_smoothing(
|
||||
if external_axes is None:
|
||||
_, ax1 = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
|
||||
|
||||
elif s_end_date and not is_valid_axes_count(
|
||||
elif end_date and not is_valid_axes_count(
|
||||
external_axes,
|
||||
3,
|
||||
prefix_text="If there is s_end_date",
|
||||
prefix_text="If there is end_date",
|
||||
suffix_text="when backtesting",
|
||||
):
|
||||
return
|
||||
elif not s_end_date and not is_valid_axes_count(
|
||||
elif not end_date and not is_valid_axes_count(
|
||||
external_axes,
|
||||
1,
|
||||
prefix_text="If there is no s_end_date",
|
||||
prefix_text="If there is no end_date",
|
||||
suffix_text="when backtesting",
|
||||
):
|
||||
return
|
||||
else:
|
||||
ax1 = external_axes[0]
|
||||
|
||||
ax1.plot(values.index, values.values)
|
||||
ax1.plot(data.index, data.values)
|
||||
|
||||
# BACKTESTING
|
||||
if s_end_date:
|
||||
ax1.set_title(f"BACKTESTING: {title} on {ticker}", fontsize=12)
|
||||
if end_date:
|
||||
ax1.set_title(f"BACKTESTING: {title} on {dataset}", fontsize=12)
|
||||
else:
|
||||
ax1.set_title(f"{title} on {ticker}", fontsize=12)
|
||||
ax1.set_title(f"{title} on {dataset}", fontsize=12)
|
||||
|
||||
ax1.set_xlim(
|
||||
values.index[0],
|
||||
data.index[0],
|
||||
get_next_stock_market_days(df_pred.index[-1], 1)[-1],
|
||||
)
|
||||
ax1.set_ylabel("Value")
|
||||
ax1.plot(
|
||||
[values.index[-1], df_pred.index[0]],
|
||||
[values.values[-1], df_pred.values[0]],
|
||||
[data.index[-1], df_pred.index[0]],
|
||||
[data.values[-1], df_pred.values[0]],
|
||||
color=theme.down_color,
|
||||
linestyle="--",
|
||||
)
|
||||
ax1.plot(df_pred.index, df_pred, color=theme.down_color)
|
||||
ax1.axvspan(
|
||||
values.index[-1],
|
||||
data.index[-1],
|
||||
df_pred.index[-1],
|
||||
facecolor=theme.down_color,
|
||||
alpha=0.2,
|
||||
)
|
||||
_, _, ymin, ymax = plt.axis()
|
||||
ax1.vlines(
|
||||
values.index[-1],
|
||||
data.index[-1],
|
||||
ymin,
|
||||
ymax,
|
||||
linestyle="--",
|
||||
@@ -188,7 +188,7 @@ def display_exponential_smoothing(
|
||||
)
|
||||
|
||||
# BACKTESTING
|
||||
if s_end_date:
|
||||
if end_date:
|
||||
ax1.plot(
|
||||
df_future.index,
|
||||
df_future,
|
||||
@@ -196,9 +196,9 @@ def display_exponential_smoothing(
|
||||
linestyle="--",
|
||||
)
|
||||
ax1.plot(
|
||||
[values.index[-1], df_future.index[0]],
|
||||
[data.index[-1], df_future.index[0]],
|
||||
[
|
||||
values.values[-1],
|
||||
data.values[-1],
|
||||
df_future.values[0],
|
||||
],
|
||||
color=theme.up_color,
|
||||
@@ -211,7 +211,7 @@ def display_exponential_smoothing(
|
||||
theme.visualize_output()
|
||||
|
||||
# BACKTESTING
|
||||
if s_end_date:
|
||||
if end_date:
|
||||
# This plot has 3 axes
|
||||
if external_axes is None:
|
||||
_, axes = plt.subplots(
|
||||
@@ -236,9 +236,9 @@ def display_exponential_smoothing(
|
||||
color=theme.up_color,
|
||||
)
|
||||
ax2.plot(
|
||||
[values.index[-1], df_future.index[0]],
|
||||
[data.index[-1], df_future.index[0]],
|
||||
[
|
||||
values.values[-1],
|
||||
data.values[-1],
|
||||
df_future.values[0],
|
||||
],
|
||||
color=theme.up_color,
|
||||
@@ -246,13 +246,13 @@ def display_exponential_smoothing(
|
||||
)
|
||||
ax2.scatter(df_pred.index, df_pred)
|
||||
ax2.plot(
|
||||
[values.index[-1], df_pred.index[0]],
|
||||
[values.values[-1], df_pred.values[0]],
|
||||
[data.index[-1], df_pred.index[0]],
|
||||
[data.values[-1], df_pred.values[0]],
|
||||
linestyle="--",
|
||||
)
|
||||
ax2.set_title("BACKTESTING: Values")
|
||||
ax2.set_xlim(
|
||||
values.index[-1],
|
||||
data.index[-1],
|
||||
df_pred.index[-1] + datetime.timedelta(days=1),
|
||||
)
|
||||
ax2.set_ylabel("Value")
|
||||
@@ -272,7 +272,7 @@ def display_exponential_smoothing(
|
||||
)
|
||||
ax3.set_title("BACKTESTING: % Error")
|
||||
ax3.plot(
|
||||
[values.index[-1], df_future.index[0]],
|
||||
[data.index[-1], df_future.index[0]],
|
||||
[
|
||||
0,
|
||||
100 * (df_pred.values[0] - df_future.values[0]) / df_future.values[0],
|
||||
@@ -281,7 +281,7 @@ def display_exponential_smoothing(
|
||||
color=theme.down_color,
|
||||
)
|
||||
ax3.set_xlim(
|
||||
values.index[-1],
|
||||
data.index[-1],
|
||||
df_pred.index[-1] + datetime.timedelta(days=1),
|
||||
)
|
||||
ax3.set_ylabel("Prediction Error (%)")
|
||||
@@ -313,5 +313,5 @@ def display_exponential_smoothing(
|
||||
|
||||
else:
|
||||
# Print prediction data
|
||||
print_pretty_prediction(df_pred, values.values[-1])
|
||||
print_pretty_prediction(df_pred, data.values[-1])
|
||||
export_data(export, os.path.dirname(os.path.abspath(__file__)), "ets")
|
||||
|
||||
@@ -22,7 +22,7 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_k_nearest_neighbors(
|
||||
ticker: str,
|
||||
dataset: str,
|
||||
data: Union[pd.DataFrame, pd.Series],
|
||||
n_neighbors: int,
|
||||
n_input_days: int,
|
||||
@@ -37,8 +37,8 @@ def display_k_nearest_neighbors(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker : str
|
||||
Stock data
|
||||
dataset : str
|
||||
Dataset label
|
||||
data : Union[pd.DataFrame, pd.Series]
|
||||
Data to use for ML
|
||||
n_neighbors : int
|
||||
@@ -83,7 +83,7 @@ def display_k_nearest_neighbors(
|
||||
y_valid=y_valid,
|
||||
y_dates_valid=y_dates_valid,
|
||||
scaler=scaler,
|
||||
title=f"KNN Model with {n_neighbors} Neighbors on {ticker}",
|
||||
title=f"KNN Model with {n_neighbors} Neighbors on {dataset}",
|
||||
forecast_data=forecast_data_df,
|
||||
n_loops=1,
|
||||
time_str=time_res,
|
||||
|
||||
@@ -43,7 +43,7 @@ def display_regression(
|
||||
n_input: int,
|
||||
n_predict: int,
|
||||
n_jumps: int,
|
||||
s_end_date: str = "",
|
||||
end_date: str = "",
|
||||
export: str = "",
|
||||
time_res: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
@@ -64,7 +64,7 @@ def display_regression(
|
||||
Length of prediction sequence
|
||||
n_jumps : int
|
||||
Number of jumps in data
|
||||
s_end_date : str, optional
|
||||
end_date : str, optional
|
||||
Start date for backtesting
|
||||
export : str, optional
|
||||
Format for exporting figures
|
||||
@@ -74,18 +74,18 @@ def display_regression(
|
||||
External axes (1 axis is expected in the list), by default None
|
||||
"""
|
||||
# BACKTESTING
|
||||
if s_end_date:
|
||||
if end_date:
|
||||
if not time_res:
|
||||
future_index = get_next_stock_market_days(
|
||||
last_stock_day=s_end_date, n_next_days=n_predict
|
||||
last_stock_day=end_date, n_next_days=n_predict
|
||||
)
|
||||
else:
|
||||
future_index = pd.date_range(
|
||||
s_end_date, periods=n_predict + 1, freq=time_res
|
||||
end_date, periods=n_predict + 1, freq=time_res
|
||||
)[1:]
|
||||
|
||||
df_future = values[future_index[0] : future_index[-1]] # noqa: E203
|
||||
values = values[:s_end_date] # type: ignore
|
||||
values = values[:end_date] # type: ignore
|
||||
|
||||
l_predictions, _ = regression_model.get_regression_model(
|
||||
list(values.values), poly_order, n_input, n_predict, n_jumps
|
||||
@@ -108,17 +108,17 @@ def display_regression(
|
||||
# This plot has 1 axis
|
||||
if external_axes is None:
|
||||
_, ax1 = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
|
||||
elif s_end_date and not is_valid_axes_count(
|
||||
elif end_date and not is_valid_axes_count(
|
||||
external_axes,
|
||||
3,
|
||||
prefix_text="If there is s_end_date",
|
||||
prefix_text="If there is end_date",
|
||||
suffix_text="when backtesting",
|
||||
):
|
||||
return
|
||||
elif not s_end_date and not is_valid_axes_count(
|
||||
elif not end_date and not is_valid_axes_count(
|
||||
external_axes,
|
||||
1,
|
||||
prefix_text="If there is no s_end_date",
|
||||
prefix_text="If there is no end_date",
|
||||
suffix_text="when backtesting",
|
||||
):
|
||||
return
|
||||
@@ -127,7 +127,7 @@ def display_regression(
|
||||
|
||||
ax1.plot(values.index, values)
|
||||
# BACKTESTING
|
||||
if s_end_date:
|
||||
if end_date:
|
||||
ax1.set_title(
|
||||
f"BACKTESTING: Regression (polynomial {poly_order}) on {dataset} - {n_predict} step prediction",
|
||||
fontsize=12,
|
||||
@@ -150,7 +150,7 @@ def display_regression(
|
||||
ax1.vlines(values.index[-1], ymin, ymax, linestyle="--")
|
||||
|
||||
# BACKTESTING
|
||||
if s_end_date:
|
||||
if end_date:
|
||||
ax1.plot(
|
||||
df_future.index,
|
||||
df_future,
|
||||
@@ -175,7 +175,7 @@ def display_regression(
|
||||
console.print("")
|
||||
|
||||
# BACKTESTING
|
||||
if s_end_date:
|
||||
if end_date:
|
||||
# This plot has 3 axes
|
||||
if external_axes is None:
|
||||
_, axes = plt.subplots(
|
||||
|
||||
@@ -22,16 +22,16 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_summary(df: pd.DataFrame) -> pd.DataFrame:
|
||||
def get_summary(data: pd.DataFrame) -> pd.DataFrame:
|
||||
"""Print summary statistics
|
||||
|
||||
Parameters
|
||||
----------
|
||||
df : pd.DataFrame
|
||||
data : pd.DataFrame
|
||||
Dataframe to get summary statistics for
|
||||
"""
|
||||
|
||||
df_stats = df.describe(percentiles=[0.1, 0.25, 0.5, 0.75, 0.9])
|
||||
df_stats = data.describe(percentiles=[0.1, 0.25, 0.5, 0.75, 0.9])
|
||||
df_stats.loc["var"] = df_stats.loc["std"] ** 2
|
||||
|
||||
return df_stats
|
||||
@@ -39,13 +39,13 @@ def get_summary(df: pd.DataFrame) -> pd.DataFrame:
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_seasonal_decomposition(
|
||||
df: pd.DataFrame, multiplicative: bool
|
||||
data: pd.DataFrame, multiplicative: bool = False
|
||||
) -> Tuple[Any, pd.DataFrame, pd.DataFrame]:
|
||||
"""Perform seasonal decomposition
|
||||
|
||||
Parameters
|
||||
----------
|
||||
df_stock : pd.DataFrame
|
||||
data : pd.DataFrame
|
||||
Dataframe of targeted data
|
||||
multiplicative : bool
|
||||
Boolean to indicate multiplication instead of addition
|
||||
@@ -66,7 +66,7 @@ def get_seasonal_decomposition(
|
||||
|
||||
model = ["additive", "multiplicative"][multiplicative]
|
||||
|
||||
result = seasonal_decompose(df, model=model, period=seasonal_periods)
|
||||
result = seasonal_decompose(data, model=model, period=seasonal_periods)
|
||||
cycle, trend = sm.tsa.filters.hpfilter(
|
||||
result.trend[result.trend.notna().values], lamb=lamb
|
||||
)
|
||||
@@ -83,7 +83,7 @@ def get_normality(data: pd.DataFrame) -> pd.DataFrame:
|
||||
|
||||
Parameters
|
||||
----------
|
||||
df : pd.DataFrame
|
||||
data : pd.DataFrame
|
||||
Dataframe of targeted data
|
||||
|
||||
Returns
|
||||
@@ -129,17 +129,19 @@ def get_normality(data: pd.DataFrame) -> pd.DataFrame:
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_unitroot(df: pd.DataFrame, fuller_reg: str, kpss_reg: str) -> pd.DataFrame:
|
||||
def get_unitroot(
|
||||
data: pd.DataFrame, fuller_reg: str = "c", kpss_reg: str = "c"
|
||||
) -> pd.DataFrame:
|
||||
"""Calculate test statistics for unit roots
|
||||
|
||||
Parameters
|
||||
----------
|
||||
df : pd.DataFrame
|
||||
data : pd.DataFrame
|
||||
DataFrame of target variable
|
||||
fuller_reg : str
|
||||
Type of regression of ADF test
|
||||
Type of regression of ADF test. Can be ‘c’,’ct’,’ctt’,’nc’ 'c' - Constant and t - trend order
|
||||
kpss_reg : str
|
||||
Type of regression for KPSS test
|
||||
Type of regression for KPSS test. Can be ‘c’,’ct'
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -149,10 +151,10 @@ def get_unitroot(df: pd.DataFrame, fuller_reg: str, kpss_reg: str) -> pd.DataFra
|
||||
# The Augmented Dickey-Fuller test
|
||||
# Used to test for a unit root in a univariate process in the presence of serial correlation.
|
||||
try:
|
||||
result = adfuller(df, regression=fuller_reg)
|
||||
result = adfuller(data, regression=fuller_reg)
|
||||
except MissingDataError:
|
||||
df = df.dropna(axis=0)
|
||||
result = adfuller(df, regression=fuller_reg)
|
||||
data = data.dropna(axis=0)
|
||||
result = adfuller(data, regression=fuller_reg)
|
||||
cols = ["Test Statistic", "P-Value", "NLags", "Nobs", "ICBest"]
|
||||
vals = [result[0], result[1], result[2], result[3], result[5]]
|
||||
data = pd.DataFrame(data=vals, index=cols, columns=["ADF"])
|
||||
@@ -165,7 +167,7 @@ def get_unitroot(df: pd.DataFrame, fuller_reg: str, kpss_reg: str) -> pd.DataFra
|
||||
# Wrap this in catch_warnings to prevent
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
res2 = kpss(df, regression=kpss_reg, nlags="auto")
|
||||
res2 = kpss(data, regression=kpss_reg, nlags="auto")
|
||||
vals2 = [res2[0], res2[1], res2[2], "", ""]
|
||||
data["KPSS"] = vals2
|
||||
return data
|
||||
@@ -215,20 +217,20 @@ def calculate_adjusted_var(
|
||||
|
||||
def get_var(
|
||||
data: pd.DataFrame,
|
||||
use_mean: bool,
|
||||
adjusted_var: bool,
|
||||
student_t: bool,
|
||||
percentile: Union[int, float],
|
||||
portfolio: bool,
|
||||
use_mean: bool = False,
|
||||
adjusted_var: bool = False,
|
||||
student_t: bool = False,
|
||||
percentile: Union[int, float] = 0.999,
|
||||
portfolio: bool = False,
|
||||
):
|
||||
"""Gets value at risk for specified stock dataframe
|
||||
|
||||
Parameters
|
||||
----------
|
||||
data: pd.DataFrame
|
||||
Dataframe of a stock/portfolio
|
||||
Data dataframe
|
||||
use_mean: bool
|
||||
If one should use the stocks mean for calculation
|
||||
If one should use the data mean for calculation
|
||||
adjusted_var: bool
|
||||
If one should return VaR adjusted for skew and kurtosis
|
||||
student_t: bool
|
||||
@@ -323,19 +325,19 @@ def get_var(
|
||||
|
||||
def get_es(
|
||||
data: pd.DataFrame,
|
||||
use_mean: bool,
|
||||
distribution: str,
|
||||
percentile: Union[float, int],
|
||||
portfolio: bool,
|
||||
use_mean: bool = False,
|
||||
distribution: str = "normal",
|
||||
percentile: Union[float, int] = 0.999,
|
||||
portfolio: bool = False,
|
||||
) -> Tuple[List[float], List[float]]:
|
||||
"""Gets Expected Shortfall for specified stock dataframe
|
||||
|
||||
Parameters
|
||||
----------
|
||||
data: pd.DataFrame
|
||||
Dataframe of a stock
|
||||
Data dataframe
|
||||
use_mean: bool
|
||||
If one should use the stocks mean for calculation
|
||||
If one should use the data mean for calculation
|
||||
distribution: str
|
||||
Type of distribution, options: laplace, student_t, normal
|
||||
percentile: Union[float,int]
|
||||
|
||||
@@ -51,17 +51,17 @@ def lambda_color_red(val: Any) -> str:
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_summary(df: pd.DataFrame, export: str):
|
||||
def display_summary(data: pd.DataFrame, export: str = ""):
|
||||
"""Show summary statistics
|
||||
|
||||
Parameters
|
||||
----------
|
||||
df : pd.DataFrame
|
||||
data : pd.DataFrame
|
||||
DataFrame to get statistics of
|
||||
export : str
|
||||
Format to export data
|
||||
"""
|
||||
summary = qa_model.get_summary(df)
|
||||
summary = qa_model.get_summary(data)
|
||||
|
||||
print_rich_table(
|
||||
summary,
|
||||
@@ -82,9 +82,9 @@ def display_summary(df: pd.DataFrame, export: str):
|
||||
@log_start_end(log=logger)
|
||||
def display_hist(
|
||||
name: str,
|
||||
df: pd.DataFrame,
|
||||
data: pd.DataFrame,
|
||||
target: str,
|
||||
bins: int,
|
||||
bins: int = 15,
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
"""Generate of histogram of data
|
||||
@@ -93,7 +93,7 @@ def display_hist(
|
||||
----------
|
||||
name : str
|
||||
Name of dataset
|
||||
df : pd.DataFrame
|
||||
data : pd.DataFrame
|
||||
Dataframe to look at
|
||||
target : str
|
||||
Data column to get histogram of the dataframe
|
||||
@@ -102,7 +102,7 @@ def display_hist(
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
External axes (1 axis is expected in the list), by default None
|
||||
"""
|
||||
data = df[target]
|
||||
data = data[target]
|
||||
|
||||
# This plot has 1 axis
|
||||
if external_axes is None:
|
||||
@@ -126,8 +126,8 @@ def display_hist(
|
||||
)
|
||||
sns.rugplot(data, color=theme.down_color, ax=ax, legend=True)
|
||||
|
||||
if isinstance(df.index[0], datetime):
|
||||
start = df.index[0]
|
||||
if isinstance(data.index[0], datetime):
|
||||
start = data.index[0]
|
||||
ax.set_title(f"Histogram of {name} {target} from {start.strftime('%Y-%m-%d')}")
|
||||
else:
|
||||
ax.set_title(f"Histogram of {name} {target}")
|
||||
@@ -150,9 +150,9 @@ def display_hist(
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_cdf(
|
||||
name: str,
|
||||
df: pd.DataFrame,
|
||||
data: pd.DataFrame,
|
||||
target: str,
|
||||
symbol: str = "",
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
@@ -160,19 +160,19 @@ def display_cdf(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
name : str
|
||||
Name of dataset
|
||||
df : pd.DataFrame
|
||||
data : pd.DataFrame
|
||||
Dataframe to look at
|
||||
target : str
|
||||
Data column
|
||||
symbol : str
|
||||
Name of dataset
|
||||
export : str
|
||||
Format to export data
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
External axes (1 axis is expected in the list), by default None
|
||||
"""
|
||||
data = df[target]
|
||||
start = df.index[0]
|
||||
data = data[target]
|
||||
start = data.index[0]
|
||||
cdf = data.value_counts().sort_index().div(len(data)).cumsum()
|
||||
|
||||
# This plot has 1 axis
|
||||
@@ -188,7 +188,7 @@ def display_cdf(
|
||||
|
||||
cdf.plot(ax=ax)
|
||||
ax.set_title(
|
||||
f"Cumulative Distribution Function of {name} {target}\nfrom {start.strftime('%Y-%m-%d')}"
|
||||
f"Cumulative Distribution Function of {symbol} {target}\nfrom {start.strftime('%Y-%m-%d')}"
|
||||
)
|
||||
ax.set_ylabel("Probability")
|
||||
ax.set_xlabel(target)
|
||||
@@ -255,10 +255,10 @@ def display_cdf(
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_bw(
|
||||
name: str,
|
||||
df: pd.DataFrame,
|
||||
data: pd.DataFrame,
|
||||
target: str,
|
||||
yearly: bool,
|
||||
symbol: str = "",
|
||||
yearly: bool = True,
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
"""Show box and whisker plots
|
||||
@@ -267,17 +267,19 @@ def display_bw(
|
||||
----------
|
||||
name : str
|
||||
Name of dataset
|
||||
df : pd.DataFrame
|
||||
data : pd.DataFrame
|
||||
Dataframe to look at
|
||||
target : str
|
||||
Data column to look at
|
||||
symbol : str
|
||||
Name of dataset
|
||||
yearly : bool
|
||||
Flag to indicate yearly accumulation
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
External axes (1 axis is expected in the list), by default None
|
||||
"""
|
||||
data = df[target]
|
||||
start = df.index[0]
|
||||
data = data[target]
|
||||
start = data.index[0]
|
||||
|
||||
# This plot has 1 axis
|
||||
if external_axes is None:
|
||||
@@ -315,7 +317,7 @@ def display_bw(
|
||||
box_plot.set(
|
||||
xlabel=["Monthly", "Yearly"][yearly],
|
||||
ylabel=target,
|
||||
title=f"{['Monthly','Yearly'][yearly]} box plot of {name} {target} from {start.strftime('%Y-%m-%d')}",
|
||||
title=f"{['Monthly','Yearly'][yearly]} box plot of {symbol} {target} from {start.strftime('%Y-%m-%d')}",
|
||||
)
|
||||
l_months = [
|
||||
"Jan",
|
||||
@@ -351,10 +353,10 @@ def display_bw(
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_acf(
|
||||
name: str,
|
||||
df: pd.DataFrame,
|
||||
data: pd.DataFrame,
|
||||
target: str,
|
||||
lags: int,
|
||||
symbol: str = "",
|
||||
lags: int = 15,
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
"""Show Auto and Partial Auto Correlation of returns and change in returns
|
||||
@@ -363,17 +365,19 @@ def display_acf(
|
||||
----------
|
||||
name : str
|
||||
Name of dataset
|
||||
df : pd.DataFrame
|
||||
data : pd.DataFrame
|
||||
Dataframe to look at
|
||||
target : str
|
||||
Data column to look at
|
||||
symbol : str
|
||||
Name of dataset
|
||||
lags : int
|
||||
Max number of lags to look at
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
External axes (4 axes are expected in the list), by default None
|
||||
"""
|
||||
df = df[target]
|
||||
start = df.index[0]
|
||||
data = data[target]
|
||||
start = data.index[0]
|
||||
|
||||
# This plot has 4 axes
|
||||
if external_axes is None:
|
||||
@@ -389,26 +393,26 @@ def display_acf(
|
||||
else:
|
||||
return
|
||||
|
||||
# Diff Auto-correlation function for original time series
|
||||
sm.graphics.tsa.plot_acf(np.diff(np.diff(df.values)), lags=lags, ax=ax1)
|
||||
ax1.set_title(f"{name} Returns Auto-Correlation", fontsize=9)
|
||||
# Diff Partial auto-correlation function for original time series
|
||||
sm.graphics.tsa.plot_pacf(np.diff(np.diff(df.values)), lags=lags, ax=ax2)
|
||||
# Diff Auto - correlation function for original time series
|
||||
sm.graphics.tsa.plot_acf(np.diff(np.diff(data.values)), lags=lags, ax=ax1)
|
||||
ax1.set_title(f"{symbol} Returns Auto-Correlation", fontsize=9)
|
||||
# Diff Partial auto - correlation function for original time series
|
||||
sm.graphics.tsa.plot_pacf(np.diff(np.diff(data.values)), lags=lags, ax=ax2)
|
||||
ax2.set_title(
|
||||
f"{name} Returns Partial Auto-Correlation",
|
||||
f"{symbol} Returns Partial Auto-Correlation",
|
||||
fontsize=9,
|
||||
)
|
||||
|
||||
# Diff Diff Auto-correlation function for original time series
|
||||
sm.graphics.tsa.plot_acf(np.diff(np.diff(df.values)), lags=lags, ax=ax3)
|
||||
sm.graphics.tsa.plot_acf(np.diff(np.diff(data.values)), lags=lags, ax=ax3)
|
||||
ax3.set_title(
|
||||
f"Change in {name} Returns Auto-Correlation",
|
||||
f"Change in {symbol} Returns Auto-Correlation",
|
||||
fontsize=9,
|
||||
)
|
||||
# Diff Diff Partial auto-correlation function for original time series
|
||||
sm.graphics.tsa.plot_pacf(np.diff(np.diff(df.values)), lags=lags, ax=ax4)
|
||||
sm.graphics.tsa.plot_pacf(np.diff(np.diff(data.values)), lags=lags, ax=ax4)
|
||||
ax4.set_title(
|
||||
f"Change in {name} Returns Partial Auto-Correlation",
|
||||
f"Change in {symbol} Returns Partial Auto-Correlation",
|
||||
fontsize=9,
|
||||
)
|
||||
|
||||
@@ -431,9 +435,9 @@ def display_acf(
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_qqplot(
|
||||
name: str,
|
||||
df: pd.DataFrame,
|
||||
data: pd.DataFrame,
|
||||
target: str,
|
||||
symbol: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
"""Show QQ plot for data against normal quantiles
|
||||
@@ -442,16 +446,18 @@ def display_qqplot(
|
||||
----------
|
||||
name : str
|
||||
Stock ticker
|
||||
df : pd.DataFrame
|
||||
data : pd.DataFrame
|
||||
Dataframe
|
||||
target : str
|
||||
Column in data to look at
|
||||
name : str
|
||||
Stock ticker
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
External axes (1 axis is expected in the list), by default None
|
||||
"""
|
||||
# Statsmodels has a UserWarning for marker kwarg-- which we don't use
|
||||
warnings.filterwarnings(category=UserWarning, action="ignore")
|
||||
data = df[target]
|
||||
data = data[target]
|
||||
|
||||
# This plot has 1 axis
|
||||
if external_axes is None:
|
||||
@@ -474,7 +480,7 @@ def display_qqplot(
|
||||
)
|
||||
ax.get_lines()[1].set_color(theme.up_color)
|
||||
|
||||
ax.set_title(f"Q-Q plot for {name} {target}")
|
||||
ax.set_title(f"Q-Q plot for {symbol} {target}")
|
||||
ax.set_ylabel("Sample quantiles")
|
||||
ax.set_xlabel("Theoretical quantiles")
|
||||
|
||||
@@ -486,17 +492,17 @@ def display_qqplot(
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_cusum(
|
||||
df: pd.DataFrame,
|
||||
data: pd.DataFrame,
|
||||
target: str,
|
||||
threshold: float,
|
||||
drift: float,
|
||||
threshold: float = 5,
|
||||
drift: float = 2.1,
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
"""Cumulative sum algorithm (CUSUM) to detect abrupt changes in data
|
||||
|
||||
Parameters
|
||||
----------
|
||||
df : pd.DataFrame
|
||||
data : pd.DataFrame
|
||||
Dataframe
|
||||
target : str
|
||||
Column of data to look at
|
||||
@@ -507,11 +513,11 @@ def display_cusum(
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
External axes (2 axes are expected in the list), by default None
|
||||
"""
|
||||
target_series = df[target].values
|
||||
target_series = data[target].values
|
||||
|
||||
# The code for this plot was adapted from detecta's sources because at the
|
||||
# time of writing this detect_cusum had a bug related to external axes support.
|
||||
# see https://github.com/demotu/detecta/pull/3
|
||||
# see https: // github.com/demotu/detecta/pull/3
|
||||
tap, tan = 0, 0
|
||||
ta, tai, taf, _ = detect_cusum(
|
||||
x=target_series,
|
||||
@@ -549,7 +555,7 @@ def display_cusum(
|
||||
else:
|
||||
return
|
||||
|
||||
target_series_indexes = range(df[target].size)
|
||||
target_series_indexes = range(data[target].size)
|
||||
ax1.plot(target_series_indexes, target_series)
|
||||
if len(ta):
|
||||
ax1.plot(
|
||||
@@ -615,7 +621,7 @@ def display_cusum(
|
||||
@log_start_end(log=logger)
|
||||
def display_seasonal(
|
||||
name: str,
|
||||
df: pd.DataFrame,
|
||||
data: pd.DataFrame,
|
||||
target: str,
|
||||
multiplicative: bool = False,
|
||||
export: str = "",
|
||||
@@ -627,18 +633,18 @@ def display_seasonal(
|
||||
----------
|
||||
name : str
|
||||
Name of dataset
|
||||
df : pd.DataFrame
|
||||
data : pd.DataFrame
|
||||
DataFrame
|
||||
target : str
|
||||
Column of data to look at
|
||||
multiplicative : bool
|
||||
Boolean to indicate multiplication instead of addition
|
||||
export : str
|
||||
Format to export trend and cycle df
|
||||
Format to export trend and cycle data
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
External axes (6 axes are expected in the list), by default None
|
||||
"""
|
||||
data = df[target]
|
||||
data = data[target]
|
||||
result, cycle, trend = qa_model.get_seasonal_decomposition(data, multiplicative)
|
||||
|
||||
plot_data = pd.merge(
|
||||
@@ -740,7 +746,7 @@ def display_seasonal(
|
||||
)
|
||||
theme.visualize_output(force_tight_layout=False)
|
||||
|
||||
# From # https://otexts.com/fpp2/seasonal-strength.html
|
||||
# From #https: // otexts.com/fpp2/seasonal-strength.html
|
||||
console.print("Time-Series Level is " + str(round(data.mean(), 2)))
|
||||
|
||||
Ft = max(0, 1 - np.var(result.resid)) / np.var(result.trend + result.resid)
|
||||
@@ -761,19 +767,19 @@ def display_seasonal(
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_normality(df: pd.DataFrame, target: str, export: str = ""):
|
||||
def display_normality(data: pd.DataFrame, target: str, export: str = ""):
|
||||
"""View normality statistics
|
||||
|
||||
Parameters
|
||||
----------
|
||||
df : pd.DataFrame
|
||||
data : pd.DataFrame
|
||||
DataFrame
|
||||
target : str
|
||||
Column in data to look at
|
||||
export : str
|
||||
Format to export data
|
||||
"""
|
||||
data = df[target]
|
||||
data = data[target]
|
||||
normal = qa_model.get_normality(data)
|
||||
stats1 = normal.copy().T
|
||||
stats1.iloc[:, 1] = stats1.iloc[:, 1].apply(lambda x: lambda_color_red(x))
|
||||
@@ -796,25 +802,29 @@ def display_normality(df: pd.DataFrame, target: str, export: str = ""):
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_unitroot(
|
||||
df: pd.DataFrame, target: str, fuller_reg: str, kpss_reg: str, export: str = ""
|
||||
data: pd.DataFrame,
|
||||
target: str,
|
||||
fuller_reg: str = "c",
|
||||
kpss_reg: str = "c",
|
||||
export: str = "",
|
||||
):
|
||||
"""Show unit root test calculations
|
||||
|
||||
Parameters
|
||||
----------
|
||||
df : pd.DataFrame
|
||||
data : pd.DataFrame
|
||||
DataFrame
|
||||
target : str
|
||||
Column of data to look at
|
||||
fuller_reg : str
|
||||
Type of regression of ADF test
|
||||
Type of regression of ADF test. Can be ‘c’,’ct’,’ctt’,’nc’ 'c' - Constant and t - trend order
|
||||
kpss_reg : str
|
||||
Type of regression for KPSS test
|
||||
Type of regression for KPSS test. Can be ‘c’,’ct'
|
||||
export : str
|
||||
Format for exporting data
|
||||
"""
|
||||
df = df[target]
|
||||
data = qa_model.get_unitroot(df, fuller_reg, kpss_reg)
|
||||
data = data[target]
|
||||
data = qa_model.get_unitroot(data, fuller_reg, kpss_reg)
|
||||
print_rich_table(
|
||||
data,
|
||||
show_index=True,
|
||||
@@ -833,19 +843,23 @@ def display_unitroot(
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_raw(
|
||||
df: pd.DataFrame, sort: str = "", des: bool = False, num: int = 20, export: str = ""
|
||||
data: pd.DataFrame,
|
||||
sortby: str = "",
|
||||
descend: bool = False,
|
||||
limit: int = 20,
|
||||
export: str = "",
|
||||
) -> None:
|
||||
"""Return raw stock data
|
||||
|
||||
Parameters
|
||||
----------
|
||||
df : DataFrame
|
||||
data : DataFrame
|
||||
DataFrame with historical information
|
||||
sort : str
|
||||
sortby : str
|
||||
The column to sort by
|
||||
des : bool
|
||||
descend : bool
|
||||
Whether to sort descending
|
||||
num : int
|
||||
limit : int
|
||||
Number of rows to show
|
||||
export : str
|
||||
Export data as CSV, JSON, XLSX
|
||||
@@ -855,22 +869,22 @@ def display_raw(
|
||||
export,
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"history",
|
||||
df,
|
||||
data,
|
||||
)
|
||||
|
||||
if isinstance(df, pd.Series):
|
||||
df1 = pd.DataFrame(df)
|
||||
if isinstance(data, pd.Series):
|
||||
df1 = pd.DataFrame(data)
|
||||
else:
|
||||
df1 = df.copy()
|
||||
df1 = data.copy()
|
||||
|
||||
if sort:
|
||||
df1 = df.sort_values(
|
||||
by=sort if sort != "AdjClose" else "Adj Close", ascending=des
|
||||
if sortby:
|
||||
df1 = data.sort_values(
|
||||
by=sortby if sortby != "AdjClose" else "Adj Close", ascending=descend
|
||||
)
|
||||
df1.index = [x.strftime("%Y-%m-%d") for x in df1.index]
|
||||
|
||||
print_rich_table(
|
||||
df1.head(num) if sort else df1.tail(num),
|
||||
df1.head(limit) if sortby else df1.tail(limit),
|
||||
headers=[x.title() if x != "" else "Date" for x in df1.columns],
|
||||
title="[bold]Raw Data[/bold]",
|
||||
show_index=True,
|
||||
@@ -990,7 +1004,7 @@ def display_line(
|
||||
|
||||
def display_var(
|
||||
data: pd.DataFrame,
|
||||
ticker: str = "",
|
||||
name: str = "",
|
||||
use_mean: bool = False,
|
||||
adjusted_var: bool = False,
|
||||
student_t: bool = False,
|
||||
@@ -1003,11 +1017,11 @@ def display_var(
|
||||
Parameters
|
||||
----------
|
||||
data: pd.Dataframe
|
||||
stock dataframe
|
||||
Data dataframe
|
||||
use_mean: bool
|
||||
if one should use the stocks mean return
|
||||
ticker: str
|
||||
ticker of the stock
|
||||
if one should use the data mean return
|
||||
name: str
|
||||
name of the data
|
||||
adjusted_var: bool
|
||||
if one should have VaR adjusted for skew and kurtosis (Cornish-Fisher-Expansion)
|
||||
student_t: bool
|
||||
@@ -1041,8 +1055,8 @@ def display_var(
|
||||
str_var_label = "VaR:"
|
||||
str_title = ""
|
||||
|
||||
if ticker != "":
|
||||
ticker += " "
|
||||
if name != "":
|
||||
name += " "
|
||||
|
||||
data_dictionary = {str_var_label: var_list, str_hist_label: hist_var_list}
|
||||
data = pd.DataFrame(
|
||||
@@ -1053,14 +1067,14 @@ def display_var(
|
||||
data,
|
||||
show_index=True,
|
||||
headers=list(data.columns),
|
||||
title=f"[bold]{ticker}{str_title}Value at Risk[/bold]",
|
||||
title=f"[bold]{name}{str_title}Value at Risk[/bold]",
|
||||
floatfmt=".4f",
|
||||
)
|
||||
|
||||
|
||||
def display_es(
|
||||
data: pd.DataFrame,
|
||||
ticker: str = "",
|
||||
name: str = "",
|
||||
use_mean: bool = False,
|
||||
distribution: str = "normal",
|
||||
percentile: float = 0.999,
|
||||
@@ -1071,11 +1085,11 @@ def display_es(
|
||||
Parameters
|
||||
----------
|
||||
data: pd.DataFrame
|
||||
stock dataframe
|
||||
Data dataframe
|
||||
use_mean:
|
||||
if one should use the stocks mean return
|
||||
ticker: str
|
||||
ticker of the stock
|
||||
if one should use the data mean return
|
||||
name: str
|
||||
name of the data
|
||||
distribution: str
|
||||
choose distribution to use: logistic, laplace, normal
|
||||
percentile: int
|
||||
@@ -1102,8 +1116,8 @@ def display_es(
|
||||
str_es_label = "ES:"
|
||||
str_title = ""
|
||||
|
||||
if ticker != "":
|
||||
ticker += " "
|
||||
if name != "":
|
||||
name += " "
|
||||
|
||||
data_dictionary = {str_es_label: es_list, str_hist_label: hist_es_list}
|
||||
data = pd.DataFrame(
|
||||
@@ -1114,12 +1128,12 @@ def display_es(
|
||||
data,
|
||||
show_index=True,
|
||||
headers=list(data.columns),
|
||||
title=f"[bold]{ticker}{str_title}Expected Shortfall[/bold]",
|
||||
title=f"[bold]{name}{str_title}Expected Shortfall[/bold]",
|
||||
floatfmt=".4f",
|
||||
)
|
||||
|
||||
|
||||
def display_sharpe(data: pd.DataFrame, rfr: float, window: float):
|
||||
def display_sharpe(data: pd.DataFrame, rfr: float = 0, window: float = 252):
|
||||
"""Calculates the sharpe ratio
|
||||
Parameters
|
||||
----------
|
||||
|
||||
@@ -13,52 +13,58 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_rolling_avg(df: pd.DataFrame, length: int) -> Tuple[pd.DataFrame, pd.DataFrame]:
|
||||
def get_rolling_avg(
|
||||
data: pd.DataFrame, window: int = 14
|
||||
) -> Tuple[pd.DataFrame, pd.DataFrame]:
|
||||
"""Return rolling mean and standard deviation
|
||||
|
||||
Parameters
|
||||
----------
|
||||
df_stock : pd.DataFrame
|
||||
data: pd.DataFrame
|
||||
Dataframe of target data
|
||||
length : int
|
||||
window: int
|
||||
Length of rolling window
|
||||
|
||||
Returns
|
||||
-------
|
||||
pd.DataFrame :
|
||||
pd.DataFrame:
|
||||
Dataframe of rolling mean
|
||||
pd.DataFrame :
|
||||
pd.DataFrame:
|
||||
Dataframe of rolling standard deviation
|
||||
"""
|
||||
rolling_mean = df.rolling(length, center=True, min_periods=1).mean()
|
||||
rolling_std = df.rolling(length, center=True, min_periods=1).std()
|
||||
rolling_mean = data.rolling(window, center=True, min_periods=1).mean()
|
||||
rolling_std = data.rolling(window, center=True, min_periods=1).std()
|
||||
|
||||
return pd.DataFrame(rolling_mean), pd.DataFrame(rolling_std)
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_spread(df: pd.DataFrame, length: int) -> Tuple[pd.DataFrame, pd.DataFrame]:
|
||||
def get_spread(
|
||||
data: pd.DataFrame, window: int = 14
|
||||
) -> Tuple[pd.DataFrame, pd.DataFrame]:
|
||||
"""Standard Deviation and Variance
|
||||
|
||||
Parameters
|
||||
----------
|
||||
df_stock : pd.DataFrame
|
||||
data: pd.DataFrame
|
||||
DataFrame of targeted data
|
||||
window: int
|
||||
Length of window
|
||||
|
||||
Returns
|
||||
-------
|
||||
df_sd : pd.DataFrame
|
||||
df_sd: pd.DataFrame
|
||||
Dataframe of rolling standard deviation
|
||||
df_var : pd.DataFrame
|
||||
df_var: pd.DataFrame
|
||||
Dataframe of rolling standard deviation
|
||||
"""
|
||||
df_sd = ta.stdev(
|
||||
close=df,
|
||||
length=length,
|
||||
close=data,
|
||||
length=window,
|
||||
).dropna()
|
||||
df_var = ta.variance(
|
||||
close=df,
|
||||
length=length,
|
||||
close=data,
|
||||
length=window,
|
||||
).dropna()
|
||||
|
||||
return pd.DataFrame(df_sd), pd.DataFrame(df_var)
|
||||
@@ -66,17 +72,17 @@ def get_spread(df: pd.DataFrame, length: int) -> Tuple[pd.DataFrame, pd.DataFram
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_quantile(
|
||||
df: pd.DataFrame, length: int, quantile_pct: float
|
||||
data: pd.DataFrame, limit: int = 14, quantile_pct: float = 0.5
|
||||
) -> Tuple[pd.DataFrame, pd.DataFrame]:
|
||||
"""Overlay Median & Quantile
|
||||
|
||||
Parameters
|
||||
----------
|
||||
df : pd.DataFrame
|
||||
data: pd.DataFrame
|
||||
Dataframe of targeted data
|
||||
length : int
|
||||
limit : int
|
||||
Length of window
|
||||
quantile : float
|
||||
quantile_pct: float
|
||||
Quantile to display
|
||||
|
||||
Returns
|
||||
@@ -86,10 +92,10 @@ def get_quantile(
|
||||
df_quantile : pd.DataFrame
|
||||
Dataframe of gievn quantile prices over window
|
||||
"""
|
||||
df_med = ta.median(close=df, length=length).dropna()
|
||||
df_med = ta.median(close=data, length=limit).dropna()
|
||||
df_quantile = ta.quantile(
|
||||
df,
|
||||
length=length,
|
||||
data,
|
||||
length=limit,
|
||||
q=quantile_pct,
|
||||
).dropna()
|
||||
|
||||
@@ -97,34 +103,34 @@ def get_quantile(
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_skew(df: pd.DataFrame, length: int) -> pd.DataFrame:
|
||||
def get_skew(data: pd.DataFrame, window: int = 14) -> pd.DataFrame:
|
||||
"""Skewness Indicator
|
||||
|
||||
Parameters
|
||||
----------
|
||||
df_stock : pd.DataFrame
|
||||
data: pd.DataFrame
|
||||
Dataframe of targeted data
|
||||
length : int
|
||||
window : int
|
||||
Length of window
|
||||
|
||||
Returns
|
||||
-------
|
||||
df_skew : pd.DataFrame
|
||||
data_skew : pd.DataFrame
|
||||
Dataframe of rolling skew
|
||||
"""
|
||||
df_skew = ta.skew(close=df, length=length).dropna()
|
||||
df_skew = ta.skew(close=data, length=window).dropna()
|
||||
return df_skew
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_kurtosis(df: pd.DataFrame, length: int) -> pd.DataFrame:
|
||||
def get_kurtosis(data: pd.DataFrame, window: int = 14) -> pd.DataFrame:
|
||||
"""Kurtosis Indicator
|
||||
|
||||
Parameters
|
||||
----------
|
||||
df_stock : pd.DataFrame
|
||||
data: pd.DataFrame
|
||||
Dataframe of targeted data
|
||||
length : int
|
||||
window: int
|
||||
Length of window
|
||||
|
||||
Returns
|
||||
@@ -132,5 +138,5 @@ def get_kurtosis(df: pd.DataFrame, length: int) -> pd.DataFrame:
|
||||
df_kurt : pd.DataFrame
|
||||
Dataframe of rolling kurtosis
|
||||
"""
|
||||
df_kurt = ta.kurtosis(close=df, length=length).dropna()
|
||||
df_kurt = ta.kurtosis(close=data, length=window).dropna()
|
||||
return df_kurt
|
||||
|
||||
@@ -25,10 +25,10 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_mean_std(
|
||||
name: str,
|
||||
df: pd.DataFrame,
|
||||
data: pd.DataFrame,
|
||||
target: str,
|
||||
window: int,
|
||||
symbol: str = "",
|
||||
limit: int = 14,
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
@@ -36,21 +36,21 @@ def display_mean_std(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
name : str
|
||||
Stock ticker
|
||||
df : pd.DataFrame
|
||||
data: pd.DataFrame
|
||||
Dataframe
|
||||
target : str
|
||||
target: str
|
||||
Column in data to look at
|
||||
window : int
|
||||
symbol : str
|
||||
Stock ticker
|
||||
limit : int
|
||||
Length of window
|
||||
export : str
|
||||
export: str
|
||||
Format to export data
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
external_axes: Optional[List[plt.Axes]], optional
|
||||
External axes (2 axes are expected in the list), by default None
|
||||
"""
|
||||
data = df[target]
|
||||
rolling_mean, rolling_std = rolling_model.get_rolling_avg(data, window)
|
||||
data = data[target]
|
||||
rolling_mean, rolling_std = rolling_model.get_rolling_avg(data, limit)
|
||||
plot_data = pd.merge(
|
||||
data,
|
||||
rolling_mean,
|
||||
@@ -87,7 +87,7 @@ def display_mean_std(
|
||||
ax1.plot(
|
||||
plot_data.index,
|
||||
plot_data[target].values,
|
||||
label=name,
|
||||
label=symbol,
|
||||
)
|
||||
ax1.plot(
|
||||
plot_data.index,
|
||||
@@ -97,7 +97,7 @@ def display_mean_std(
|
||||
"Values",
|
||||
)
|
||||
ax1.legend(["Real Values", "Rolling Mean"])
|
||||
ax1.set_title(f"Rolling mean and std (window {str(window)}) of {name} {target}")
|
||||
ax1.set_title(f"Rolling mean and std (window {str(limit)}) of {symbol} {target}")
|
||||
ax1.set_xlim([plot_data.index[0], plot_data.index[-1]])
|
||||
|
||||
ax2.plot(
|
||||
@@ -134,10 +134,10 @@ def display_mean_std(
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_spread(
|
||||
name: str,
|
||||
df: pd.DataFrame,
|
||||
data: pd.DataFrame,
|
||||
target: str,
|
||||
window: int,
|
||||
symbol: str = "",
|
||||
limit: int = 14,
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
@@ -145,21 +145,23 @@ def display_spread(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
name : str
|
||||
Stock ticker
|
||||
df : pd.DataFrame
|
||||
data: pd.DataFrame
|
||||
Dataframe
|
||||
target: str
|
||||
Column in data to look at
|
||||
window : int
|
||||
target: str
|
||||
Column in data to look at
|
||||
symbol : str
|
||||
Stock ticker
|
||||
limit : int
|
||||
Length of window
|
||||
export : str
|
||||
export: str
|
||||
Format to export data
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
external_axes: Optional[List[plt.Axes]], optional
|
||||
External axes (3 axes are expected in the list), by default None
|
||||
"""
|
||||
data = df[target]
|
||||
df_sd, df_var = rolling_model.get_spread(data, window)
|
||||
data = data[target]
|
||||
df_sd, df_var = rolling_model.get_spread(data, limit)
|
||||
|
||||
plot_data = pd.merge(
|
||||
data,
|
||||
@@ -197,18 +199,18 @@ def display_spread(
|
||||
ax1.plot(plot_data.index, plot_data[target].values)
|
||||
ax1.set_xlim(plot_data.index[0], plot_data.index[-1])
|
||||
ax1.set_ylabel("Value")
|
||||
ax1.set_title(f"Spread of {name} {target}")
|
||||
ax1.set_title(f"Spread of {symbol} {target}")
|
||||
|
||||
ax2.plot(
|
||||
plot_data[f"STDEV_{window}"].index,
|
||||
plot_data[f"STDEV_{window}"].values,
|
||||
plot_data[f"STDEV_{limit}"].index,
|
||||
plot_data[f"STDEV_{limit}"].values,
|
||||
label="Stdev",
|
||||
)
|
||||
ax2.set_ylabel("Stdev")
|
||||
|
||||
ax3.plot(
|
||||
plot_data[f"VAR_{window}"].index,
|
||||
plot_data[f"VAR_{window}"].values,
|
||||
plot_data[f"VAR_{limit}"].index,
|
||||
plot_data[f"VAR_{limit}"].values,
|
||||
label="Variance",
|
||||
)
|
||||
ax3.set_ylabel("Variance")
|
||||
@@ -242,11 +244,11 @@ def display_spread(
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_quantile(
|
||||
name: str,
|
||||
df: pd.DataFrame,
|
||||
data: pd.DataFrame,
|
||||
target: str,
|
||||
window: int,
|
||||
quantile: float,
|
||||
symbol: str = "",
|
||||
limit: int = 14,
|
||||
quantile: float = 0.5,
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
@@ -254,23 +256,23 @@ def display_quantile(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
name : str
|
||||
Stock ticker
|
||||
df : pd.DataFrame
|
||||
data: pd.DataFrame
|
||||
Dataframe
|
||||
target : str
|
||||
target: str
|
||||
Column in data to look at
|
||||
window : int
|
||||
symbol : str
|
||||
Stock ticker
|
||||
limit : int
|
||||
Length of window
|
||||
quantile : float
|
||||
quantile: float
|
||||
Quantile to get
|
||||
export : str
|
||||
export: str
|
||||
Format to export data
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
external_axes: Optional[List[plt.Axes]], optional
|
||||
External axes (1 axis is expected in the list), by default None
|
||||
"""
|
||||
data = df[target]
|
||||
df_med, df_quantile = rolling_model.get_quantile(data, window, quantile)
|
||||
data = data[target]
|
||||
df_med, df_quantile = rolling_model.get_quantile(data, limit, quantile)
|
||||
|
||||
plot_data = pd.merge(
|
||||
data,
|
||||
@@ -301,22 +303,22 @@ def display_quantile(
|
||||
else:
|
||||
return
|
||||
|
||||
ax.set_title(f"{name} {target} Median & Quantile")
|
||||
ax.set_title(f"{symbol} {target} Median & Quantile")
|
||||
ax.plot(plot_data.index, plot_data[target].values, label=target)
|
||||
ax.plot(
|
||||
plot_data.index,
|
||||
plot_data[f"MEDIAN_{window}"].values,
|
||||
label=f"Median w={window}",
|
||||
plot_data[f"MEDIAN_{limit}"].values,
|
||||
label=f"Median w={limit}",
|
||||
)
|
||||
ax.plot(
|
||||
plot_data.index,
|
||||
plot_data[f"QTL_{window}_{quantile}"].values,
|
||||
plot_data[f"QTL_{limit}_{quantile}"].values,
|
||||
label=f"Quantile q={quantile}",
|
||||
linestyle="--",
|
||||
)
|
||||
|
||||
ax.set_xlim(plot_data.index[0], plot_data.index[-1])
|
||||
ax.set_ylabel(f"{name} Value")
|
||||
ax.set_ylabel(f"{symbol} Value")
|
||||
ax.legend()
|
||||
|
||||
theme.style_primary_axis(
|
||||
@@ -339,9 +341,9 @@ def display_quantile(
|
||||
@log_start_end(log=logger)
|
||||
def display_skew(
|
||||
name: str,
|
||||
df: pd.DataFrame,
|
||||
data: pd.DataFrame,
|
||||
target: str,
|
||||
window: int,
|
||||
window: int = 14,
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
@@ -349,20 +351,20 @@ def display_skew(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
name : str
|
||||
name: str
|
||||
Stock ticker
|
||||
df : pd.DataFrame
|
||||
data: pd.DataFrame
|
||||
Dataframe
|
||||
target : str
|
||||
target: str
|
||||
Column in data to look at
|
||||
window : int
|
||||
window: int
|
||||
Length of window
|
||||
export : str
|
||||
export: str
|
||||
Format to export data
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
external_axes: Optional[List[plt.Axes]], optional
|
||||
External axes (2 axes are expected in the list), by default None
|
||||
"""
|
||||
data = df[target]
|
||||
data = data[target]
|
||||
df_skew = rolling_model.get_skew(data, window)
|
||||
|
||||
plot_data = pd.merge(
|
||||
@@ -423,9 +425,9 @@ def display_skew(
|
||||
@log_start_end(log=logger)
|
||||
def display_kurtosis(
|
||||
name: str,
|
||||
df: pd.DataFrame,
|
||||
data: pd.DataFrame,
|
||||
target: str,
|
||||
window: int,
|
||||
window: int = 14,
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
@@ -433,18 +435,20 @@ def display_kurtosis(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
name : str
|
||||
name: str
|
||||
Ticker
|
||||
df : pd.DataFrame
|
||||
data: pd.DataFrame
|
||||
Dataframe of stock prices
|
||||
window : int
|
||||
target: str
|
||||
Column in data to look at
|
||||
window: int
|
||||
Length of window
|
||||
export : str
|
||||
export: str
|
||||
Format to export data
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
external_axes: Optional[List[plt.Axes]], optional
|
||||
External axes (2 axes are expected in the list), by default None
|
||||
"""
|
||||
data = df[target]
|
||||
data = data[target]
|
||||
df_kurt = rolling_model.get_kurtosis(data, window)
|
||||
|
||||
plot_data = pd.merge(
|
||||
|
||||
@@ -14,7 +14,7 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def calculate_fib_levels(
|
||||
df_stock: pd.DataFrame,
|
||||
data: pd.DataFrame,
|
||||
period: int = 120,
|
||||
open_date: Any = None,
|
||||
close_date: Any = None,
|
||||
@@ -23,7 +23,7 @@ def calculate_fib_levels(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
df_stock : pd.DataFrame
|
||||
data : pd.DataFrame
|
||||
Dataframe of prices
|
||||
period : int
|
||||
Days to look back for retracement
|
||||
@@ -46,31 +46,31 @@ def calculate_fib_levels(
|
||||
Price at max point
|
||||
"""
|
||||
if open_date and close_date:
|
||||
if open_date not in df_stock.index:
|
||||
date0 = df_stock.index[df_stock.index.get_loc(open_date, method="nearest")]
|
||||
console.print(f"Start date not in df_stock. Using nearest: {date0}")
|
||||
if open_date not in data.index:
|
||||
date0 = data.index[data.index.get_loc(open_date, method="nearest")]
|
||||
console.print(f"Start date not in data. Using nearest: {date0}")
|
||||
else:
|
||||
date0 = open_date
|
||||
if close_date not in df_stock.index:
|
||||
date1 = df_stock.index[df_stock.index.get_loc(close_date, method="nearest")]
|
||||
console.print(f"End date not in df_stock. Using nearest: {date1}")
|
||||
if close_date not in data.index:
|
||||
date1 = data.index[data.index.get_loc(close_date, method="nearest")]
|
||||
console.print(f"End date not in data. Using nearest: {date1}")
|
||||
else:
|
||||
date1 = close_date
|
||||
|
||||
df_stock0 = df_stock.loc[date0, "Adj Close"]
|
||||
df_stock1 = df_stock.loc[date1, "Adj Close"]
|
||||
data0 = data.loc[date0, "Adj Close"]
|
||||
data1 = data.loc[date1, "Adj Close"]
|
||||
|
||||
min_pr = min(df_stock0, df_stock1)
|
||||
max_pr = max(df_stock0, df_stock1)
|
||||
min_pr = min(data0, data1)
|
||||
max_pr = max(data0, data1)
|
||||
|
||||
if min_pr == df_stock0:
|
||||
if min_pr == data0:
|
||||
min_date = date0
|
||||
max_date = date1
|
||||
else:
|
||||
min_date = date1
|
||||
max_date = date0
|
||||
else:
|
||||
data_to_use = df_stock.iloc[period:]["Adj Close"]
|
||||
data_to_use = data.iloc[period:]["Adj Close"]
|
||||
|
||||
min_pr = data_to_use.min()
|
||||
min_date = data_to_use.idxmin()
|
||||
|
||||
@@ -26,11 +26,11 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def fibonacci_retracement(
|
||||
ohlc: pd.DataFrame,
|
||||
data: pd.DataFrame,
|
||||
period: int = 120,
|
||||
start_date: Optional[Union[str, None]] = None,
|
||||
end_date: Optional[Union[str, None]] = None,
|
||||
s_ticker: str = "",
|
||||
symbol: str = "",
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
@@ -38,16 +38,16 @@ def fibonacci_retracement(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ohlc: pd.DataFrame
|
||||
Stock data
|
||||
data: pd.DataFrame
|
||||
OHLC data
|
||||
period: int
|
||||
Days to lookback
|
||||
start_date: Optional[str, None]
|
||||
User picked date for starting retracement
|
||||
end_date: Optional[str, None]
|
||||
User picked date for ending retracement
|
||||
s_ticker:str
|
||||
Stock ticker
|
||||
symbol: str
|
||||
Ticker symbol
|
||||
export: str
|
||||
Format to export data
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
@@ -59,11 +59,11 @@ def fibonacci_retracement(
|
||||
max_date,
|
||||
min_pr,
|
||||
max_pr,
|
||||
) = custom_indicators_model.calculate_fib_levels(ohlc, period, start_date, end_date)
|
||||
) = custom_indicators_model.calculate_fib_levels(data, period, start_date, end_date)
|
||||
|
||||
levels = df_fib.Price
|
||||
|
||||
plot_data = reindex_dates(ohlc)
|
||||
plot_data = reindex_dates(data)
|
||||
|
||||
# This plot has 2 axes
|
||||
if external_axes is None:
|
||||
@@ -79,7 +79,7 @@ def fibonacci_retracement(
|
||||
|
||||
ax1.plot(plot_data["Adj Close"])
|
||||
|
||||
if is_intraday(ohlc):
|
||||
if is_intraday(data):
|
||||
date_format = "%b %d %H:%M"
|
||||
else:
|
||||
date_format = "%Y-%m-%d"
|
||||
@@ -101,7 +101,7 @@ def fibonacci_retracement(
|
||||
ax1.fill_between(plot_data.index, levels[i], levels[i + 1], alpha=0.15)
|
||||
|
||||
ax1.set_xlim(plot_data.index[0], plot_data.index[-1])
|
||||
ax1.set_title(f"Fibonacci Support for {s_ticker.upper()}")
|
||||
ax1.set_title(f"Fibonacci Support for {symbol.upper()}")
|
||||
ax1.set_yticks(levels)
|
||||
ax1.set_yticklabels([0, 0.235, 0.382, 0.5, 0.618, 0.65, 1])
|
||||
theme.style_primary_axis(
|
||||
|
||||
@@ -20,7 +20,7 @@ def cci(
|
||||
high_vals: pd.Series,
|
||||
low_vals: pd.Series,
|
||||
close_vals: pd.Series,
|
||||
length: int = 14,
|
||||
window: int = 14,
|
||||
scalar: float = 0.0015,
|
||||
) -> pd.DataFrame:
|
||||
"""Commodity channel index
|
||||
@@ -33,7 +33,7 @@ def cci(
|
||||
Low values
|
||||
close-values: pd.Series
|
||||
Close values
|
||||
length: int
|
||||
window: int
|
||||
Length of window
|
||||
scalar: float
|
||||
Scalar variable
|
||||
@@ -48,7 +48,7 @@ def cci(
|
||||
high=high_vals,
|
||||
low=low_vals,
|
||||
close=close_vals,
|
||||
length=length,
|
||||
length=window,
|
||||
scalar=scalar,
|
||||
).dropna()
|
||||
)
|
||||
@@ -85,7 +85,7 @@ def macd(
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def rsi(
|
||||
values: pd.Series, length: int = 14, scalar: float = 100, drift: int = 1
|
||||
values: pd.Series, window: int = 14, scalar: float = 100, drift: int = 1
|
||||
) -> pd.DataFrame:
|
||||
"""Relative strength index
|
||||
|
||||
@@ -93,7 +93,7 @@ def rsi(
|
||||
----------
|
||||
values: pd.Series
|
||||
Dataframe of prices
|
||||
length: int
|
||||
window: int
|
||||
Length of window
|
||||
scalar: float
|
||||
Scalar variable
|
||||
@@ -106,7 +106,7 @@ def rsi(
|
||||
Dataframe of technical indicator
|
||||
"""
|
||||
return pd.DataFrame(
|
||||
ta.rsi(values, length=length, scalar=scalar, drift=drift).dropna()
|
||||
ta.rsi(values, length=window, scalar=scalar, drift=drift).dropna()
|
||||
)
|
||||
|
||||
|
||||
@@ -153,7 +153,7 @@ def stoch(
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def fisher(high_vals: pd.Series, low_vals: pd.Series, length: int = 14) -> pd.DataFrame:
|
||||
def fisher(high_vals: pd.Series, low_vals: pd.Series, window: int = 14) -> pd.DataFrame:
|
||||
"""Fisher Transform
|
||||
|
||||
Parameters
|
||||
@@ -162,7 +162,7 @@ def fisher(high_vals: pd.Series, low_vals: pd.Series, length: int = 14) -> pd.Da
|
||||
High values
|
||||
low_vals: pd.Series
|
||||
Low values
|
||||
length: int
|
||||
window: int
|
||||
Length for indicator window
|
||||
Returns
|
||||
----------
|
||||
@@ -170,39 +170,39 @@ def fisher(high_vals: pd.Series, low_vals: pd.Series, length: int = 14) -> pd.Da
|
||||
Dataframe of technical indicator
|
||||
"""
|
||||
# Daily
|
||||
return pd.DataFrame(ta.fisher(high=high_vals, low=low_vals, length=length).dropna())
|
||||
return pd.DataFrame(ta.fisher(high=high_vals, low=low_vals, length=window).dropna())
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def cg(values: pd.Series, length: int) -> pd.DataFrame:
|
||||
def cg(values: pd.Series, window: int) -> pd.DataFrame:
|
||||
"""Center of gravity
|
||||
|
||||
Parameters
|
||||
----------
|
||||
values: pd.DataFrame
|
||||
Data to use with close being titled values
|
||||
length: int
|
||||
window: int
|
||||
Length for indicator window
|
||||
Returns
|
||||
----------
|
||||
d.DataFrame
|
||||
Dataframe of technical indicator
|
||||
"""
|
||||
return pd.DataFrame(ta.cg(close=values, length=length).dropna())
|
||||
return pd.DataFrame(ta.cg(close=values, length=window).dropna())
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def clenow_momentum(
|
||||
values: pd.Series, length: int = 90
|
||||
values: pd.Series, window: int = 90
|
||||
) -> Tuple[float, float, pd.Series]:
|
||||
"""Gets the Clenow Volatility Adjusted Momentum. this is defined as the regression coefficient on log prices
|
||||
multiplied by the R^2 value of the regression
|
||||
|
||||
Parameters
|
||||
----------
|
||||
values:pd.Series
|
||||
values: pd.Series
|
||||
Values to perform regression for
|
||||
length: int
|
||||
window: int
|
||||
Length of lookback period
|
||||
|
||||
Returns
|
||||
@@ -214,13 +214,13 @@ def clenow_momentum(
|
||||
pd.Series:
|
||||
Values for best fit line
|
||||
"""
|
||||
if len(values) < length:
|
||||
if len(values) < window:
|
||||
console.print(
|
||||
f"[red]Calculation asks for at least last {length} days of data[/red]"
|
||||
f"[red]Calculation asks for at least last {window} days of data[/red]"
|
||||
)
|
||||
return np.nan, np.nan, pd.Series()
|
||||
|
||||
values = values[-length:]
|
||||
values = values[-window:]
|
||||
|
||||
y = np.log(values)
|
||||
X = np.arange(len(y)).reshape(-1, 1)
|
||||
|
||||
@@ -29,10 +29,10 @@ register_matplotlib_converters()
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_cci(
|
||||
ohlc: pd.DataFrame,
|
||||
length: int = 14,
|
||||
data: pd.DataFrame,
|
||||
window: int = 14,
|
||||
scalar: float = 0.0015,
|
||||
s_ticker: str = "",
|
||||
symbol: str = "",
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
@@ -41,13 +41,13 @@ def display_cci(
|
||||
Parameters
|
||||
----------
|
||||
|
||||
ohlc : pd.DataFrame
|
||||
data : pd.DataFrame
|
||||
Dataframe of OHLC
|
||||
length : int
|
||||
window : int
|
||||
Length of window
|
||||
scalar : float
|
||||
Scalar variable
|
||||
s_ticker : str
|
||||
symbol : str
|
||||
Stock ticker
|
||||
export : str
|
||||
Format to export data
|
||||
@@ -55,9 +55,9 @@ def display_cci(
|
||||
External axes (2 axes are expected in the list), by default None
|
||||
"""
|
||||
df_ta = momentum_model.cci(
|
||||
ohlc["High"], ohlc["Low"], ohlc["Adj Close"], length, scalar
|
||||
data["High"], data["Low"], data["Adj Close"], window, scalar
|
||||
)
|
||||
plot_data = pd.merge(ohlc, df_ta, how="outer", left_index=True, right_index=True)
|
||||
plot_data = pd.merge(data, df_ta, how="outer", left_index=True, right_index=True)
|
||||
plot_data = reindex_dates(plot_data)
|
||||
|
||||
# This plot has 2 axes
|
||||
@@ -71,7 +71,7 @@ def display_cci(
|
||||
else:
|
||||
return
|
||||
|
||||
ax1.set_title(f"{s_ticker} CCI")
|
||||
ax1.set_title(f"{symbol} CCI")
|
||||
ax1.plot(
|
||||
plot_data.index,
|
||||
plot_data["Adj Close"].values,
|
||||
@@ -123,7 +123,7 @@ def display_macd(
|
||||
n_fast: int = 12,
|
||||
n_slow: int = 26,
|
||||
n_signal: int = 9,
|
||||
s_ticker: str = "",
|
||||
symbol: str = "",
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
@@ -139,7 +139,7 @@ def display_macd(
|
||||
Slow period
|
||||
n_signal : int
|
||||
Signal period
|
||||
s_ticker : str
|
||||
symbol : str
|
||||
Stock ticker
|
||||
export : str
|
||||
Format to export data
|
||||
@@ -161,7 +161,7 @@ def display_macd(
|
||||
else:
|
||||
return
|
||||
|
||||
ax1.set_title(f"{s_ticker} MACD")
|
||||
ax1.set_title(f"{symbol} MACD")
|
||||
ax1.plot(plot_data.index, plot_data.iloc[:, 1].values)
|
||||
ax1.set_xlim(plot_data.index[0], plot_data.index[-1])
|
||||
ax1.set_ylabel("Share Price ($)")
|
||||
@@ -207,10 +207,10 @@ def display_macd(
|
||||
@log_start_end(log=logger)
|
||||
def display_rsi(
|
||||
series: pd.Series,
|
||||
length: int = 14,
|
||||
window: int = 14,
|
||||
scalar: float = 100.0,
|
||||
drift: int = 1,
|
||||
s_ticker: str = "",
|
||||
symbol: str = "",
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
@@ -220,20 +220,20 @@ def display_rsi(
|
||||
----------
|
||||
series : pd.Series
|
||||
Values to input
|
||||
length : int
|
||||
window : int
|
||||
Length of window
|
||||
scalar : float
|
||||
Scalar variable
|
||||
drift : int
|
||||
Drift variable
|
||||
s_ticker : str
|
||||
symbol : str
|
||||
Stock ticker
|
||||
export : str
|
||||
Format to export data
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
External axes (2 axes are expected in the list), by default None
|
||||
"""
|
||||
df_ta = momentum_model.rsi(series, length, scalar, drift)
|
||||
df_ta = momentum_model.rsi(series, window, scalar, drift)
|
||||
|
||||
# This plot has 2 axes
|
||||
if external_axes is None:
|
||||
@@ -250,7 +250,7 @@ def display_rsi(
|
||||
plot_data = reindex_dates(plot_data)
|
||||
|
||||
ax1.plot(plot_data.index, plot_data.iloc[:, 1].values)
|
||||
ax1.set_title(f"{s_ticker} RSI{length}")
|
||||
ax1.set_title(f"{symbol} RSI{window}")
|
||||
ax1.set_xlim(plot_data.index[0], plot_data.index[-1])
|
||||
ax1.set_ylabel("Share Price ($)")
|
||||
theme.style_primary_axis(
|
||||
@@ -291,11 +291,11 @@ def display_rsi(
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_stoch(
|
||||
ohlc: pd.DataFrame,
|
||||
data: pd.DataFrame,
|
||||
fastkperiod: int = 14,
|
||||
slowdperiod: int = 3,
|
||||
slowkperiod: int = 3,
|
||||
s_ticker: str = "",
|
||||
symbol: str = "",
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
) -> None:
|
||||
@@ -303,25 +303,25 @@ def display_stoch(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ohlc : pd.DataFrame
|
||||
Dataframe of prices
|
||||
data : pd.DataFrame
|
||||
Dataframe of OHLC prices
|
||||
fastkperiod : int
|
||||
Fast k period
|
||||
slowdperiod : int
|
||||
Slow d period
|
||||
slowkperiod : int
|
||||
Slow k period
|
||||
s_ticker : str
|
||||
Stock ticker
|
||||
symbol : str
|
||||
Stock ticker symbol
|
||||
export : str
|
||||
Format to export data
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
External axes (3 axes are expected in the list), by default None
|
||||
"""
|
||||
df_ta = momentum_model.stoch(
|
||||
ohlc["High"],
|
||||
ohlc["Low"],
|
||||
ohlc["Adj Close"],
|
||||
data["High"],
|
||||
data["Low"],
|
||||
data["Adj Close"],
|
||||
fastkperiod,
|
||||
slowdperiod,
|
||||
slowkperiod,
|
||||
@@ -338,12 +338,12 @@ def display_stoch(
|
||||
else:
|
||||
return
|
||||
|
||||
plot_data = pd.merge(ohlc, df_ta, how="outer", left_index=True, right_index=True)
|
||||
plot_data = pd.merge(data, df_ta, how="outer", left_index=True, right_index=True)
|
||||
plot_data = reindex_dates(plot_data)
|
||||
|
||||
ax1.plot(plot_data.index, plot_data["Adj Close"].values)
|
||||
|
||||
ax1.set_title(f"Stochastic Relative Strength Index (STOCH RSI) on {s_ticker}")
|
||||
ax1.set_title(f"Stochastic Relative Strength Index (STOCH RSI) on {symbol}")
|
||||
ax1.set_xlim(plot_data.index[0], plot_data.index[-1])
|
||||
ax1.set_ylabel("Share Price ($)")
|
||||
theme.style_primary_axis(
|
||||
@@ -385,9 +385,9 @@ def display_stoch(
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_fisher(
|
||||
ohlc: pd.DataFrame,
|
||||
length: int = 14,
|
||||
s_ticker: str = "",
|
||||
data: pd.DataFrame,
|
||||
window: int = 14,
|
||||
symbol: str = "",
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
@@ -395,19 +395,19 @@ def display_fisher(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ohlc : pd.DataFrame
|
||||
Dataframe of prices
|
||||
length : int
|
||||
data : pd.DataFrame
|
||||
Dataframe of OHLC prices
|
||||
window : int
|
||||
Length of window
|
||||
s_ticker : str
|
||||
symbol : str
|
||||
Ticker string
|
||||
export : str
|
||||
Format to export data
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
External axes (3 axes are expected in the list), by default None
|
||||
"""
|
||||
df_ta = momentum_model.fisher(ohlc["High"], ohlc["Low"], length)
|
||||
plot_data = pd.merge(ohlc, df_ta, how="outer", left_index=True, right_index=True)
|
||||
df_ta = momentum_model.fisher(data["High"], data["Low"], window)
|
||||
plot_data = pd.merge(data, df_ta, how="outer", left_index=True, right_index=True)
|
||||
plot_data = reindex_dates(plot_data)
|
||||
|
||||
# This plot has 3 axes
|
||||
@@ -422,7 +422,7 @@ def display_fisher(
|
||||
else:
|
||||
return
|
||||
|
||||
ax1.set_title(f"{s_ticker} Fisher Transform")
|
||||
ax1.set_title(f"{symbol} Fisher Transform")
|
||||
ax1.plot(plot_data.index, plot_data["Adj Close"].values)
|
||||
ax1.set_xlim(plot_data.index[0], plot_data.index[-1])
|
||||
ax1.set_ylabel("Price")
|
||||
@@ -474,8 +474,8 @@ def display_fisher(
|
||||
@log_start_end(log=logger)
|
||||
def display_cg(
|
||||
series: pd.Series,
|
||||
length: int = 14,
|
||||
s_ticker: str = "",
|
||||
window: int = 14,
|
||||
symbol: str = "",
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
@@ -485,16 +485,16 @@ def display_cg(
|
||||
----------
|
||||
series : pd.Series
|
||||
Series of values
|
||||
length : int
|
||||
window : int
|
||||
Length of window
|
||||
s_ticker : str
|
||||
symbol : str
|
||||
Stock ticker
|
||||
export : str
|
||||
Format to export data
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
External axes (2 axes are expected in the list), by default None
|
||||
"""
|
||||
df_ta = momentum_model.cg(series, length)
|
||||
df_ta = momentum_model.cg(series, window)
|
||||
plot_data = pd.merge(series, df_ta, how="outer", left_index=True, right_index=True)
|
||||
plot_data = reindex_dates(plot_data)
|
||||
|
||||
@@ -509,7 +509,7 @@ def display_cg(
|
||||
else:
|
||||
return
|
||||
|
||||
ax1.set_title(f"{s_ticker} Centre of Gravity")
|
||||
ax1.set_title(f"{symbol} Centre of Gravity")
|
||||
ax1.plot(plot_data.index, plot_data[series.name].values)
|
||||
ax1.set_xlim(plot_data.index[0], plot_data.index[-1])
|
||||
ax1.set_ylabel("Share Price ($)")
|
||||
@@ -545,23 +545,28 @@ def display_cg(
|
||||
@log_start_end(log=logger)
|
||||
def display_clenow_momentum(
|
||||
series: pd.Series,
|
||||
length: int = 90,
|
||||
window: int = 90,
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
"""
|
||||
"""Display clenow momentum
|
||||
|
||||
Parameters
|
||||
----------
|
||||
series
|
||||
length
|
||||
export
|
||||
series : pd.Series
|
||||
Series of values
|
||||
window : int
|
||||
Length of window
|
||||
export : str
|
||||
Format to export data
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
External axes (2 axes are expected in the list), by default None
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
||||
"""
|
||||
r2, coef, fit_data = momentum_model.clenow_momentum(series, length)
|
||||
r2, coef, fit_data = momentum_model.clenow_momentum(series, window)
|
||||
|
||||
df = pd.DataFrame.from_dict(
|
||||
{
|
||||
@@ -589,7 +594,7 @@ def display_clenow_momentum(
|
||||
return
|
||||
|
||||
ax1.plot(series.index, np.log(series.values))
|
||||
ax1.plot(series.index[-length:], fit_data, linewidth=2)
|
||||
ax1.plot(series.index[-window:], fit_data, linewidth=2)
|
||||
|
||||
ax1.set_title("Clenow Momentum Exponential Regression")
|
||||
ax1.set_xlim(series.index[0], series.index[-1])
|
||||
|
||||
@@ -15,12 +15,12 @@ WINDOW_LENGTHS2 = [10, 20]
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def ema(values: pd.DataFrame, length: int, offset: int) -> pd.DataFrame:
|
||||
def ema(data: pd.DataFrame, length: int, offset: int = 0) -> pd.DataFrame:
|
||||
"""Gets exponential moving average (EMA) for stock
|
||||
|
||||
Parameters
|
||||
----------
|
||||
values: pd.DataFrame
|
||||
data: pd.DataFrame
|
||||
Dataframe of dates and prices
|
||||
length: int
|
||||
Length of EMA window
|
||||
@@ -32,16 +32,16 @@ def ema(values: pd.DataFrame, length: int, offset: int) -> pd.DataFrame:
|
||||
pd.DataFrame
|
||||
Dataframe containing prices and EMA
|
||||
"""
|
||||
return pd.DataFrame(ta.ema(values, length=length, offset=offset)).dropna()
|
||||
return pd.DataFrame(ta.ema(data, length=length, offset=offset)).dropna()
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def sma(values: pd.DataFrame, length: int, offset: int) -> pd.DataFrame:
|
||||
def sma(data: pd.DataFrame, length: int, offset: int = 0) -> pd.DataFrame:
|
||||
"""Gets simple moving average (EMA) for stock
|
||||
|
||||
Parameters
|
||||
----------
|
||||
values: pd.DataFrame
|
||||
data: pd.DataFrame
|
||||
Dataframe of dates and prices
|
||||
length: int
|
||||
Length of SMA window
|
||||
@@ -53,16 +53,16 @@ def sma(values: pd.DataFrame, length: int, offset: int) -> pd.DataFrame:
|
||||
pd.DataFrame
|
||||
Dataframe containing prices and SMA
|
||||
"""
|
||||
return pd.DataFrame(ta.sma(values, length=length, offset=offset)).dropna()
|
||||
return pd.DataFrame(ta.sma(data, length=length, offset=offset)).dropna()
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def wma(values: pd.DataFrame, length: int, offset: int) -> pd.DataFrame:
|
||||
def wma(data: pd.DataFrame, length: int, offset: int = 0) -> pd.DataFrame:
|
||||
"""Gets weighted moving average (WMA) for stock
|
||||
|
||||
Parameters
|
||||
----------
|
||||
values: pd.DataFrame
|
||||
data: pd.DataFrame
|
||||
Dataframe of dates and prices
|
||||
length: int
|
||||
Length of SMA window
|
||||
@@ -74,16 +74,16 @@ def wma(values: pd.DataFrame, length: int, offset: int) -> pd.DataFrame:
|
||||
df_ta: pd.DataFrame
|
||||
Dataframe containing prices and WMA
|
||||
"""
|
||||
return pd.DataFrame(ta.wma(values, length=length, offset=offset)).dropna()
|
||||
return pd.DataFrame(ta.wma(data, length=length, offset=offset)).dropna()
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def hma(values: pd.DataFrame, length: int, offset: int) -> pd.DataFrame:
|
||||
def hma(data: pd.DataFrame, length: int, offset: int = 0) -> pd.DataFrame:
|
||||
"""Gets hull moving average (HMA) for stock
|
||||
|
||||
Parameters
|
||||
----------
|
||||
values: pd.DataFrame
|
||||
data: pd.DataFrame
|
||||
Dataframe of dates and prices
|
||||
length: int
|
||||
Length of SMA window
|
||||
@@ -95,11 +95,11 @@ def hma(values: pd.DataFrame, length: int, offset: int) -> pd.DataFrame:
|
||||
df_ta: pd.DataFrame
|
||||
Dataframe containing prices and HMA
|
||||
"""
|
||||
return pd.DataFrame(ta.hma(values, length=length, offset=offset)).dropna()
|
||||
return pd.DataFrame(ta.hma(data, length=length, offset=offset)).dropna()
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def zlma(values: pd.DataFrame, length: int, offset: int) -> pd.DataFrame:
|
||||
def zlma(data: pd.DataFrame, length: int, offset: int = 0) -> pd.DataFrame:
|
||||
"""Gets zero-lagged exponential moving average (ZLEMA) for stock
|
||||
|
||||
Parameters
|
||||
@@ -116,16 +116,16 @@ def zlma(values: pd.DataFrame, length: int, offset: int) -> pd.DataFrame:
|
||||
df_ta: pd.DataFrame
|
||||
Dataframe containing prices and EMA
|
||||
"""
|
||||
return pd.DataFrame(ta.zlma(values, length=length, offset=offset)).dropna()
|
||||
return pd.DataFrame(ta.zlma(data, length=length, offset=offset)).dropna()
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def vwap(df: pd.DataFrame, offset: int) -> pd.DataFrame:
|
||||
def vwap(data: pd.DataFrame, offset: int = 0) -> pd.DataFrame:
|
||||
"""Gets volume weighted average price (VWAP)
|
||||
|
||||
Parameters
|
||||
----------
|
||||
df: pd.DataFrame
|
||||
data: pd.DataFrame
|
||||
Dataframe of dates and prices
|
||||
offset: int
|
||||
Length of offset
|
||||
@@ -136,10 +136,10 @@ def vwap(df: pd.DataFrame, offset: int) -> pd.DataFrame:
|
||||
"""
|
||||
|
||||
df_vwap = ta.vwap(
|
||||
high=df["High"],
|
||||
low=df["Low"],
|
||||
close=df["Close"],
|
||||
volume=df["Volume"],
|
||||
high=data["High"],
|
||||
low=data["Low"],
|
||||
close=data["Close"],
|
||||
volume=data["Volume"],
|
||||
offset=offset,
|
||||
)
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ __docformat__ = "numpy"
|
||||
import logging
|
||||
import os
|
||||
from typing import List, Optional
|
||||
from datetime import datetime
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import mplfinance as mpf
|
||||
@@ -35,7 +34,7 @@ def view_ma(
|
||||
length: List[int] = None,
|
||||
offset: int = 0,
|
||||
ma_type: str = "EMA",
|
||||
s_ticker: str = "",
|
||||
symbol: str = "",
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
) -> None:
|
||||
@@ -43,23 +42,25 @@ def view_ma(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
series : pd.Series
|
||||
series: pd.Series
|
||||
Series of prices
|
||||
length : List[int]
|
||||
length: List[int]
|
||||
Length of EMA window
|
||||
offset: int
|
||||
Offset variable
|
||||
ma_type: str
|
||||
Type of moving average. Either "EMA" "ZLMA" or "SMA"
|
||||
s_ticker : str
|
||||
symbol: str
|
||||
Ticker
|
||||
export : str
|
||||
export: str
|
||||
Format to export data
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
external_axes: Optional[List[plt.Axes]], optional
|
||||
External axes (1 axis is expected in the list), by default None
|
||||
"""
|
||||
# Define a dataframe for adding EMA series to it
|
||||
price_df = pd.DataFrame(series)
|
||||
|
||||
l_legend = [s_ticker]
|
||||
l_legend = [symbol]
|
||||
if not length:
|
||||
length = [20, 50]
|
||||
|
||||
@@ -93,11 +94,11 @@ def view_ma(
|
||||
|
||||
ax.plot(plot_data.index, plot_data.iloc[:, 1].values)
|
||||
ax.set_xlim([plot_data.index[0], plot_data.index[-1]])
|
||||
ax.set_ylabel(f"{s_ticker} Price")
|
||||
ax.set_ylabel(f"{symbol} Price")
|
||||
for idx in range(2, plot_data.shape[1]):
|
||||
ax.plot(plot_data.iloc[:, idx])
|
||||
|
||||
ax.set_title(f"{s_ticker} {ma_type.upper()}")
|
||||
ax.set_title(f"{symbol} {ma_type.upper()}")
|
||||
ax.legend(l_legend)
|
||||
theme.style_primary_axis(
|
||||
ax,
|
||||
@@ -118,28 +119,28 @@ def view_ma(
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def view_vwap(
|
||||
s_ticker: str,
|
||||
ohlc: pd.DataFrame,
|
||||
start: datetime = None,
|
||||
end: datetime = None,
|
||||
data: pd.DataFrame,
|
||||
symbol: str = "",
|
||||
start_date: str = None,
|
||||
end_date: str = None,
|
||||
offset: int = 0,
|
||||
s_interval: str = "",
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
"""Plots EMA technical indicator
|
||||
"""Plots VWMA technical indicator
|
||||
|
||||
Parameters
|
||||
----------
|
||||
s_ticker : str
|
||||
data : pd.DataFrame
|
||||
Dataframe of OHLC prices
|
||||
symbol : str
|
||||
Ticker
|
||||
ohlc : pd.DataFrame
|
||||
Dataframe of prices
|
||||
offset : int
|
||||
Offset variable
|
||||
start: datetime
|
||||
start_date: datetime
|
||||
Start date to get data from with
|
||||
end: datetime
|
||||
end_date: datetime
|
||||
End date to get data from with
|
||||
s_interval : str
|
||||
Interval of data
|
||||
@@ -149,21 +150,24 @@ def view_vwap(
|
||||
External axes (3 axes are expected in the list), by default None
|
||||
"""
|
||||
|
||||
ohlc.index = ohlc.index.tz_localize(None)
|
||||
data.index = data.index.tz_localize(None)
|
||||
|
||||
if start and end:
|
||||
start_date = start.date()
|
||||
end_date = end.date()
|
||||
if start_date is None:
|
||||
start = data.index[0].date()
|
||||
console.print(f"No start date specified. Start date: {start}")
|
||||
else:
|
||||
start_date = end_date = ohlc.index[-1].date()
|
||||
console.print(
|
||||
f"No Specified date range. load most recent trading data: {start_date.strftime('%Y-%m-%d')}"
|
||||
)
|
||||
start = start_date
|
||||
|
||||
day_df = ohlc[(start_date <= ohlc.index.date) & (ohlc.index.date <= end_date)]
|
||||
if end_date is None:
|
||||
end = data.index[-1].date()
|
||||
console.print(f"No end date specified. End date: {end}")
|
||||
else:
|
||||
end = end_date
|
||||
|
||||
day_df = data[(start <= data.index.date) & (data.index.date <= end)]
|
||||
if len(day_df) == 0:
|
||||
console.print(
|
||||
f"[red]No data found between {start_date.strftime('%Y-%m-%d')} and {end_date.strftime('%Y-%m-%d')}\n[/red]"
|
||||
f"[red]No data found between {start.strftime('%Y-%m-%d')} and {end.strftime('%Y-%m-%d')}\n[/red]"
|
||||
)
|
||||
return
|
||||
|
||||
@@ -194,7 +198,7 @@ def view_vwap(
|
||||
)
|
||||
fig, ax = mpf.plot(day_df, **candle_chart_kwargs)
|
||||
fig.suptitle(
|
||||
f"{s_ticker} {s_interval} VWAP",
|
||||
f"{symbol} {s_interval} VWAP",
|
||||
x=0.055,
|
||||
y=0.965,
|
||||
horizontalalignment="left",
|
||||
|
||||
@@ -16,7 +16,7 @@ def adx(
|
||||
high_values: pd.Series,
|
||||
low_values: pd.Series,
|
||||
close_values: pd.Series,
|
||||
length: int = 14,
|
||||
window: int = 14,
|
||||
scalar: int = 100,
|
||||
drift: int = 1,
|
||||
):
|
||||
@@ -30,7 +30,7 @@ def adx(
|
||||
Low prices
|
||||
close_values: pd.Series
|
||||
close prices
|
||||
length: int
|
||||
window: int
|
||||
Length of window
|
||||
scalar: int
|
||||
Scalar variable
|
||||
@@ -47,7 +47,7 @@ def adx(
|
||||
high=high_values,
|
||||
low=low_values,
|
||||
close=close_values,
|
||||
length=length,
|
||||
length=window,
|
||||
scalar=scalar,
|
||||
drift=drift,
|
||||
).dropna()
|
||||
@@ -56,7 +56,7 @@ def adx(
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def aroon(
|
||||
high_values: pd.Series, low_values: pd.Series, length: int = 25, scalar: int = 100
|
||||
high_values: pd.Series, low_values: pd.Series, window: int = 25, scalar: int = 100
|
||||
) -> pd.DataFrame:
|
||||
"""Aroon technical indicator
|
||||
|
||||
@@ -66,7 +66,7 @@ def aroon(
|
||||
High prices
|
||||
low_values: pd.Series
|
||||
Low prices
|
||||
length : int
|
||||
window : int
|
||||
Length of window
|
||||
scalar : int
|
||||
Scalar variable
|
||||
@@ -81,7 +81,7 @@ def aroon(
|
||||
ta.aroon(
|
||||
high=high_values,
|
||||
low=low_values,
|
||||
length=length,
|
||||
length=window,
|
||||
scalar=scalar,
|
||||
).dropna()
|
||||
)
|
||||
|
||||
@@ -27,11 +27,11 @@ register_matplotlib_converters()
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_adx(
|
||||
ohlc: pd.DataFrame,
|
||||
length: int = 14,
|
||||
data: pd.DataFrame,
|
||||
window: int = 14,
|
||||
scalar: int = 100,
|
||||
drift: int = 1,
|
||||
s_ticker: str = "",
|
||||
symbol: str = "",
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
@@ -39,15 +39,15 @@ def display_adx(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ohlc : pd.DataFrame
|
||||
data : pd.DataFrame
|
||||
Dataframe with OHLC price data
|
||||
length : int
|
||||
window : int
|
||||
Length of window
|
||||
scalar : int
|
||||
Scalar variable
|
||||
drift : int
|
||||
Drift variable
|
||||
s_ticker : str
|
||||
symbol : str
|
||||
Ticker
|
||||
export : str
|
||||
Format to export data
|
||||
@@ -55,14 +55,14 @@ def display_adx(
|
||||
External axes (2 axes are expected in the list), by default None
|
||||
"""
|
||||
df_ta = trend_indicators_model.adx(
|
||||
high_values=ohlc["High"],
|
||||
low_values=ohlc["Low"],
|
||||
close_values=ohlc["Adj Close"],
|
||||
length=length,
|
||||
high_values=data["High"],
|
||||
low_values=data["Low"],
|
||||
close_values=data["Adj Close"],
|
||||
window=window,
|
||||
scalar=scalar,
|
||||
drift=drift,
|
||||
)
|
||||
plot_data = pd.merge(ohlc, df_ta, how="outer", left_index=True, right_index=True)
|
||||
plot_data = pd.merge(data, df_ta, how="outer", left_index=True, right_index=True)
|
||||
plot_data = reindex_dates(plot_data)
|
||||
|
||||
# This plot has 2 axes
|
||||
@@ -77,7 +77,7 @@ def display_adx(
|
||||
return
|
||||
|
||||
ax1.plot(plot_data.index, plot_data["Close"].values)
|
||||
ax1.set_title(f"Average Directional Movement Index (ADX) on {s_ticker}")
|
||||
ax1.set_title(f"Average Directional Movement Index (ADX) on {symbol}")
|
||||
ax1.set_xlim(plot_data.index[0], plot_data.index[-1])
|
||||
ax1.set_ylabel("Price")
|
||||
theme.style_primary_axis(
|
||||
@@ -120,10 +120,10 @@ def display_adx(
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_aroon(
|
||||
ohlc: pd.DataFrame,
|
||||
length: int = 25,
|
||||
data: pd.DataFrame,
|
||||
window: int = 25,
|
||||
scalar: int = 100,
|
||||
s_ticker: str = "",
|
||||
symbol: str = "",
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
@@ -131,26 +131,26 @@ def display_aroon(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ohlc : pd.DataFrame
|
||||
data: pd.DataFrame
|
||||
Dataframe with OHLC price data
|
||||
length:int
|
||||
window: int
|
||||
Length of window
|
||||
s_ticker : str
|
||||
symbol: str
|
||||
Ticker
|
||||
scalar : int
|
||||
scalar: int
|
||||
Scalar variable
|
||||
export: str
|
||||
Format to export data
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
external_axes: Optional[List[plt.Axes]], optional
|
||||
External axes (3 axes are expected in the list), by default None
|
||||
"""
|
||||
df_ta = trend_indicators_model.aroon(
|
||||
high_values=ohlc["High"],
|
||||
low_values=ohlc["Low"],
|
||||
length=length,
|
||||
high_values=data["High"],
|
||||
low_values=data["Low"],
|
||||
window=window,
|
||||
scalar=scalar,
|
||||
)
|
||||
plot_data = pd.merge(ohlc, df_ta, how="outer", left_index=True, right_index=True)
|
||||
plot_data = pd.merge(data, df_ta, how="outer", left_index=True, right_index=True)
|
||||
plot_data = reindex_dates(plot_data)
|
||||
|
||||
# This plot has 3 axes
|
||||
@@ -165,7 +165,7 @@ def display_aroon(
|
||||
return
|
||||
|
||||
ax1.plot(plot_data.index, plot_data["Adj Close"].values)
|
||||
ax1.set_title(f"Aroon on {s_ticker}")
|
||||
ax1.set_title(f"Aroon on {symbol}")
|
||||
ax1.set_xlim(plot_data.index[0], plot_data.index[-1])
|
||||
ax1.set_ylabel("Price")
|
||||
theme.style_primary_axis(
|
||||
|
||||
@@ -15,7 +15,7 @@ MAMODES = ["ema", "sma", "wma", "hma", "zlma"]
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def bbands(
|
||||
close_values: pd.Series, length: int = 15, n_std: float = 2, mamode: str = "ema"
|
||||
close_values: pd.Series, window: int = 15, n_std: float = 2, mamode: str = "ema"
|
||||
) -> pd.DataFrame:
|
||||
"""Calculate Bollinger Bands
|
||||
|
||||
@@ -23,7 +23,7 @@ def bbands(
|
||||
----------
|
||||
close_values : pd.DataFrame
|
||||
DataFrame of sclose prices
|
||||
length : int
|
||||
window : int
|
||||
Length of window to calculate BB
|
||||
n_std : float
|
||||
Number of standard deviations to show
|
||||
@@ -38,7 +38,7 @@ def bbands(
|
||||
return pd.DataFrame(
|
||||
ta.bbands(
|
||||
close=close_values,
|
||||
length=length,
|
||||
length=window,
|
||||
std=n_std,
|
||||
mamode=mamode,
|
||||
)
|
||||
@@ -85,7 +85,7 @@ def kc(
|
||||
high_prices: pd.Series,
|
||||
low_prices: pd.Series,
|
||||
close_prices: pd.Series,
|
||||
length: int = 20,
|
||||
window: int = 20,
|
||||
scalar: float = 2,
|
||||
mamode: str = "ema",
|
||||
offset: int = 0,
|
||||
@@ -94,14 +94,16 @@ def kc(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
high_values : pd.DataFrame
|
||||
high_prices : pd.DataFrame
|
||||
High prices
|
||||
low_values : pd.DataFrame
|
||||
low_prices : pd.DataFrame
|
||||
Low prices
|
||||
close_values : pd.DataFrame
|
||||
close_prices : pd.DataFrame
|
||||
Close prices
|
||||
length : int
|
||||
window : int
|
||||
Length of window
|
||||
scalar: float
|
||||
Scalar value
|
||||
mamode: str
|
||||
Type of filter
|
||||
offset : int
|
||||
@@ -118,7 +120,7 @@ def kc(
|
||||
high=high_prices,
|
||||
low=low_prices,
|
||||
close=close_prices,
|
||||
length=length,
|
||||
length=window,
|
||||
scalar=scalar,
|
||||
mamode=mamode,
|
||||
offset=offset,
|
||||
|
||||
@@ -24,9 +24,9 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_bbands(
|
||||
ohlc: pd.DataFrame,
|
||||
ticker: str = "",
|
||||
length: int = 15,
|
||||
data: pd.DataFrame,
|
||||
symbol: str = "",
|
||||
limit: int = 15,
|
||||
n_std: float = 2,
|
||||
mamode: str = "sma",
|
||||
export: str = "",
|
||||
@@ -36,11 +36,11 @@ def display_bbands(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ohlc : pd.DataFrame
|
||||
Dataframe of stock prices
|
||||
ticker : str
|
||||
Ticker
|
||||
length : int
|
||||
data : pd.DataFrame
|
||||
Dataframe of ohlc prices
|
||||
symbol : str
|
||||
Ticker symbol
|
||||
limit : int
|
||||
Length of window to calculate BB
|
||||
n_std : float
|
||||
Number of standard deviations to show
|
||||
@@ -51,8 +51,8 @@ def display_bbands(
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
External axes (1 axis is expected in the list), by default None
|
||||
"""
|
||||
df_ta = volatility_model.bbands(ohlc["Adj Close"], length, n_std, mamode)
|
||||
plot_data = pd.merge(ohlc, df_ta, how="outer", left_index=True, right_index=True)
|
||||
df_ta = volatility_model.bbands(data["Adj Close"], limit, n_std, mamode)
|
||||
plot_data = pd.merge(data, df_ta, how="outer", left_index=True, right_index=True)
|
||||
plot_data = reindex_dates(plot_data)
|
||||
|
||||
# This plot has 1 axis
|
||||
@@ -80,10 +80,10 @@ def display_bbands(
|
||||
theme.up_color,
|
||||
linewidth=0.7,
|
||||
)
|
||||
ax.set_title(f"{ticker} Bollinger Bands")
|
||||
ax.set_title(f"{symbol} Bollinger Bands")
|
||||
ax.set_xlim(plot_data.index[0], plot_data.index[-1])
|
||||
ax.set_ylabel("Share Price ($)")
|
||||
ax.legend([ticker, df_ta.columns[0], df_ta.columns[1], df_ta.columns[2]])
|
||||
ax.legend([symbol, df_ta.columns[0], df_ta.columns[1], df_ta.columns[2]])
|
||||
ax.fill_between(
|
||||
df_ta.index, df_ta.iloc[:, 0].values, df_ta.iloc[:, 2].values, alpha=0.1
|
||||
)
|
||||
@@ -106,8 +106,8 @@ def display_bbands(
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_donchian(
|
||||
ohlc: pd.DataFrame,
|
||||
ticker: str = "",
|
||||
data: pd.DataFrame,
|
||||
symbol: str = "",
|
||||
upper_length: int = 20,
|
||||
lower_length: int = 20,
|
||||
export: str = "",
|
||||
@@ -117,10 +117,10 @@ def display_donchian(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ohlc : pd.DataFrame
|
||||
Dataframe of stock prices
|
||||
ticker : str
|
||||
Ticker
|
||||
data : pd.DataFrame
|
||||
Dataframe of ohlc prices
|
||||
symbol : str
|
||||
Ticker symbol
|
||||
upper_length : int
|
||||
Length of window to calculate upper channel
|
||||
lower_length : int
|
||||
@@ -131,9 +131,9 @@ def display_donchian(
|
||||
External axes (1 axis is expected in the list), by default None
|
||||
"""
|
||||
df_ta = volatility_model.donchian(
|
||||
ohlc["High"], ohlc["Low"], upper_length, lower_length
|
||||
data["High"], data["Low"], upper_length, lower_length
|
||||
)
|
||||
plot_data = pd.merge(ohlc, df_ta, how="outer", left_index=True, right_index=True)
|
||||
plot_data = pd.merge(data, df_ta, how="outer", left_index=True, right_index=True)
|
||||
plot_data = reindex_dates(plot_data)
|
||||
|
||||
# This plot has 1 axis
|
||||
@@ -164,10 +164,10 @@ def display_donchian(
|
||||
plot_data[df_ta.columns[2]].values,
|
||||
alpha=0.1,
|
||||
)
|
||||
ax.set_title(f"{ticker} donchian")
|
||||
ax.set_title(f"{symbol} donchian")
|
||||
ax.set_xlim(plot_data.index[0], plot_data.index[-1])
|
||||
ax.set_ylabel("Price ($)")
|
||||
ax.legend([ticker, df_ta.columns[0], df_ta.columns[1], df_ta.columns[2]])
|
||||
ax.legend([symbol, df_ta.columns[0], df_ta.columns[1], df_ta.columns[2]])
|
||||
theme.style_primary_axis(
|
||||
ax,
|
||||
data_index=plot_data.index.to_list(),
|
||||
@@ -187,12 +187,12 @@ def display_donchian(
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def view_kc(
|
||||
ohlc: pd.DataFrame,
|
||||
length: int = 20,
|
||||
data: pd.DataFrame,
|
||||
limit: int = 20,
|
||||
scalar: float = 2,
|
||||
mamode: str = "ema",
|
||||
offset: int = 0,
|
||||
s_ticker: str = "",
|
||||
symbol: str = "",
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
@@ -201,31 +201,33 @@ def view_kc(
|
||||
Parameters
|
||||
----------
|
||||
|
||||
ohlc : pd.DataFrame
|
||||
Dataframe of stock prices
|
||||
length : int
|
||||
data: pd.DataFrame
|
||||
Dataframe of ohlc prices
|
||||
limit: int
|
||||
Length of window
|
||||
scalar: float
|
||||
Scalar value
|
||||
mamode: str
|
||||
Type of filter
|
||||
offset : int
|
||||
offset: int
|
||||
Offset value
|
||||
s_ticker : str
|
||||
Ticker
|
||||
export : str
|
||||
symbol: str
|
||||
Ticker symbol
|
||||
export: str
|
||||
Format to export data
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
external_axes: Optional[List[plt.Axes]], optional
|
||||
External axes (2 axes are expected in the list), by default None
|
||||
"""
|
||||
df_ta = volatility_model.kc(
|
||||
ohlc["High"],
|
||||
ohlc["Low"],
|
||||
ohlc["Adj Close"],
|
||||
length,
|
||||
data["High"],
|
||||
data["Low"],
|
||||
data["Adj Close"],
|
||||
limit,
|
||||
scalar,
|
||||
mamode,
|
||||
offset,
|
||||
)
|
||||
plot_data = pd.merge(ohlc, df_ta, how="outer", left_index=True, right_index=True)
|
||||
plot_data = pd.merge(data, df_ta, how="outer", left_index=True, right_index=True)
|
||||
plot_data = reindex_dates(plot_data)
|
||||
|
||||
# This plot has 1 axis
|
||||
@@ -256,10 +258,10 @@ def view_kc(
|
||||
plot_data[df_ta.columns[2]].values,
|
||||
alpha=0.1,
|
||||
)
|
||||
ax.set_title(f"{s_ticker} Keltner Channels")
|
||||
ax.set_title(f"{symbol} Keltner Channels")
|
||||
ax.set_xlim(plot_data.index[0], plot_data.index[-1])
|
||||
ax.set_ylabel("Price")
|
||||
ax.legend([s_ticker, df_ta.columns[0], df_ta.columns[1], df_ta.columns[2]])
|
||||
ax.legend([symbol, df_ta.columns[0], df_ta.columns[1], df_ta.columns[2]])
|
||||
theme.style_primary_axis(
|
||||
ax,
|
||||
data_index=plot_data.index.to_list(),
|
||||
|
||||
@@ -12,12 +12,12 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def ad(df_stock: pd.DataFrame, use_open: bool = False) -> pd.DataFrame:
|
||||
def ad(data: pd.DataFrame, use_open: bool = False) -> pd.DataFrame:
|
||||
"""Calculate AD technical indicator
|
||||
|
||||
Parameters
|
||||
----------
|
||||
df_stock : pd.DataFrame
|
||||
data : pd.DataFrame
|
||||
Dataframe of prices with OHLC and Volume
|
||||
use_open : bool
|
||||
Whether to use open prices
|
||||
@@ -29,35 +29,39 @@ def ad(df_stock: pd.DataFrame, use_open: bool = False) -> pd.DataFrame:
|
||||
"""
|
||||
if use_open:
|
||||
df_ta = ta.ad(
|
||||
high=df_stock["High"],
|
||||
low=df_stock["Low"],
|
||||
close=df_stock["Close"],
|
||||
volume=df_stock["Volume"],
|
||||
open_=df_stock["Open"],
|
||||
high=data["High"],
|
||||
low=data["Low"],
|
||||
close=data["Close"],
|
||||
volume=data["Volume"],
|
||||
open_=data["Open"],
|
||||
).dropna()
|
||||
# Do not use open stock values
|
||||
else:
|
||||
df_ta = ta.ad(
|
||||
high=df_stock["High"],
|
||||
low=df_stock["Low"],
|
||||
close=df_stock["Close"],
|
||||
volume=df_stock["Volume"],
|
||||
high=data["High"],
|
||||
low=data["Low"],
|
||||
close=data["Close"],
|
||||
volume=data["Volume"],
|
||||
).dropna()
|
||||
return pd.DataFrame(df_ta)
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def adosc(
|
||||
df_stock: pd.DataFrame, use_open: bool = False, fast: int = 3, slow: int = 10
|
||||
data: pd.DataFrame, use_open: bool = False, fast: int = 3, slow: int = 10
|
||||
) -> pd.DataFrame:
|
||||
"""Calculate AD oscillator technical indicator
|
||||
|
||||
Parameters
|
||||
----------
|
||||
df_stock : pd.DataFrame
|
||||
Dataframe of prices
|
||||
data : pd.DataFrame
|
||||
Dataframe of OHLC prices
|
||||
use_open : bool
|
||||
Whether to use open prices
|
||||
fast: int
|
||||
Fast value
|
||||
slow: int
|
||||
Slow value
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -66,20 +70,20 @@ def adosc(
|
||||
"""
|
||||
if use_open:
|
||||
df_ta = ta.adosc(
|
||||
high=df_stock["High"],
|
||||
low=df_stock["Low"],
|
||||
close=df_stock["Close"],
|
||||
volume=df_stock["Volume"],
|
||||
open_=df_stock["Open"],
|
||||
high=data["High"],
|
||||
low=data["Low"],
|
||||
close=data["Close"],
|
||||
volume=data["Volume"],
|
||||
open_=data["Open"],
|
||||
fast=fast,
|
||||
slow=slow,
|
||||
).dropna()
|
||||
else:
|
||||
df_ta = ta.adosc(
|
||||
high=df_stock["High"],
|
||||
low=df_stock["Low"],
|
||||
close=df_stock["Close"],
|
||||
volume=df_stock["Volume"],
|
||||
high=data["High"],
|
||||
low=data["Low"],
|
||||
close=data["Close"],
|
||||
volume=data["Volume"],
|
||||
fast=fast,
|
||||
slow=slow,
|
||||
).dropna()
|
||||
@@ -87,19 +91,17 @@ def adosc(
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def obv(df_stock: pd.DataFrame) -> pd.DataFrame:
|
||||
def obv(data: pd.DataFrame) -> pd.DataFrame:
|
||||
"""On Balance Volume
|
||||
|
||||
Parameters
|
||||
----------
|
||||
df_stock: pd.DataFrame
|
||||
Dataframe of stock prices
|
||||
data: pd.DataFrame
|
||||
Dataframe of OHLC prices
|
||||
|
||||
Returns
|
||||
-------
|
||||
pd.DataFrame
|
||||
Dataframe with technical indicator
|
||||
"""
|
||||
return pd.DataFrame(
|
||||
ta.obv(close=df_stock["Adj Close"], volume=df_stock["Volume"]).dropna()
|
||||
)
|
||||
return pd.DataFrame(ta.obv(close=data["Adj Close"], volume=data["Volume"]).dropna())
|
||||
|
||||
@@ -24,9 +24,9 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_ad(
|
||||
ohlc: pd.DataFrame,
|
||||
data: pd.DataFrame,
|
||||
use_open: bool = False,
|
||||
s_ticker: str = "",
|
||||
symbol: str = "",
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
@@ -34,25 +34,25 @@ def display_ad(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ohlc : pd.DataFrame
|
||||
Dataframe of prices
|
||||
data : pd.DataFrame
|
||||
Dataframe of ohlc prices
|
||||
use_open : bool
|
||||
Whether to use open prices in calculation
|
||||
s_ticker : str
|
||||
Ticker
|
||||
symbol : str
|
||||
Ticker symbol
|
||||
export: str
|
||||
Format to export data as
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
External axes (3 axes are expected in the list), by default None
|
||||
"""
|
||||
divisor = 1_000_000
|
||||
df_vol = ohlc["Volume"] / divisor
|
||||
df_vol = data["Volume"] / divisor
|
||||
df_vol.name = "Adj Volume"
|
||||
df_ta = volume_model.ad(ohlc, use_open)
|
||||
df_ta = volume_model.ad(data, use_open)
|
||||
df_cal = df_ta["AD"] / divisor
|
||||
df_cal.name = "Adj AD"
|
||||
|
||||
plot_data = pd.merge(ohlc, df_vol, how="outer", left_index=True, right_index=True)
|
||||
plot_data = pd.merge(data, df_vol, how="outer", left_index=True, right_index=True)
|
||||
plot_data = pd.merge(
|
||||
plot_data, df_ta, how="outer", left_index=True, right_index=True
|
||||
)
|
||||
@@ -77,7 +77,7 @@ def display_ad(
|
||||
return
|
||||
|
||||
ax1.plot(plot_data.index, plot_data["Adj Close"].values)
|
||||
ax1.set_title(f"{s_ticker} AD", x=0.08, y=1)
|
||||
ax1.set_title(f"{symbol} AD", x=0.08, y=1)
|
||||
ax1.set_xlim(plot_data.index[0], plot_data.index[-1])
|
||||
ax1.set_ylabel("Price")
|
||||
theme.style_primary_axis(
|
||||
@@ -127,11 +127,11 @@ def display_ad(
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_adosc(
|
||||
ohlc: pd.DataFrame,
|
||||
data: pd.DataFrame,
|
||||
fast: int = 3,
|
||||
slow: int = 10,
|
||||
use_open: bool = False,
|
||||
s_ticker: str = "",
|
||||
symbol: str = "",
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
@@ -139,15 +139,15 @@ def display_adosc(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ohlc : pd.DataFrame
|
||||
Dataframe of prices
|
||||
data : pd.DataFrame
|
||||
Dataframe of ohlc prices
|
||||
use_open : bool
|
||||
Whether to use open prices in calculation
|
||||
fast: int
|
||||
Length of fast window
|
||||
slow : int
|
||||
Length of slow window
|
||||
s_ticker : str
|
||||
symbol : str
|
||||
Stock ticker
|
||||
export : str
|
||||
Format to export data
|
||||
@@ -155,13 +155,13 @@ def display_adosc(
|
||||
External axes (3 axes are expected in the list), by default None
|
||||
"""
|
||||
divisor = 1_000_000
|
||||
df_vol = ohlc["Volume"] / divisor
|
||||
df_vol = data["Volume"] / divisor
|
||||
df_vol.name = "Adj Volume"
|
||||
df_ta = volume_model.adosc(ohlc, use_open, fast, slow)
|
||||
df_ta = volume_model.adosc(data, use_open, fast, slow)
|
||||
df_cal = df_ta[df_ta.columns[0]] / divisor
|
||||
df_cal.name = "Adj ADOSC"
|
||||
|
||||
plot_data = pd.merge(ohlc, df_vol, how="outer", left_index=True, right_index=True)
|
||||
plot_data = pd.merge(data, df_vol, how="outer", left_index=True, right_index=True)
|
||||
plot_data = pd.merge(
|
||||
plot_data, df_ta, how="outer", left_index=True, right_index=True
|
||||
)
|
||||
@@ -185,7 +185,7 @@ def display_adosc(
|
||||
else:
|
||||
return
|
||||
|
||||
ax1.set_title(f"{s_ticker} AD Oscillator")
|
||||
ax1.set_title(f"{symbol} AD Oscillator")
|
||||
ax1.plot(plot_data.index, plot_data["Adj Close"].values)
|
||||
ax1.set_xlim(plot_data.index[0], plot_data.index[-1])
|
||||
ax1.set_ylabel("Price")
|
||||
@@ -235,8 +235,8 @@ def display_adosc(
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_obv(
|
||||
ohlc: pd.DataFrame,
|
||||
s_ticker: str = "",
|
||||
data: pd.DataFrame,
|
||||
symbol: str = "",
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
@@ -244,9 +244,9 @@ def display_obv(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ohlc : pd.DataFrame
|
||||
Dataframe of prices
|
||||
s_ticker : str
|
||||
data : pd.DataFrame
|
||||
Dataframe of ohlc prices
|
||||
symbol : str
|
||||
Ticker
|
||||
export: str
|
||||
Format to export data as
|
||||
@@ -254,13 +254,13 @@ def display_obv(
|
||||
External axes (1 axis is expected in the list), by default None
|
||||
"""
|
||||
divisor = 1_000_000
|
||||
df_vol = ohlc["Volume"] / divisor
|
||||
df_vol = data["Volume"] / divisor
|
||||
df_vol.name = "Adj Volume"
|
||||
df_ta = volume_model.obv(ohlc)
|
||||
df_ta = volume_model.obv(data)
|
||||
df_cal = df_ta[df_ta.columns[0]] / divisor
|
||||
df_cal.name = "Adj OBV"
|
||||
|
||||
plot_data = pd.merge(ohlc, df_vol, how="outer", left_index=True, right_index=True)
|
||||
plot_data = pd.merge(data, df_vol, how="outer", left_index=True, right_index=True)
|
||||
plot_data = pd.merge(
|
||||
plot_data, df_ta, how="outer", left_index=True, right_index=True
|
||||
)
|
||||
@@ -285,7 +285,7 @@ def display_obv(
|
||||
return
|
||||
|
||||
ax1.plot(plot_data.index, plot_data["Adj Close"].values)
|
||||
ax1.set_title(f"{s_ticker} OBV")
|
||||
ax1.set_title(f"{symbol} OBV")
|
||||
ax1.set_xlim(plot_data.index[0], plot_data.index[-1])
|
||||
ax1.set_ylabel("Price")
|
||||
theme.style_primary_axis(
|
||||
|
||||
@@ -301,7 +301,7 @@ class CryptoController(CryptoBaseController):
|
||||
|
||||
if ns_parser:
|
||||
finbrain_crypto_view.display_crypto_sentiment_analysis(
|
||||
coin=ns_parser.coin, export=ns_parser.export
|
||||
symbol=ns_parser.coin, export=ns_parser.export
|
||||
)
|
||||
|
||||
@log_start_end(log=logger)
|
||||
@@ -469,16 +469,16 @@ class CryptoController(CryptoBaseController):
|
||||
# TODO: merge find + display_all_coins
|
||||
if ns_parser.coin:
|
||||
find(
|
||||
coin=ns_parser.coin,
|
||||
query=ns_parser.coin,
|
||||
source=ns_parser.source,
|
||||
key=ns_parser.key,
|
||||
top=ns_parser.limit,
|
||||
limit=ns_parser.limit,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
display_all_coins(
|
||||
coin=ns_parser.coin,
|
||||
symbol=ns_parser.coin,
|
||||
source=ns_parser.source,
|
||||
top=ns_parser.limit,
|
||||
limit=ns_parser.limit,
|
||||
skip=ns_parser.skip,
|
||||
show_all=bool("ALL" in other_args),
|
||||
export=ns_parser.export,
|
||||
|
||||
@@ -22,6 +22,7 @@ from openbb_terminal.helper_funcs import (
|
||||
plot_autoscale,
|
||||
export_data,
|
||||
print_rich_table,
|
||||
lambda_long_number_format_y_axis,
|
||||
is_valid_axes_count,
|
||||
)
|
||||
from openbb_terminal.config_plot import PLOT_DPI
|
||||
@@ -288,15 +289,16 @@ def get_coinpaprika_id(symbol: str):
|
||||
|
||||
|
||||
def load(
|
||||
symbol_search: str,
|
||||
symbol: str,
|
||||
vs: str = "usd",
|
||||
days: int = 365,
|
||||
):
|
||||
"""Load crypto currency to perform analysis on CoinGecko is used as source for price and YahooFinance for volume.
|
||||
"""Load crypto currency to perform analysis on CoinGecko is used as source for price and
|
||||
YahooFinance for volume.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
symbol_search: str
|
||||
symbol: str
|
||||
Coin to get
|
||||
vs: str
|
||||
Quote Currency (usd or eur), by default usd
|
||||
@@ -308,7 +310,7 @@ def load(
|
||||
pd.DataFrame
|
||||
Dataframe consisting of price and volume data
|
||||
"""
|
||||
coingecko_id = get_coingecko_id(symbol_search)
|
||||
coingecko_id = get_coingecko_id(symbol)
|
||||
if not coingecko_id:
|
||||
return pd.DataFrame()
|
||||
|
||||
@@ -316,7 +318,7 @@ def load(
|
||||
|
||||
start_date = datetime.now() - timedelta(days=days)
|
||||
df = yf.download(
|
||||
f"{symbol_search}-{vs}",
|
||||
f"{symbol}-{vs}",
|
||||
end=datetime.now(),
|
||||
start=start_date,
|
||||
progress=False,
|
||||
@@ -328,7 +330,7 @@ def load(
|
||||
df.index.name = "date"
|
||||
if not df.empty:
|
||||
console.print(
|
||||
f"\nLoading Daily {symbol_search.upper()} crypto "
|
||||
f"\nLoading Daily {symbol.upper()} crypto "
|
||||
f"with starting period {start_date.strftime('%Y-%m-%d')} for analysis.",
|
||||
)
|
||||
return df
|
||||
@@ -757,13 +759,17 @@ FIND_KEYS = ["id", "symbol", "name"]
|
||||
|
||||
|
||||
def find(
|
||||
coin: str, source: str = "cg", key: str = "symbol", top: int = 10, export: str = ""
|
||||
query: str,
|
||||
source: str = "cg",
|
||||
key: str = "symbol",
|
||||
limit: int = 10,
|
||||
export: str = "",
|
||||
) -> None:
|
||||
"""Find similar coin by coin name,symbol or id.
|
||||
|
||||
If you don't remember exact name or id of the Coin at CoinGecko CoinPaprika, Binance or Coinbase
|
||||
you can use this command to display coins with similar name, symbol or id to your search query.
|
||||
Example of usage: coin name is something like "polka". So I can try: find -c polka -k name -t 25
|
||||
If you don't know exact name or id of the Coin at CoinGecko CoinPaprika, Binance or Coinbase
|
||||
you use this command to display coins with similar name, symbol or id to your search query.
|
||||
Example: coin name is something like "polka". So I can try: find -c polka -k name -t 25
|
||||
It will search for coin that has similar name to polka and display top 25 matches.
|
||||
|
||||
-c, --coin stands for coin - you provide here your search query
|
||||
@@ -772,14 +778,14 @@ def find(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
top: int
|
||||
Number of records to display
|
||||
coin: str
|
||||
query: str
|
||||
Cryptocurrency
|
||||
key: str
|
||||
Searching key (symbol, id, name)
|
||||
source: str
|
||||
Data source of coins. CoinGecko (cg) or CoinPaprika (cp) or Binance (bin), Coinbase (cb)
|
||||
key: str
|
||||
Searching key (symbol, id, name)
|
||||
limit: int
|
||||
Number of records to display
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
@@ -788,8 +794,8 @@ def find(
|
||||
coins_df = get_coin_list()
|
||||
coins_list = coins_df[key].to_list()
|
||||
if key in ["symbol", "id"]:
|
||||
coin = coin.lower()
|
||||
sim = difflib.get_close_matches(coin, coins_list, top)
|
||||
coin = query.lower()
|
||||
sim = difflib.get_close_matches(coin, coins_list, limit)
|
||||
df = pd.Series(sim).to_frame().reset_index()
|
||||
df.columns = ["index", key]
|
||||
coins_df.drop("index", axis=1, inplace=True)
|
||||
@@ -803,7 +809,7 @@ def find(
|
||||
func_key = keys[key]
|
||||
coin = getattr(coin, str(func_key))()
|
||||
|
||||
sim = difflib.get_close_matches(coin, coins_list, top)
|
||||
sim = difflib.get_close_matches(coin, coins_list, limit)
|
||||
df = pd.Series(sim).to_frame().reset_index()
|
||||
df.columns = ["index", key]
|
||||
df = df.merge(coins_df, on=key)
|
||||
@@ -821,7 +827,7 @@ def find(
|
||||
)
|
||||
coins_list = coins[key].to_list()
|
||||
|
||||
sim = difflib.get_close_matches(coin, coins_list, top)
|
||||
sim = difflib.get_close_matches(coin, coins_list, limit)
|
||||
df = pd.Series(sim).to_frame().reset_index()
|
||||
df.columns = ["index", key]
|
||||
df = df.merge(coins, on=key)
|
||||
@@ -837,7 +843,7 @@ def find(
|
||||
)
|
||||
coins_list = coins[key].to_list()
|
||||
|
||||
sim = difflib.get_close_matches(coin, coins_list, top)
|
||||
sim = difflib.get_close_matches(coin, coins_list, limit)
|
||||
df = pd.Series(sim).to_frame().reset_index()
|
||||
df.columns = ["index", key]
|
||||
df = df.merge(coins, on=key)
|
||||
@@ -993,7 +999,7 @@ def load_ta_data(
|
||||
# console.print(f"{coin} loaded vs {currency}")
|
||||
|
||||
df = coinbase_model.get_candles(
|
||||
product_id=pair,
|
||||
symbol=pair,
|
||||
interval=interval or "24hour",
|
||||
).head(limit)
|
||||
|
||||
@@ -1062,7 +1068,7 @@ def load_yf_data(symbol: str, currency: str, interval: str, days: int):
|
||||
|
||||
|
||||
def display_all_coins(
|
||||
source: str, coin: str, top: int, skip: int, show_all: bool, export: str
|
||||
source: str, symbol: str, limit: int, skip: int, show_all: bool, export: str
|
||||
) -> None:
|
||||
"""Find similar coin by coin name,symbol or id.
|
||||
If you don't remember exact name or id of the Coin at CoinGecko, CoinPaprika, Coinbase, Binance
|
||||
@@ -1073,9 +1079,9 @@ def display_all_coins(
|
||||
-t, --top it displays top N number of records.
|
||||
Parameters
|
||||
----------
|
||||
top: int
|
||||
limit: int
|
||||
Number of records to display
|
||||
coin: str
|
||||
symbol: str
|
||||
Cryptocurrency
|
||||
source: str
|
||||
Data source of coins. CoinGecko (cg) or CoinPaprika (cp) or Binance (bin), Coinbase (cb)
|
||||
@@ -1105,7 +1111,7 @@ def display_all_coins(
|
||||
elif not source or source not in sources:
|
||||
df = prepare_all_coins_df()
|
||||
cg_coins_list = df["CoinGecko"].to_list()
|
||||
sim = difflib.get_close_matches(coin.lower(), cg_coins_list, limit, cutoff)
|
||||
sim = difflib.get_close_matches(symbol.lower(), cg_coins_list, limit, cutoff)
|
||||
df_matched = pd.Series(sim).to_frame().reset_index()
|
||||
df_matched.columns = ["index", "CoinGecko"]
|
||||
df = df.merge(df_matched, on="CoinGecko")
|
||||
@@ -1115,12 +1121,12 @@ def display_all_coins(
|
||||
|
||||
if source == "cg":
|
||||
coins_df = get_coin_list().drop("index", axis=1)
|
||||
df = _create_closest_match_df(coin.lower(), coins_df, limit, cutoff)
|
||||
df = _create_closest_match_df(symbol.lower(), coins_df, limit, cutoff)
|
||||
df = df[["index", "id", "name"]]
|
||||
|
||||
elif source == "cp":
|
||||
coins_df = get_list_of_coins()
|
||||
df = _create_closest_match_df(coin.lower(), coins_df, limit, cutoff)
|
||||
df = _create_closest_match_df(symbol.lower(), coins_df, limit, cutoff)
|
||||
df = df[["index", "id", "name"]]
|
||||
|
||||
elif source == "bin":
|
||||
@@ -1130,7 +1136,7 @@ def display_all_coins(
|
||||
coins_df = pd.merge(
|
||||
coins_df_bin, coins_df_gecko[["id", "name"]], how="left", on="id"
|
||||
)
|
||||
df = _create_closest_match_df(coin.lower(), coins_df, limit, cutoff)
|
||||
df = _create_closest_match_df(symbol.lower(), coins_df, limit, cutoff)
|
||||
df = df[["index", "symbol", "name"]]
|
||||
df.columns = ["index", "id", "name"]
|
||||
|
||||
@@ -1141,7 +1147,7 @@ def display_all_coins(
|
||||
coins_df = pd.merge(
|
||||
coins_df_cb, coins_df_gecko[["id", "name"]], how="left", on="id"
|
||||
)
|
||||
df = _create_closest_match_df(coin.lower(), coins_df, limit, cutoff)
|
||||
df = _create_closest_match_df(symbol.lower(), coins_df, limit, cutoff)
|
||||
df = df[["index", "symbol", "name"]]
|
||||
df.columns = ["index", "id", "name"]
|
||||
|
||||
@@ -1151,7 +1157,7 @@ def display_all_coins(
|
||||
console.print("")
|
||||
|
||||
try:
|
||||
df = df[skip : skip + top] # noqa
|
||||
df = df[skip : skip + limit] # noqa
|
||||
except Exception as e:
|
||||
logger.exception(str(e))
|
||||
console.print(e)
|
||||
@@ -1240,39 +1246,22 @@ def plot_candles(
|
||||
"warn_too_much_data": 10000,
|
||||
}
|
||||
|
||||
maximum_value = candles_df.max().max()
|
||||
|
||||
if maximum_value > 1_000_000_000_000:
|
||||
df_rounded = candles_df / 1_000_000_000_000
|
||||
denomination = " in Trillions"
|
||||
elif maximum_value > 1_000_000_000:
|
||||
df_rounded = candles_df / 1_000_000_000
|
||||
denomination = " in Billions"
|
||||
elif maximum_value > 1_000_000:
|
||||
df_rounded = candles_df / 1_000_000
|
||||
denomination = " in Millions"
|
||||
elif maximum_value > 1_000:
|
||||
df_rounded = candles_df / 1_000
|
||||
denomination = " in Thousands"
|
||||
else:
|
||||
df_rounded = candles_df
|
||||
denomination = ""
|
||||
|
||||
# This plot has 2 axes
|
||||
if external_axes is None:
|
||||
candle_chart_kwargs["returnfig"] = True
|
||||
candle_chart_kwargs["figratio"] = (10, 7)
|
||||
candle_chart_kwargs["figscale"] = 1.10
|
||||
candle_chart_kwargs["figsize"] = plot_autoscale()
|
||||
fig, _ = mpf.plot(df_rounded, **candle_chart_kwargs)
|
||||
fig, ax = mpf.plot(candles_df, **candle_chart_kwargs)
|
||||
|
||||
fig.suptitle(
|
||||
f"\n{title} [{denomination}]",
|
||||
f"\n{title}",
|
||||
horizontalalignment="left",
|
||||
verticalalignment="top",
|
||||
x=0.05,
|
||||
y=1,
|
||||
)
|
||||
lambda_long_number_format_y_axis(candles_df, "Volume", ax)
|
||||
theme.visualize_output(force_tight_layout=False)
|
||||
else:
|
||||
nr_external_axes = 2 if volume else 1
|
||||
@@ -1287,9 +1276,7 @@ def plot_candles(
|
||||
|
||||
candle_chart_kwargs["ax"] = ax
|
||||
|
||||
console.print(f"Data {denomination}")
|
||||
|
||||
mpf.plot(df_rounded, **candle_chart_kwargs)
|
||||
mpf.plot(candles_df, **candle_chart_kwargs)
|
||||
|
||||
|
||||
def plot_order_book(
|
||||
|
||||
@@ -9,7 +9,7 @@ import pandas as pd
|
||||
import requests
|
||||
|
||||
from openbb_terminal.decorators import log_start_end
|
||||
from openbb_terminal.helper_funcs import get_user_agent
|
||||
from openbb_terminal.helper_funcs import get_user_agent, lambda_long_number_format
|
||||
|
||||
|
||||
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||
@@ -108,6 +108,8 @@ def get_defi_vaults(
|
||||
chain: Optional[str] = None,
|
||||
protocol: Optional[str] = None,
|
||||
kind: Optional[str] = None,
|
||||
ascend: bool = True,
|
||||
sortby: str = "apy",
|
||||
) -> pd.DataFrame:
|
||||
"""Get DeFi Vaults Information. DeFi Vaults are pools of funds with an assigned strategy which main goal is to
|
||||
maximize returns of its crypto assets. [Source: https://coindix.com/]
|
||||
@@ -148,7 +150,16 @@ def get_defi_vaults(
|
||||
data = response.json()["data"]
|
||||
if len(data) == 0:
|
||||
return pd.DataFrame()
|
||||
return pd.DataFrame(data)[VAULTS_FILTERS]
|
||||
df = pd.DataFrame(data)[VAULTS_FILTERS]
|
||||
except Exception as e:
|
||||
logger.exception(e)
|
||||
raise ValueError(f"Invalid Response: {response.text}") from e
|
||||
|
||||
df = df.sort_values(by=sortby, ascending=ascend).fillna("NA")
|
||||
df["tvl"] = df["tvl"].apply(lambda x: lambda_long_number_format(x))
|
||||
df["apy"] = df["apy"].apply(
|
||||
lambda x: f"{str(round(x * 100, 2))} %" if isinstance(x, (int, float)) else x
|
||||
)
|
||||
df.columns = [x.title() for x in df.columns]
|
||||
df.rename(columns={"Apy": "APY (%)", "Tvl": "TVL ($)"}, inplace=True)
|
||||
return df
|
||||
|
||||
@@ -9,7 +9,6 @@ from openbb_terminal.cryptocurrency.defi import coindix_model
|
||||
from openbb_terminal.decorators import log_start_end
|
||||
from openbb_terminal.helper_funcs import (
|
||||
export_data,
|
||||
lambda_long_number_format,
|
||||
print_rich_table,
|
||||
)
|
||||
|
||||
@@ -23,7 +22,7 @@ def display_defi_vaults(
|
||||
kind: Optional[str] = None,
|
||||
top: int = 10,
|
||||
sortby: str = "apy",
|
||||
descend: bool = False,
|
||||
ascend: bool = True,
|
||||
link: bool = False,
|
||||
export: str = "",
|
||||
) -> None:
|
||||
@@ -51,7 +50,7 @@ def display_defi_vaults(
|
||||
Number of records to display
|
||||
sortby: str
|
||||
Key by which to sort data
|
||||
descend: bool
|
||||
ascend: bool
|
||||
Flag to sort data descending
|
||||
link: bool
|
||||
Flag to show links
|
||||
@@ -59,24 +58,18 @@ def display_defi_vaults(
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
|
||||
df = coindix_model.get_defi_vaults(chain=chain, protocol=protocol, kind=kind)
|
||||
df_data = df.copy()
|
||||
df = coindix_model.get_defi_vaults(
|
||||
chain=chain, protocol=protocol, kind=kind, sortby=sortby, ascend=ascend
|
||||
)
|
||||
if df.empty:
|
||||
print(
|
||||
f"Couldn't find any vaults for "
|
||||
f"{'' if not chain else 'chain: ' + chain}{'' if not protocol else ', protocol: ' + protocol}"
|
||||
f"{'' if not chain else 'chain: ' + chain}"
|
||||
f"{'' if not protocol else ', protocol: ' + protocol}"
|
||||
f"{'' if not kind else ', kind:' + kind}"
|
||||
)
|
||||
return
|
||||
|
||||
df = df.sort_values(by=sortby, ascending=descend).fillna("NA")
|
||||
df["tvl"] = df["tvl"].apply(lambda x: lambda_long_number_format(x))
|
||||
df["apy"] = df["apy"].apply(
|
||||
lambda x: f"{str(round(x * 100, 2))} %" if isinstance(x, (int, float)) else x
|
||||
)
|
||||
df.columns = [x.title() for x in df.columns]
|
||||
df.rename(columns={"Apy": "APY (%)", "Tvl": "TVL ($)"}, inplace=True)
|
||||
|
||||
if link is True:
|
||||
df.drop("Link", axis=1, inplace=True)
|
||||
|
||||
@@ -91,5 +84,5 @@ def display_defi_vaults(
|
||||
export,
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"vaults",
|
||||
df_data,
|
||||
df,
|
||||
)
|
||||
|
||||
@@ -38,7 +38,7 @@ def display_anchor_data(
|
||||
address : str
|
||||
Terra address. Valid terra addresses start with 'terra'
|
||||
show_transactions : bool
|
||||
Flag to show history of transactions in Anchor protocol for address specified. Default False
|
||||
Flag to show history of transactions in Anchor protocol for address. Default False
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
@@ -54,9 +54,7 @@ def display_anchor_data(
|
||||
(ax,) = external_axes
|
||||
else:
|
||||
return
|
||||
print("")
|
||||
console.print(stats_str)
|
||||
print("")
|
||||
console.print(f"\n{stats_str}\n")
|
||||
|
||||
if show_transactions:
|
||||
print_rich_table(
|
||||
|
||||
@@ -6,8 +6,6 @@ from openbb_terminal.helper_classes import ModelsNamespace as _models
|
||||
# pylint: disable=unused-import
|
||||
|
||||
# Menu commands
|
||||
from .terraengineer_view import display_terra_asset_history as aterra
|
||||
from .terraengineer_view import display_anchor_yield_reserve as ayr
|
||||
from .terramoney_fcd_view import display_account_staking_info as sinfo
|
||||
from .terramoney_fcd_view import display_validators as validators
|
||||
from .terramoney_fcd_view import display_account_growth as gacc
|
||||
|
||||
@@ -21,7 +21,6 @@ from openbb_terminal.cryptocurrency.defi import (
|
||||
llama_view,
|
||||
substack_view,
|
||||
terraengineer_model,
|
||||
terraengineer_view,
|
||||
terramoney_fcd_model,
|
||||
terramoney_fcd_view,
|
||||
smartstake_view,
|
||||
@@ -160,71 +159,6 @@ class DefiController(BaseController):
|
||||
address=ns_parser.address,
|
||||
)
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def call_aterra(self, other_args: List[str]):
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
prog="aterra",
|
||||
description="""
|
||||
Displays the 30-day history of an asset in a certain terra address.
|
||||
[Source: https://terra.engineer/]
|
||||
""",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--asset",
|
||||
dest="asset",
|
||||
type=str,
|
||||
help="Terra asset {ust,luna,sdt} Default: ust",
|
||||
default=terraengineer_model.ASSETS[0],
|
||||
choices=terraengineer_model.ASSETS,
|
||||
)
|
||||
parser.add_argument(
|
||||
"--address",
|
||||
dest="address",
|
||||
type=check_terra_address_format,
|
||||
help="Terra address. Valid terra addresses start with 'terra'",
|
||||
required="-h" not in other_args,
|
||||
)
|
||||
|
||||
if other_args and not other_args[0][0] == "-":
|
||||
other_args.insert(0, "--asset")
|
||||
|
||||
ns_parser = self.parse_known_args_and_warn(
|
||||
parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED
|
||||
)
|
||||
|
||||
if ns_parser:
|
||||
terraengineer_view.display_terra_asset_history(
|
||||
export=ns_parser.export,
|
||||
address=ns_parser.address,
|
||||
asset=ns_parser.asset,
|
||||
)
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def call_ayr(self, other_args: List[str]):
|
||||
"""Process ayr command"""
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
prog="ayr",
|
||||
description="""
|
||||
Displays the 30-day history of the Anchor Yield Reserve.
|
||||
An increasing yield reserve indicates that the return on collateral staked by borrowers in Anchor
|
||||
is greater than the yield paid to depositors. A decreasing yield reserve means yield paid
|
||||
to depositors is outpacing the staking returns of borrower's collateral.
|
||||
TLDR: Shows the address that contains UST that is paid on anchor interest earn.
|
||||
[Source: https://terra.engineer/]
|
||||
""",
|
||||
)
|
||||
|
||||
ns_parser = self.parse_known_args_and_warn(
|
||||
parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED
|
||||
)
|
||||
|
||||
if ns_parser:
|
||||
terraengineer_view.display_anchor_yield_reserve(export=ns_parser.export)
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def call_sinfo(self, other_args: List[str]):
|
||||
parser = argparse.ArgumentParser(
|
||||
@@ -466,11 +400,11 @@ class DefiController(BaseController):
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--descend",
|
||||
action="store_false",
|
||||
help="Flag to sort in descending order (lowest first)",
|
||||
dest="descend",
|
||||
default=True,
|
||||
"--ascend",
|
||||
action="store_true",
|
||||
help="Flag to sort in ascending order (highest first)",
|
||||
dest="ascending",
|
||||
default=False,
|
||||
)
|
||||
|
||||
ns_parser = self.parse_known_args_and_warn(
|
||||
@@ -481,7 +415,7 @@ class DefiController(BaseController):
|
||||
defipulse_view.display_defipulse(
|
||||
top=ns_parser.limit,
|
||||
sortby=ns_parser.sortby,
|
||||
descend=ns_parser.descend,
|
||||
ascend=ns_parser.ascending,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
|
||||
@@ -720,7 +654,7 @@ class DefiController(BaseController):
|
||||
skip=ns_parser.skip,
|
||||
limit=ns_parser.limit,
|
||||
sortby=ns_parser.sortby,
|
||||
descend=ns_parser.descend,
|
||||
ascend=not ns_parser.descend,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
|
||||
@@ -1022,7 +956,7 @@ class DefiController(BaseController):
|
||||
protocol=ns_parser.protocol,
|
||||
top=ns_parser.limit,
|
||||
sortby=ns_parser.sortby,
|
||||
descend=ns_parser.descend,
|
||||
descend=not ns_parser.descend,
|
||||
link=ns_parser.link,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
|
||||
@@ -13,7 +13,7 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_defipulse_index() -> pd.DataFrame:
|
||||
def get_defipulse_index(sortby: str = "TVL", ascend: bool = False) -> pd.DataFrame:
|
||||
"""Scrapes data from DeFi Pulse with all DeFi Pulse crypto protocols.
|
||||
[Source: https://defipulse.com/]
|
||||
|
||||
@@ -48,5 +48,6 @@ def get_defipulse_index() -> pd.DataFrame:
|
||||
],
|
||||
)
|
||||
df["Rank"] = df.index
|
||||
df = df.sort_values(by=sortby, ascending=ascend)
|
||||
|
||||
return df
|
||||
|
||||
@@ -13,7 +13,7 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_defipulse(
|
||||
top: int = 10, sortby: str = "TVL", descend: bool = True, export: str = ""
|
||||
top: int = 10, sortby: str = "TVL", ascend: bool = False, export: str = ""
|
||||
) -> None:
|
||||
"""Displays all DeFi Pulse crypto protocols.
|
||||
[Source: https://defipulse.com/]
|
||||
@@ -25,16 +25,13 @@ def display_defipulse(
|
||||
sortby: str
|
||||
Key by which to sort data (Possible values are: "Rank", "Name", "Chain", "Sector",
|
||||
"TVL", "1 Day (%)"), by default TVL
|
||||
descend: bool
|
||||
Flag to sort data descending, by default True
|
||||
ascend: bool
|
||||
Flag to sort data ascending, by default False
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file, by default False
|
||||
"""
|
||||
|
||||
df = defipulse_model.get_defipulse_index()
|
||||
df_data = df.copy()
|
||||
|
||||
df = df.sort_values(by=sortby, ascending=descend)
|
||||
df = defipulse_model.get_defipulse_index(sortby, ascend)
|
||||
|
||||
print_rich_table(
|
||||
df.head(top),
|
||||
@@ -43,9 +40,4 @@ def display_defipulse(
|
||||
title="DeFi Pulse Crypto Protocols",
|
||||
)
|
||||
|
||||
export_data(
|
||||
export,
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"dpi",
|
||||
df_data,
|
||||
)
|
||||
export_data(export, os.path.dirname(os.path.abspath(__file__)), "dpi", df)
|
||||
|
||||
@@ -74,7 +74,9 @@ def query_graph(url: str, query: str) -> dict:
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_uni_tokens(skip: int = 0, limit: int = 100) -> pd.DataFrame:
|
||||
def get_uni_tokens(
|
||||
skip: int = 0, limit: int = 100, sortby: str = "index", ascend: bool = False
|
||||
) -> pd.DataFrame:
|
||||
"""Get list of tokens trade-able on Uniswap DEX. [Source: https://thegraph.com/en/]
|
||||
|
||||
Parameters
|
||||
@@ -83,6 +85,10 @@ def get_uni_tokens(skip: int = 0, limit: int = 100) -> pd.DataFrame:
|
||||
Skip n number of records.
|
||||
limit: int
|
||||
Show n number of records.
|
||||
sortby: str
|
||||
The column to sort by
|
||||
ascend: bool
|
||||
Whether to sort in ascending order
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -106,8 +112,8 @@ def get_uni_tokens(skip: int = 0, limit: int = 100) -> pd.DataFrame:
|
||||
data = query_graph(UNI_URL, query)
|
||||
if not data:
|
||||
return pd.DataFrame()
|
||||
|
||||
return pd.DataFrame(data["tokens"]).reset_index()
|
||||
df = pd.DataFrame(data["tokens"]).reset_index()
|
||||
return df.sort_values(by=sortby, ascending=ascend)
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
|
||||
@@ -19,7 +19,7 @@ def display_uni_tokens(
|
||||
skip: int = 0,
|
||||
limit: int = 20,
|
||||
sortby: str = "index",
|
||||
descend: bool = True,
|
||||
ascend: bool = False,
|
||||
export: str = "",
|
||||
) -> None:
|
||||
"""Displays tokens trade-able on Uniswap DEX.
|
||||
@@ -33,17 +33,15 @@ def display_uni_tokens(
|
||||
Number of records to display
|
||||
sortby: str
|
||||
Key by which to sort data
|
||||
descend: bool
|
||||
ascend: bool
|
||||
Flag to sort data descending
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
|
||||
df = graph_model.get_uni_tokens(skip=skip)
|
||||
df = graph_model.get_uni_tokens(skip=skip, sortby=sortby, ascend=ascend)
|
||||
df_data = df.copy()
|
||||
|
||||
df = df.sort_values(by=sortby, ascending=descend)
|
||||
|
||||
df[["totalLiquidity", "tradeVolumeUSD"]] = df[
|
||||
["totalLiquidity", "tradeVolumeUSD"]
|
||||
].applymap(lambda x: lambda_very_long_number_formatter(x))
|
||||
@@ -158,7 +156,7 @@ def display_recently_added(
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_uni_pools(
|
||||
top: int = 20, sortby: str = "volumeUSD", descend: bool = False, export: str = ""
|
||||
top: int = 20, sortby: str = "volumeUSD", ascend: bool = False, export: str = ""
|
||||
) -> None:
|
||||
"""Displays uniswap pools by volume.
|
||||
[Source: https://thegraph.com/en/]
|
||||
@@ -170,13 +168,13 @@ def display_uni_pools(
|
||||
sortby: str
|
||||
Key by which to sort data. The table can be sorted by every of its columns
|
||||
(see https://bit.ly/3ORagr1 then press ctrl-enter or execute the query).
|
||||
descend: bool
|
||||
ascend: bool
|
||||
Flag to sort data descending
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
|
||||
df = graph_model.get_uni_pools_by_volume().sort_values(by=sortby, ascending=descend)
|
||||
df = graph_model.get_uni_pools_by_volume().sort_values(by=sortby, ascending=ascend)
|
||||
df["volumeUSD"] = df["volumeUSD"].apply(
|
||||
lambda x: lambda_very_long_number_formatter(x)
|
||||
)
|
||||
|
||||
@@ -28,10 +28,15 @@ LLAMA_FILTERS = [
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_defi_protocols() -> pd.DataFrame:
|
||||
def get_defi_protocols(num: int = 100) -> pd.DataFrame:
|
||||
"""Returns information about listed DeFi protocols, their current TVL and changes to it in the last hour/day/week.
|
||||
[Source: https://docs.llama.fi/api]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
num: int
|
||||
The number of dApps to display
|
||||
|
||||
Returns
|
||||
-------
|
||||
pd.DataFrame
|
||||
@@ -63,12 +68,16 @@ def get_defi_protocols() -> pd.DataFrame:
|
||||
df["description"] = df["description"].apply(
|
||||
lambda x: "\n".join(textwrap.wrap(x, width=70)) if isinstance(x, str) else x
|
||||
)
|
||||
return df[columns]
|
||||
df = df[columns]
|
||||
|
||||
except Exception as e:
|
||||
logger.exception("Wrong response type: %s", str(e))
|
||||
raise ValueError("Wrong response type\n") from e
|
||||
|
||||
df = df.sort_values("tvl", ascending=False).head(num)
|
||||
df = df.set_index("name")
|
||||
return df
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_defi_protocol(protocol: str) -> pd.DataFrame:
|
||||
|
||||
@@ -43,10 +43,7 @@ def display_grouped_defi_protocols(
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
External axes (1 axis is expected in the list), by default None
|
||||
"""
|
||||
df = llama_model.get_defi_protocols()
|
||||
df = df.sort_values("tvl", ascending=False).head(num)
|
||||
|
||||
df = df.set_index("name")
|
||||
df = llama_model.get_defi_protocols(num)
|
||||
chains = df.groupby("chain").size().index.values.tolist()
|
||||
|
||||
# This plot has 1 axis
|
||||
@@ -97,10 +94,14 @@ def display_grouped_defi_protocols(
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_defi_protocols(
|
||||
top: int, sortby: str, descend: bool, description: bool, export: str = ""
|
||||
top: int,
|
||||
sortby: str,
|
||||
ascend: bool = False,
|
||||
description: bool = False,
|
||||
export: str = "",
|
||||
) -> None:
|
||||
"""Display information about listed DeFi protocols, their current TVL and changes to it in the last hour/day/week.
|
||||
[Source: https://docs.llama.fi/api]
|
||||
"""Display information about listed DeFi protocols, their current TVL and changes to it in
|
||||
the last hour/day/week. [Source: https://docs.llama.fi/api]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
@@ -108,7 +109,7 @@ def display_defi_protocols(
|
||||
Number of records to display
|
||||
sortby: str
|
||||
Key by which to sort data
|
||||
descend: bool
|
||||
ascend: bool
|
||||
Flag to sort data descending
|
||||
description: bool
|
||||
Flag to display description of protocol
|
||||
@@ -119,7 +120,7 @@ def display_defi_protocols(
|
||||
df = llama_model.get_defi_protocols()
|
||||
df_data = df.copy()
|
||||
|
||||
df = df.sort_values(by=sortby, ascending=descend)
|
||||
df = df.sort_values(by=sortby, ascending=ascend)
|
||||
df = df.drop(columns="chain")
|
||||
|
||||
df["tvl"] = df["tvl"].apply(lambda x: lambda_long_number_format(x))
|
||||
|
||||
@@ -9,17 +9,19 @@ from openbb_terminal import config_terminal as cfg
|
||||
from openbb_terminal.rich_config import console
|
||||
|
||||
|
||||
def get_luna_supply_stats(supply_type: str, days: int) -> pd.DataFrame:
|
||||
def get_luna_supply_stats(
|
||||
supply_type: str = "lunaSupplyChallengeStats", days: int = 30
|
||||
) -> pd.DataFrame:
|
||||
"""Get supply history of the Terra ecosystem
|
||||
|
||||
Source: [Smartstake.io]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
days: int
|
||||
Day count to fetch data
|
||||
supply_type: str
|
||||
Supply type to unpack json
|
||||
days: int
|
||||
Day count to fetch data
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
||||
@@ -24,15 +24,13 @@ from openbb_terminal.decorators import log_start_end
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
LUNA_CIR_SUPPLY_CHANGE = "lunaSupplyChallengeStats"
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
@check_api_key(["API_SMARTSTAKE_KEY", "API_SMARTSTAKE_TOKEN"])
|
||||
def display_luna_circ_supply_change(
|
||||
days: int,
|
||||
days: int = 30,
|
||||
export: str = "",
|
||||
supply_type: str = LUNA_CIR_SUPPLY_CHANGE,
|
||||
supply_type: str = "lunaSupplyChallengeStats",
|
||||
limit: int = 5,
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
|
||||
@@ -26,7 +26,6 @@ def display_newsletters(top: int = 10, export: str = "") -> None:
|
||||
"""
|
||||
|
||||
df = substack_model.get_newsletters()
|
||||
df_data = df.copy()
|
||||
|
||||
print_rich_table(
|
||||
df.head(top),
|
||||
@@ -35,9 +34,4 @@ def display_newsletters(top: int = 10, export: str = "") -> None:
|
||||
title="Substack Newsletters",
|
||||
)
|
||||
|
||||
export_data(
|
||||
export,
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"newsletter",
|
||||
df_data,
|
||||
)
|
||||
export_data(export, os.path.dirname(os.path.abspath(__file__)), "newsletter", df)
|
||||
|
||||
@@ -17,7 +17,7 @@ ASSETS = ["ust", "luna", "sdt"]
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_history_asset_from_terra_address(
|
||||
asset: str = "ust", address: str = ""
|
||||
asset: str = "ust", address: str = "terra1tmnqgvg567ypvsvk6rwsga3srp7e3lg6u0elp8"
|
||||
) -> pd.DataFrame:
|
||||
"""Returns historical data of an asset in a certain terra address
|
||||
[Source: https://terra.engineer/]
|
||||
@@ -49,7 +49,10 @@ def get_history_asset_from_terra_address(
|
||||
raise Exception(f"Status code: {response.status_code}. Reason: {response.text}")
|
||||
|
||||
data = response.json()
|
||||
df = pd.DataFrame(data[0]["data"])
|
||||
df["x"] = pd.to_datetime(df["x"])
|
||||
if data[0]["data"]:
|
||||
df = pd.DataFrame(data[0]["data"])
|
||||
df["x"] = pd.to_datetime(df["x"])
|
||||
else:
|
||||
df = pd.DataFrame()
|
||||
|
||||
return df
|
||||
|
||||
@@ -19,6 +19,7 @@ from openbb_terminal.helper_funcs import (
|
||||
plot_autoscale,
|
||||
is_valid_axes_count,
|
||||
)
|
||||
from openbb_terminal.rich_config import console
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -49,6 +50,8 @@ def display_terra_asset_history(
|
||||
df = terraengineer_model.get_history_asset_from_terra_address(
|
||||
address=address, asset=asset
|
||||
)
|
||||
if df.empty:
|
||||
console.print("[red]No data in the provided dataframe[/red]\n")
|
||||
|
||||
# This plot has 1 axis
|
||||
if not external_axes:
|
||||
@@ -96,6 +99,9 @@ def display_anchor_yield_reserve(
|
||||
df = terraengineer_model.get_history_asset_from_terra_address(
|
||||
address="terra1tmnqgvg567ypvsvk6rwsga3srp7e3lg6u0elp8"
|
||||
)
|
||||
if df.empty:
|
||||
console.print("[red]No data was found[/red]\n")
|
||||
return
|
||||
|
||||
# This plot has 1 axis
|
||||
if not external_axes:
|
||||
|
||||
@@ -144,9 +144,17 @@ def get_staking_account_info(address: str = "") -> Tuple[pd.DataFrame, str]:
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_validators() -> pd.DataFrame:
|
||||
def get_validators(sortby: str = "votingPower", ascend: bool = True) -> pd.DataFrame:
|
||||
"""Get information about terra validators [Source: https://fcd.terra.dev/swagger]
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
sortby: str
|
||||
Key by which to sort data. Choose from:
|
||||
validatorName, tokensAmount, votingPower, commissionRate, status, uptime
|
||||
ascend: bool
|
||||
Flag to sort data descending
|
||||
|
||||
Returns
|
||||
-------
|
||||
pd.DataFrame
|
||||
@@ -172,17 +180,28 @@ def get_validators() -> pd.DataFrame:
|
||||
}
|
||||
)
|
||||
|
||||
return pd.DataFrame(results).sort_values(by="votingPower")
|
||||
df = pd.DataFrame(results)
|
||||
if not df.empty:
|
||||
df = df.sort_values(by=sortby, ascending=ascend)
|
||||
return df
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_proposals(status: str = "") -> pd.DataFrame:
|
||||
def get_proposals(
|
||||
status: str = "", sortby: str = "id", ascend: bool = True, top: int = 10
|
||||
) -> pd.DataFrame:
|
||||
"""Get terra blockchain governance proposals list [Source: https://fcd.terra.dev/swagger]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
status: str
|
||||
status of proposal, one from list: ['Voting','Deposit','Passed','Rejected']
|
||||
sortby: str
|
||||
Key by which to sort data
|
||||
ascend: bool
|
||||
Flag to sort data ascending
|
||||
top: int
|
||||
Number of records to display
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -228,6 +247,8 @@ def get_proposals(status: str = "") -> pd.DataFrame:
|
||||
|
||||
if status.title() in statuses:
|
||||
df = df[df["status"] == status.title()]
|
||||
df = df.sort_values(by=sortby, ascending=ascend).head(top)
|
||||
df.columns = prettify_column_names(df.columns)
|
||||
return df
|
||||
|
||||
|
||||
@@ -255,9 +276,14 @@ def get_account_growth(cumulative: bool = True) -> pd.DataFrame:
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_staking_ratio_history():
|
||||
def get_staking_ratio_history(top: int = 200):
|
||||
"""Get terra blockchain staking ratio history [Source: https://fcd.terra.dev/swagger]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
top: int
|
||||
The number of ratios to show
|
||||
|
||||
Returns
|
||||
-------
|
||||
pd.DataFrame
|
||||
@@ -268,13 +294,21 @@ def get_staking_ratio_history():
|
||||
df = pd.DataFrame(response)
|
||||
df["date"] = df["datetime"].apply(lambda x: datetime.fromtimestamp(x / 1000).date())
|
||||
df["stakingRatio"] = df["stakingRatio"].apply(lambda x: round(float(x) * 100, 2))
|
||||
return df[["date", "stakingRatio"]]
|
||||
df = df[["date", "stakingRatio"]]
|
||||
df = df.sort_values("date", ascending=False).head(top)
|
||||
df = df.set_index("date")
|
||||
return df
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_staking_returns_history():
|
||||
def get_staking_returns_history(top: int = 200):
|
||||
"""Get terra blockchain staking returns history [Source: https://fcd.terra.dev/v1]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
top: int
|
||||
The number of returns to show
|
||||
|
||||
Returns
|
||||
-------
|
||||
pd.DataFrame
|
||||
@@ -287,4 +321,8 @@ def get_staking_returns_history():
|
||||
df["annualizedReturn"] = df["annualizedReturn"].apply(
|
||||
lambda x: round(float(x) * 100, 2)
|
||||
)
|
||||
return df[["date", "annualizedReturn"]]
|
||||
df = df[["date", "annualizedReturn"]]
|
||||
df = df.sort_values("date", ascending=False).head(top)
|
||||
df = df.set_index("date")
|
||||
|
||||
return df
|
||||
|
||||
@@ -59,7 +59,7 @@ def display_account_staking_info(
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_validators(
|
||||
top: int = 10, sortby: str = "votingPower", descend: bool = False, export: str = ""
|
||||
top: int = 10, sortby: str = "votingPower", ascend: bool = True, export: str = ""
|
||||
) -> None:
|
||||
"""Display information about terra validators [Source: https://fcd.terra.dev/swagger]
|
||||
|
||||
@@ -68,16 +68,16 @@ def display_validators(
|
||||
top: int
|
||||
Number of records to display
|
||||
sortby: str
|
||||
Key by which to sort data
|
||||
descend: bool
|
||||
Key by which to sort data. Choose from:
|
||||
validatorName, tokensAmount, votingPower, commissionRate, status, uptime
|
||||
ascend: bool
|
||||
Flag to sort data descending
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
|
||||
df = terramoney_fcd_model.get_validators()
|
||||
df = terramoney_fcd_model.get_validators(sortby, ascend)
|
||||
df_data = df.copy()
|
||||
df = df.sort_values(by=sortby, ascending=descend)
|
||||
df["tokensAmount"] = df["tokensAmount"].apply(
|
||||
lambda x: lambda_very_long_number_formatter(x)
|
||||
)
|
||||
@@ -106,7 +106,7 @@ def display_gov_proposals(
|
||||
top: int = 10,
|
||||
status: str = "all",
|
||||
sortby: str = "id",
|
||||
descend: bool = False,
|
||||
ascend: bool = True,
|
||||
export: str = "",
|
||||
) -> None:
|
||||
"""Display terra blockchain governance proposals list [Source: https://fcd.terra.dev/swagger]
|
||||
@@ -119,30 +119,17 @@ def display_gov_proposals(
|
||||
status of proposal, one from list: ['Voting','Deposit','Passed','Rejected']
|
||||
sortby: str
|
||||
Key by which to sort data
|
||||
descend: bool
|
||||
Flag to sort data descending
|
||||
ascend: bool
|
||||
Flag to sort data ascend
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
|
||||
df = terramoney_fcd_model.get_proposals(status)
|
||||
df_data = df.copy()
|
||||
df = df.sort_values(by=sortby, ascending=descend).head(top)
|
||||
df.columns = prettify_column_names(df.columns)
|
||||
df = terramoney_fcd_model.get_proposals(status, sortby, ascend, top)
|
||||
|
||||
print_rich_table(
|
||||
df,
|
||||
headers=list(df.columns),
|
||||
floatfmt=".2f",
|
||||
show_index=False,
|
||||
)
|
||||
print_rich_table(df, headers=list(df.columns), floatfmt=".2f", show_index=False)
|
||||
|
||||
export_data(
|
||||
export,
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"govp",
|
||||
df_data,
|
||||
)
|
||||
export_data(export, os.path.dirname(os.path.abspath(__file__)), "govp", df)
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
@@ -229,12 +216,9 @@ def display_staking_ratio_history(
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
External axes (1 axis is expected in the list), by default None
|
||||
|
||||
"""
|
||||
|
||||
df = terramoney_fcd_model.get_staking_ratio_history()
|
||||
df = df.sort_values("date", ascending=False).head(top)
|
||||
df = df.set_index("date")
|
||||
df = terramoney_fcd_model.get_staking_ratio_history(top)
|
||||
|
||||
start, end = df.index[-1], df.index[0]
|
||||
|
||||
@@ -289,10 +273,7 @@ def display_staking_returns_history(
|
||||
else:
|
||||
return
|
||||
|
||||
df = terramoney_fcd_model.get_staking_returns_history()
|
||||
|
||||
df = df.sort_values("date", ascending=False).head(top)
|
||||
df = df.set_index("date")
|
||||
df = terramoney_fcd_model.get_staking_returns_history(top)
|
||||
|
||||
start, end = df.index[-1], df.index[0]
|
||||
|
||||
|
||||
@@ -14,11 +14,28 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
FILTERS = ["Symbol", "CMC_Rank", "LastPrice", "DayPctChange", "MarketCap"]
|
||||
|
||||
sort_map = {
|
||||
"Symbol": "Symbol",
|
||||
"CMC_Rank": "CMC_Rank",
|
||||
"LastPrice": "Last Price",
|
||||
"DayPctChange": "1 Day Pct Change",
|
||||
"MarketCap": "Market Cap ($B)",
|
||||
}
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_cmc_top_n() -> pd.DataFrame:
|
||||
def get_cmc_top_n(sortby: str = "CMC_Rank", ascend: bool = True) -> pd.DataFrame:
|
||||
"""Shows top n coins. [Source: CoinMarketCap]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
sortby: str
|
||||
Key to sort data. The table can be sorted by every of its columns. Refer to
|
||||
Coin Market Cap:s API documentation, see:
|
||||
https://coinmarketcap.com/api/documentation/v1/#operation/getV1CryptocurrencyListingsLatest
|
||||
ascend: bool
|
||||
Whether to sort ascending or descending
|
||||
|
||||
Returns
|
||||
-------
|
||||
pd.DataFrame
|
||||
@@ -54,4 +71,5 @@ def get_cmc_top_n() -> pd.DataFrame:
|
||||
else:
|
||||
console.print(e)
|
||||
|
||||
df = df.sort_values(by=sort_map[sortby], ascending=ascend)
|
||||
return df
|
||||
|
||||
@@ -12,21 +12,13 @@ from openbb_terminal.rich_config import console
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
sort_map = {
|
||||
"Symbol": "Symbol",
|
||||
"CMC_Rank": "CMC_Rank",
|
||||
"LastPrice": "Last Price",
|
||||
"DayPctChange": "1 Day Pct Change",
|
||||
"MarketCap": "Market Cap ($B)",
|
||||
}
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
@check_api_key(["API_CMC_KEY"])
|
||||
def display_cmc_top_coins(
|
||||
top: int = 15,
|
||||
sortby: str = "CMC_Rank",
|
||||
descend: bool = False,
|
||||
ascend: bool = True,
|
||||
export: str = "",
|
||||
) -> None:
|
||||
"""Shows top n coins. [Source: CoinMarketCap]
|
||||
@@ -37,23 +29,21 @@ def display_cmc_top_coins(
|
||||
Number of records to display
|
||||
sortby: str
|
||||
Key to sort data. The table can be sorted by every of its columns. Refer to
|
||||
Coin Market Cap:s API documentation
|
||||
(see https://coinmarketcap.com/api/documentation/v1/#operation/getV1CryptocurrencyListingsLatest)
|
||||
descend: bool
|
||||
Flag to sort data descending
|
||||
Coin Market Cap:s API documentation, see:
|
||||
https://coinmarketcap.com/api/documentation/v1/#operation/getV1CryptocurrencyListingsLatest
|
||||
ascend: bool
|
||||
Flag to sort data ascending
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
|
||||
"""
|
||||
|
||||
df = coinmarketcap_model.get_cmc_top_n()
|
||||
df = coinmarketcap_model.get_cmc_top_n(sortby, ascend)
|
||||
|
||||
if df.empty:
|
||||
console.print("No Data Found\n")
|
||||
return
|
||||
|
||||
df = df.sort_values(by=sort_map[sortby], ascending=descend)
|
||||
|
||||
print_rich_table(
|
||||
df.iloc[:top, :], headers=list(df.columns), show_index=False, title="Top Coins"
|
||||
)
|
||||
|
||||
@@ -25,7 +25,11 @@ FILTERS = ["category", "id", "name"]
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_search_results(
|
||||
query: str, category: Optional[Any] = None, modifier: Optional[Any] = None
|
||||
query: str,
|
||||
category: Optional[Any] = None,
|
||||
modifier: Optional[Any] = None,
|
||||
sortby: str = "id",
|
||||
ascend: bool = True,
|
||||
) -> pd.DataFrame:
|
||||
"""Search CoinPaprika. [Source: CoinPaprika]
|
||||
|
||||
@@ -40,6 +44,11 @@ def get_search_results(
|
||||
modifier: Optional[Any]
|
||||
set modifier for search results. Available options: symbol_search -
|
||||
search only by symbol (works for currencies only)
|
||||
sortby: str
|
||||
Key to sort data. The table can be sorted by every of its columns. Refer to
|
||||
API documentation (see https://api.coinpaprika.com/docs#tag/Tools/paths/~1search/get)
|
||||
ascend: bool
|
||||
Flag to sort data descending
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -65,4 +74,6 @@ def get_search_results(
|
||||
"category": item,
|
||||
}
|
||||
)
|
||||
return pd.DataFrame(results)
|
||||
df = pd.DataFrame(results)
|
||||
df = df.sort_values(by=sortby, ascending=ascend)
|
||||
return df
|
||||
|
||||
@@ -18,7 +18,7 @@ def display_search_results(
|
||||
category: str = "all",
|
||||
top: int = 10,
|
||||
sortby: str = "id",
|
||||
descend: bool = False,
|
||||
ascend: bool = True,
|
||||
export: str = "",
|
||||
) -> None:
|
||||
"""Search over CoinPaprika. [Source: CoinPaprika]
|
||||
@@ -33,8 +33,8 @@ def display_search_results(
|
||||
Number of records to display
|
||||
sortby: str
|
||||
Key to sort data. The table can be sorted by every of its columns. Refer to
|
||||
CoinPaprikas API documentation (see https://api.coinpaprika.com/docs#tag/Tools/paths/~1search/get)
|
||||
descend: bool
|
||||
API documentation (see https://api.coinpaprika.com/docs#tag/Tools/paths/~1search/get)
|
||||
ascend: bool
|
||||
Flag to sort data descending
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
@@ -43,7 +43,9 @@ def display_search_results(
|
||||
if category.lower() == "all":
|
||||
category = "currencies,exchanges,icos,people,tags"
|
||||
|
||||
df = paprika.get_search_results(query=query, category=category)
|
||||
df = paprika.get_search_results(
|
||||
query=query, category=category, sortby=sortby, ascend=ascend
|
||||
)
|
||||
|
||||
if df.empty:
|
||||
console.print(
|
||||
@@ -51,8 +53,6 @@ def display_search_results(
|
||||
)
|
||||
return
|
||||
|
||||
df = df.sort_values(by=sortby, ascending=descend)
|
||||
|
||||
print_rich_table(
|
||||
df.head(top),
|
||||
headers=list(df.columns),
|
||||
|
||||
@@ -70,20 +70,23 @@ def _make_request(url: str) -> Optional[dict]:
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_top_nfts() -> pd.DataFrame:
|
||||
def get_top_nfts(sortby: str = "") -> pd.DataFrame:
|
||||
"""Get top nft collections [Source: https://dappradar.com/]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
sortby: str
|
||||
Key by which to sort data
|
||||
|
||||
Returns
|
||||
-------
|
||||
pd.DataFrame
|
||||
NFT collections. Columns: Name, Protocols, Floor Price [$], Avg Price [$], Market Cap [$], Volume [$]
|
||||
NFTs Columns: Name, Protocols, Floor Price [$], Avg Price [$], Market Cap [$], Volume [$]
|
||||
"""
|
||||
|
||||
response = _make_request(
|
||||
"https://nft-sales-service.dappradar.com/v2/collection/day?limit=20&page=1¤cy=USD&sort=marketCapInFiat&order=desc" # noqa
|
||||
"https://nft-sales-service.dappradar.com/v2/collection/day?limit=20&p"
|
||||
"age=1¤cy=USD&sort=marketCapInFiat&order=desc"
|
||||
)
|
||||
if response:
|
||||
data = response.get("results")
|
||||
@@ -106,15 +109,19 @@ def get_top_nfts() -> pd.DataFrame:
|
||||
)
|
||||
df["Protocols"] = df["Protocols"].apply(lambda x: ",".join(x))
|
||||
return df
|
||||
if sortby in NFT_COLUMNS:
|
||||
df = df.sort_values(by=sortby, ascending=False)
|
||||
return pd.DataFrame()
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_top_dexes() -> pd.DataFrame:
|
||||
def get_top_dexes(sortby: str = "") -> pd.DataFrame:
|
||||
"""Get top dexes by daily volume and users [Source: https://dappradar.com/]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
sortby: str
|
||||
Key by which to sort data
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -122,7 +129,9 @@ def get_top_dexes() -> pd.DataFrame:
|
||||
Top decentralized exchanges. Columns: Name, Daily Users, Daily Volume [$]
|
||||
"""
|
||||
data = _make_request(
|
||||
"https://dappradar.com/v2/api/dapps?params=WkdGd2NISmhaR0Z5Y0dGblpUMHhKbk5uY205MWNEMXRZWGdtWTNWeWNtVnVZM2s5VlZORUptWmxZWFIxY21Wa1BURW1jbUZ1WjJVOVpHRjVKbU5oZEdWbmIzSjVQV1Y0WTJoaGJtZGxjeVp6YjNKMFBYUnZkR0ZzVm05c2RXMWxTVzVHYVdGMEptOXlaR1Z5UFdSbGMyTW1iR2x0YVhROU1qWT0=" # noqa
|
||||
"https://dappradar.com/v2/api/dapps?params=WkdGd2NISmhaR0Z5Y0dGblpUMHhKbk5uY205MWNEMXR"
|
||||
"ZWGdtWTNWeWNtVnVZM2s5VlZORUptWmxZWFIxY21Wa1BURW1jbUZ1WjJVOVpHRjVKbU5oZEdWbmIzSjVQV1Y0WTJ"
|
||||
"oaGJtZGxjeVp6YjNKMFBYUnZkR0ZzVm05c2RXMWxTVzVHYVdGMEptOXlaR1Z5UFdSbGMyTW1iR2x0YVhROU1qWT0="
|
||||
)
|
||||
if data:
|
||||
arr = []
|
||||
@@ -135,6 +144,8 @@ def get_top_dexes() -> pd.DataFrame:
|
||||
]
|
||||
)
|
||||
df = pd.DataFrame(arr, columns=DEX_COLUMNS)
|
||||
if sortby in DEX_COLUMNS:
|
||||
df = df.sort_values(by=sortby, ascending=False)
|
||||
return df
|
||||
return pd.DataFrame()
|
||||
|
||||
@@ -152,7 +163,9 @@ def get_top_games() -> pd.DataFrame:
|
||||
Top blockchain games. Columns: Name, Daily Users, Daily Volume [$]
|
||||
"""
|
||||
data = _make_request(
|
||||
"https://dappradar.com/v2/api/dapps?params=WkdGd2NISmhaR0Z5Y0dGblpUMHhKbk5uY205MWNEMXRZWGdtWTNWeWNtVnVZM2s5VlZORUptWmxZWFIxY21Wa1BURW1jbUZ1WjJVOVpHRjVKbU5oZEdWbmIzSjVQV2RoYldWekpuTnZjblE5ZFhObGNpWnZjbVJsY2oxa1pYTmpKbXhwYldsMFBUSTI=" # noqa
|
||||
"https://dappradar.com/v2/api/dapps?params=WkdGd2NISmhaR0Z5Y0dGblpUMHhKbk5uY205MWNEMX"
|
||||
"RZWGdtWTNWeWNtVnVZM2s5VlZORUptWmxZWFIxY21Wa1BURW1jbUZ1WjJVOVpHRjVKbU5oZEdWbmIzSjVQV2R"
|
||||
"oYldWekpuTnZjblE5ZFhObGNpWnZjbVJsY2oxa1pYTmpKbXhwYldsMFBUSTI="
|
||||
)
|
||||
if data:
|
||||
arr = []
|
||||
@@ -173,19 +186,24 @@ def get_top_games() -> pd.DataFrame:
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_top_dapps() -> pd.DataFrame:
|
||||
def get_top_dapps(sortby: str = "") -> pd.DataFrame:
|
||||
"""Get top decentralized applications by daily volume and users [Source: https://dappradar.com/]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
sortby: str
|
||||
Key by which to sort data
|
||||
|
||||
Returns
|
||||
-------
|
||||
pd.DataFrame
|
||||
Top decentralized exchanges. Columns: Name, Category, Protocols, Daily Users, Daily Volume [$]
|
||||
Top decentralized exchanges.
|
||||
Columns: Name, Category, Protocols, Daily Users, Daily Volume [$]
|
||||
"""
|
||||
data = _make_request(
|
||||
"https://dappradar.com/v2/api/dapps?params=WkdGd2NISmhaR0Z5Y0dGblpUMHhKbk5uY205MWNEMXRZWGdtWTNWeWNtVnVZM2s5VlZORUptWmxZWFIxY21Wa1BURW1jbUZ1WjJVOVpHRjVKbk52Y25ROWRYTmxjaVp2Y21SbGNqMWtaWE5qSm14cGJXbDBQVEky" # noqa
|
||||
"https://dappradar.com/v2/api/dapps?params=WkdGd2NISmhaR0Z5Y0dGblpUMHhKbk5uY205MWNEMX"
|
||||
"RZWGdtWTNWeWNtVnVZM2s5VlZORUptWmxZWFIxY21Wa1BURW1jbUZ1WjJVOVpHRjVKbk52Y25ROWRYTmxjaVp"
|
||||
"2Y21SbGNqMWtaWE5qSm14cGJXbDBQVEky"
|
||||
)
|
||||
if data:
|
||||
arr = []
|
||||
@@ -204,5 +222,7 @@ def get_top_dapps() -> pd.DataFrame:
|
||||
columns=DAPPS_COLUMNS,
|
||||
).sort_values("Daily Users", ascending=False)
|
||||
df["Protocols"] = df["Protocols"].apply(lambda x: ",".join(x))
|
||||
if sortby in DAPPS_COLUMNS:
|
||||
df = df.sort_values(by=sortby, ascending=False)
|
||||
return df
|
||||
return pd.DataFrame()
|
||||
|
||||
@@ -30,33 +30,31 @@ def display_top_nfts(top: int = 10, sortby: str = "", export: str = "") -> None:
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
|
||||
df = dappradar_model.get_top_nfts()
|
||||
df = dappradar_model.get_top_nfts(sortby)
|
||||
if df.empty:
|
||||
console.print("Failed to fetch data from DappRadar\n")
|
||||
else:
|
||||
if sortby in dappradar_model.NFT_COLUMNS:
|
||||
df = df.sort_values(by=sortby, ascending=False)
|
||||
for col in ["Floor Price [$]", "Avg Price [$]", "Market Cap [$]", "Volume [$]"]:
|
||||
if col in df.columns:
|
||||
df[col] = (
|
||||
df[col]
|
||||
.fillna(-1)
|
||||
.apply(lambda x: lambda_very_long_number_formatter(x))
|
||||
.replace(-1, np.nan)
|
||||
)
|
||||
print_rich_table(
|
||||
df.head(top),
|
||||
headers=list(df.columns),
|
||||
show_index=False,
|
||||
title="Top NFT collections",
|
||||
)
|
||||
return
|
||||
for col in ["Floor Price [$]", "Avg Price [$]", "Market Cap [$]", "Volume [$]"]:
|
||||
if col in df.columns:
|
||||
df[col] = (
|
||||
df[col]
|
||||
.fillna(-1)
|
||||
.apply(lambda x: lambda_very_long_number_formatter(x))
|
||||
.replace(-1, np.nan)
|
||||
)
|
||||
print_rich_table(
|
||||
df.head(top),
|
||||
headers=list(df.columns),
|
||||
show_index=False,
|
||||
title="Top NFT collections",
|
||||
)
|
||||
|
||||
export_data(
|
||||
export,
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"drnft",
|
||||
df,
|
||||
)
|
||||
export_data(
|
||||
export,
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"drnft",
|
||||
df,
|
||||
)
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
@@ -111,12 +109,10 @@ def display_top_dexes(top: int = 10, export: str = "", sortby: str = "") -> None
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
|
||||
df = dappradar_model.get_top_dexes()
|
||||
df = dappradar_model.get_top_dexes(sortby)
|
||||
if df.empty:
|
||||
console.print("Failed to fetch data from DappRadar\n")
|
||||
return
|
||||
if sortby in dappradar_model.DEX_COLUMNS:
|
||||
df = df.sort_values(by=sortby, ascending=False)
|
||||
for col in ["Daily Users", "Daily Volume [$]"]:
|
||||
if col in df.columns:
|
||||
df[col] = df[col].apply(lambda x: lambda_very_long_number_formatter(x))
|
||||
@@ -149,12 +145,10 @@ def display_top_dapps(top: int = 10, export: str = "", sortby: str = "") -> None
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
|
||||
df = dappradar_model.get_top_dapps()
|
||||
df = dappradar_model.get_top_dapps(sortby)
|
||||
if df.empty:
|
||||
console.print("Failed to fetch data from DappRadar\n")
|
||||
return
|
||||
if sortby in dappradar_model.DAPPS_COLUMNS:
|
||||
df = df.sort_values(by=sortby, ascending=False)
|
||||
for col in ["Daily Users", "Daily Volume [$]"]:
|
||||
if col in df.columns:
|
||||
df[col] = df[col].apply(lambda x: lambda_very_long_number_formatter(x))
|
||||
|
||||
@@ -359,7 +359,7 @@ class DiscoveryController(BaseController):
|
||||
dest="sortby",
|
||||
nargs="+",
|
||||
help="Sort by given column. Default: Market Cap Rank",
|
||||
default=["Market Cap"],
|
||||
default=["market_cap"],
|
||||
)
|
||||
|
||||
ns_parser = self.parse_known_args_and_warn(
|
||||
@@ -493,7 +493,7 @@ class DiscoveryController(BaseController):
|
||||
coinmarketcap_view.display_cmc_top_coins(
|
||||
top=ns_parser.limit,
|
||||
sortby=ns_parser.sortby,
|
||||
descend=ns_parser.descend,
|
||||
descend=not ns_parser.descend,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
|
||||
|
||||
@@ -11,6 +11,16 @@ from openbb_terminal.decorators import log_start_end
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
COINS_COLUMNS = [
|
||||
"Symbol",
|
||||
"Name",
|
||||
"total_volume",
|
||||
"market_cap Cap",
|
||||
"market_cap Cap Rank",
|
||||
"7D Change [%]",
|
||||
"24H Change [%]",
|
||||
]
|
||||
|
||||
PERIODS = {
|
||||
"1h": "?time=h1",
|
||||
"24h": "?time=h24",
|
||||
@@ -99,7 +109,7 @@ def get_categories_keys() -> List[str]:
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_coins(top: int = 250, category: str = "") -> pd.DataFrame:
|
||||
def get_coins(top: int = 250, category: str = "", sortby="Symbol") -> pd.DataFrame:
|
||||
|
||||
"""Get N coins from CoinGecko [Source: CoinGecko]
|
||||
|
||||
@@ -107,6 +117,9 @@ def get_coins(top: int = 250, category: str = "") -> pd.DataFrame:
|
||||
----------
|
||||
top: int
|
||||
Number of top coins to grab from CoinGecko
|
||||
sortby: str
|
||||
Key to sort data
|
||||
|
||||
Returns
|
||||
-------
|
||||
pandas.DataFrame
|
||||
@@ -146,6 +159,9 @@ def get_coins(top: int = 250, category: str = "") -> pd.DataFrame:
|
||||
# df = df.append(pd.DataFrame(data), ignore_index=True)
|
||||
top -= 250
|
||||
p += 1
|
||||
if sortby in COINS_COLUMNS:
|
||||
df = df[(df["total_volume"].notna()) & (df["market_cap"].notna())]
|
||||
df = df.sort_values(by=sortby.lower(), ascending=False)
|
||||
return df.head(top)
|
||||
|
||||
|
||||
@@ -153,15 +169,18 @@ GAINERS_LOSERS_COLUMNS = [
|
||||
"Symbol",
|
||||
"Name",
|
||||
"Price [$]",
|
||||
"Market Cap",
|
||||
"Market Cap Rank",
|
||||
"Volume [$]",
|
||||
"market_cap",
|
||||
"market_cap_rank",
|
||||
"total_volume",
|
||||
]
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_gainers_or_losers(
|
||||
top: int = 20, period: str = "1h", typ: str = "gainers"
|
||||
top: int = 20,
|
||||
period: str = "1h",
|
||||
typ: str = "gainers",
|
||||
sortby: str = "market_cap",
|
||||
) -> pd.DataFrame:
|
||||
"""Returns data about top gainers - coins which gain the most in given period and
|
||||
top losers - coins that lost the most in given period of time. [Source: CoinGecko]
|
||||
@@ -170,6 +189,9 @@ def get_gainers_or_losers(
|
||||
----------
|
||||
top: int
|
||||
Num of coins to get
|
||||
sortby: str
|
||||
Key to sort data. The table can be sorted by every of its columns. Refer to
|
||||
API documentation (see /coins/markets in https://www.coingecko.com/en/api/documentation)
|
||||
period: str
|
||||
One from {14d,1h,1y,200d,24h,30d,7d}
|
||||
typ: str
|
||||
@@ -206,6 +228,9 @@ def get_gainers_or_losers(
|
||||
axis=1,
|
||||
inplace=False,
|
||||
)
|
||||
if sortby in COINS_COLUMNS:
|
||||
df = df[(df["total_volume"].notna()) & (df["market_cap"].notna())]
|
||||
df = df.sort_values(by=sortby, ascending=True)
|
||||
return sorted_df
|
||||
|
||||
|
||||
@@ -224,7 +249,7 @@ def get_trending_coins() -> pd.DataFrame:
|
||||
client = CoinGeckoAPI()
|
||||
data = client.get_search_trending()
|
||||
coins = data["coins"]
|
||||
df = pd.DataFrame(columns=["Symbol", "Name", "Market Cap Rank"])
|
||||
df = pd.DataFrame(columns=["Symbol", "Name", "market_cap Cap Rank"])
|
||||
for i, coin in enumerate(coins):
|
||||
coin = coin["item"]
|
||||
df.loc[i] = [coin["id"], coin["name"], coin["market_cap_rank"]]
|
||||
|
||||
@@ -18,7 +18,6 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
register_matplotlib_converters()
|
||||
|
||||
# pylint: disable=inconsistent-return-statements
|
||||
# pylint: disable=R0904, C0302
|
||||
|
||||
COINS_COLUMNS = [
|
||||
@@ -41,7 +40,7 @@ def display_coins(
|
||||
Parameters
|
||||
----------
|
||||
category: str
|
||||
Coingecko category. If no category is passed it will search for all coins. (E.g., smart-contract-platform)
|
||||
If no category is passed it will search for all coins. (E.g., smart-contract-platform)
|
||||
top: int
|
||||
Number of records to display
|
||||
sortby: str
|
||||
@@ -49,7 +48,7 @@ def display_coins(
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
df = pycoingecko_model.get_coins(top=top, category=category)
|
||||
df = pycoingecko_model.get_coins(top=top, category=category, sortby=sortby)
|
||||
if not df.empty:
|
||||
df = df[
|
||||
[
|
||||
@@ -67,10 +66,6 @@ def display_coins(
|
||||
axis=1,
|
||||
inplace=False,
|
||||
)
|
||||
if sortby in COINS_COLUMNS:
|
||||
df = df[
|
||||
(df["Volume [$]"].notna()) & (df["Market Cap"].notna())
|
||||
].sort_values(by=sortby, ascending=False)
|
||||
for col in ["Volume [$]", "Market Cap"]:
|
||||
if col in df.columns:
|
||||
df[col] = df[col].apply(lambda x: lambda_very_long_number_formatter(x))
|
||||
@@ -92,7 +87,7 @@ def display_coins(
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_gainers(
|
||||
period: str = "1h", top: int = 20, sortby: str = "Market Cap Rank", export: str = ""
|
||||
period: str = "1h", top: int = 20, sortby: str = "market_cap_rank", export: str = ""
|
||||
) -> None:
|
||||
"""Shows Largest Gainers - coins which gain the most in given period. [Source: CoinGecko]
|
||||
|
||||
@@ -104,18 +99,20 @@ def display_gainers(
|
||||
Number of records to display
|
||||
sortby: str
|
||||
Key to sort data. The table can be sorted by every of its columns. Refer to
|
||||
Coin Geckos API documentation (see /coins/markets part in https://www.coingecko.com/en/api/documentation)
|
||||
API documentation (see /coins/markets in https://www.coingecko.com/en/api/documentation)
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
|
||||
df = pycoingecko_model.get_gainers_or_losers(top=top, period=period, typ="gainers")
|
||||
df = pycoingecko_model.get_gainers_or_losers(
|
||||
top=top, period=period, typ="gainers", sortby=sortby
|
||||
)
|
||||
if not df.empty:
|
||||
if sortby in COINS_COLUMNS:
|
||||
df = df[
|
||||
(df["Volume [$]"].notna()) & (df["Market Cap"].notna())
|
||||
(df["total_volume"].notna()) & (df["market_cap"].notna())
|
||||
].sort_values(by=sortby, ascending=True)
|
||||
for col in ["Volume [$]", "Market Cap"]:
|
||||
for col in ["total_volume", "market_cap"]:
|
||||
if col in df.columns:
|
||||
df[col] = df[col].apply(lambda x: lambda_very_long_number_formatter(x))
|
||||
print_rich_table(
|
||||
@@ -148,17 +145,15 @@ def display_losers(
|
||||
Number of records to display
|
||||
sortby: str
|
||||
Key to sort data. The table can be sorted by every of its columns. Refer to
|
||||
Coin Geckos API documentation (see /coins/markets part in https://www.coingecko.com/en/api/documentation)
|
||||
API documentation (see /coins/markets in https://www.coingecko.com/en/api/documentation)
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
|
||||
df = pycoingecko_model.get_gainers_or_losers(top=top, period=period, typ="losers")
|
||||
df = pycoingecko_model.get_gainers_or_losers(
|
||||
top=top, period=period, typ="losers", sortby=sortby
|
||||
)
|
||||
if not df.empty:
|
||||
if sortby in COINS_COLUMNS:
|
||||
df = df[
|
||||
(df["Volume [$]"].notna()) & (df["Market Cap"].notna())
|
||||
].sort_values(by=sortby, ascending=True)
|
||||
for col in ["Volume [$]", "Market Cap"]:
|
||||
if col in df.columns:
|
||||
df[col] = df[col].apply(lambda x: lambda_very_long_number_formatter(x))
|
||||
|
||||
@@ -18,7 +18,7 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def _get_trading_pairs() -> List[dict]:
|
||||
"""Helper method that return all trading pairs on binance. Other methods are use this data as an input for e.g
|
||||
"""Helper method that return all trading pairs on binance. Methods ause this data for input for e.g
|
||||
building dataframe with all coins, or to build dict of all trading pairs. [Source: Binance]
|
||||
|
||||
Returns
|
||||
@@ -27,8 +27,8 @@ def _get_trading_pairs() -> List[dict]:
|
||||
list of dictionaries in format:
|
||||
[
|
||||
{'symbol': 'ETHBTC', 'status': 'TRADING', 'baseAsset': 'ETH', 'baseAssetPrecision': 8,
|
||||
'quoteAsset': 'BTC', 'quotePrecision': 8, 'quoteAssetPrecision': 8, 'baseCommissionPrecision': 8,
|
||||
'quoteCommissionPrecision': 8,
|
||||
'quoteAsset': 'BTC', 'quotePrecision': 8, 'quoteAssetPrecision': 8,
|
||||
'baseCommissionPrecision': 8, 'quoteCommissionPrecision': 8,
|
||||
'orderTypes': ['LIMIT', 'LIMIT_MAKER', 'MARKET', 'STOP_LOSS_LIMIT', 'TAKE_PROFIT_LIMIT'],
|
||||
'icebergAllowed': True,
|
||||
'ocoAllowed': True,
|
||||
|
||||
@@ -22,9 +22,9 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_order_book(
|
||||
coin: str,
|
||||
from_symbol: str,
|
||||
limit: int = 100,
|
||||
currency: str = "USDT",
|
||||
to_symbol: str = "USDT",
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
) -> None:
|
||||
@@ -33,11 +33,11 @@ def display_order_book(
|
||||
Parameters
|
||||
----------
|
||||
|
||||
coin: str
|
||||
from_symbol: str
|
||||
Cryptocurrency symbol
|
||||
limit: int
|
||||
Limit parameter. Adjusts the weight
|
||||
currency: str
|
||||
to_symbol: str
|
||||
Quote currency (what to view coin vs)
|
||||
export: str
|
||||
Export dataframe data to csv,json,xlsx
|
||||
@@ -45,7 +45,7 @@ def display_order_book(
|
||||
External axes (1 axis is expected in the list), by default None
|
||||
"""
|
||||
|
||||
pair = coin + currency
|
||||
pair = from_symbol + to_symbol
|
||||
|
||||
client = Client(cfg.API_BINANCE_KEY, cfg.API_BINANCE_SECRET)
|
||||
|
||||
@@ -55,7 +55,7 @@ def display_order_book(
|
||||
asks = np.asarray(market_book["asks"], dtype=float)
|
||||
bids = np.insert(bids, 2, bids[:, 1].cumsum(), axis=1)
|
||||
asks = np.insert(asks, 2, np.flipud(asks[:, 1]).cumsum(), axis=1)
|
||||
plot_order_book(bids, asks, coin, external_axes)
|
||||
plot_order_book(bids, asks, to_symbol, external_axes)
|
||||
|
||||
export_data(
|
||||
export,
|
||||
@@ -64,16 +64,20 @@ def display_order_book(
|
||||
pd.DataFrame(market_book),
|
||||
)
|
||||
except BinanceAPIException:
|
||||
console.print(f"{coin} is not a valid binance symbol")
|
||||
console.print(f"{to_symbol} is not a valid binance symbol")
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_balance(coin: str, currency: str = "USDT", export: str = "") -> None:
|
||||
def display_balance(
|
||||
from_symbol: str, to_symbol: str = "USDT", export: str = ""
|
||||
) -> None:
|
||||
"""Get account holdings for asset. [Source: Binance]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
coin: str
|
||||
from_symbol: str
|
||||
Cryptocurrency
|
||||
to_symbol: str
|
||||
Cryptocurrency
|
||||
currency: str
|
||||
Quote currency (what to view coin vs)
|
||||
@@ -83,20 +87,19 @@ def display_balance(coin: str, currency: str = "USDT", export: str = "") -> None
|
||||
|
||||
client = Client(cfg.API_BINANCE_KEY, cfg.API_BINANCE_SECRET)
|
||||
|
||||
pair = coin + currency
|
||||
pair = from_symbol + to_symbol
|
||||
current_balance = client.get_asset_balance(asset=pair)
|
||||
if current_balance is None:
|
||||
console.print("Check loaded coin")
|
||||
console.print("Check loaded coin\n")
|
||||
return
|
||||
|
||||
console.print("")
|
||||
amounts = [float(current_balance["free"]), float(current_balance["locked"])]
|
||||
total = np.sum(amounts)
|
||||
df = pd.DataFrame(amounts).apply(lambda x: str(float(x)))
|
||||
df.columns = ["Amount"]
|
||||
df.index = ["Free", "Locked"]
|
||||
df["Percent"] = df.div(df.sum(axis=0), axis=1).round(3)
|
||||
console.print(f"You currently have {total} coins and the breakdown is:")
|
||||
console.print(f"\nYou currently have {total} coins and the breakdown is:")
|
||||
|
||||
print_rich_table(
|
||||
df, headers=df.columns, show_index=True, title="Account Holdings for Assets"
|
||||
|
||||
@@ -4,6 +4,7 @@ __docformat__ = "numpy"
|
||||
from typing import Dict
|
||||
import ccxt
|
||||
import pandas as pd
|
||||
from openbb_terminal.cryptocurrency.dataframe_helpers import prettify_column_names
|
||||
|
||||
|
||||
def get_exchanges():
|
||||
@@ -21,7 +22,7 @@ def get_exchanges():
|
||||
return ccxt.exchanges
|
||||
|
||||
|
||||
def get_orderbook(exchange_id: str, coin: str, vs: str) -> Dict:
|
||||
def get_orderbook(exchange_id: str, symbol: str, vs: str) -> Dict:
|
||||
"""Returns orderbook for a coin in a given exchange
|
||||
[Source: https://docs.ccxt.com/en/latest/manual.html]
|
||||
|
||||
@@ -29,7 +30,7 @@ def get_orderbook(exchange_id: str, coin: str, vs: str) -> Dict:
|
||||
----------
|
||||
exchange_id : str
|
||||
exchange id
|
||||
coin : str
|
||||
symbol : str
|
||||
coin symbol
|
||||
vs : str
|
||||
currency to compare coin against
|
||||
@@ -40,11 +41,11 @@ def get_orderbook(exchange_id: str, coin: str, vs: str) -> Dict:
|
||||
"""
|
||||
exchange_class = getattr(ccxt, exchange_id)
|
||||
exchange = exchange_class()
|
||||
ob = exchange.fetch_order_book(f"{coin.upper()}/{vs.upper()}")
|
||||
ob = exchange.fetch_order_book(f"{symbol.upper()}/{vs.upper()}")
|
||||
return ob
|
||||
|
||||
|
||||
def get_trades(exchange_id: str, coin: str, vs: str) -> pd.DataFrame:
|
||||
def get_trades(exchange_id: str, symbol: str, vs: str) -> pd.DataFrame:
|
||||
"""Returns trades for a coin in a given exchange
|
||||
[Source: https://docs.ccxt.com/en/latest/manual.html]
|
||||
|
||||
@@ -52,7 +53,7 @@ def get_trades(exchange_id: str, coin: str, vs: str) -> pd.DataFrame:
|
||||
----------
|
||||
exchange_id : str
|
||||
exchange id
|
||||
coin : str
|
||||
symbol : str
|
||||
coin symbol
|
||||
vs : str
|
||||
currency to compare coin against
|
||||
@@ -64,7 +65,9 @@ def get_trades(exchange_id: str, coin: str, vs: str) -> pd.DataFrame:
|
||||
"""
|
||||
exchange_class = getattr(ccxt, exchange_id)
|
||||
exchange = exchange_class()
|
||||
trades = exchange.fetch_trades(f"{coin.upper()}/{vs.upper()}")
|
||||
trades = exchange.fetch_trades(f"{symbol.upper()}/{vs.upper()}")
|
||||
df = pd.DataFrame(trades, columns=["datetime", "price", "amount", "cost", "side"])
|
||||
df["datetime"] = pd.to_datetime(df["datetime"])
|
||||
df.rename(columns={"datetime": "date"}, inplace=True)
|
||||
df.columns = prettify_column_names(df.columns)
|
||||
return df
|
||||
|
||||
@@ -7,14 +7,13 @@ from typing import List, Optional
|
||||
from matplotlib import pyplot as plt
|
||||
import numpy as np
|
||||
from openbb_terminal.cryptocurrency.cryptocurrency_helpers import plot_order_book
|
||||
from openbb_terminal.cryptocurrency.dataframe_helpers import prettify_column_names
|
||||
from openbb_terminal.cryptocurrency.due_diligence import ccxt_model
|
||||
from openbb_terminal.helper_funcs import export_data, print_rich_table
|
||||
|
||||
|
||||
def display_order_book(
|
||||
exchange: str,
|
||||
coin: str,
|
||||
symbol: str,
|
||||
vs: str,
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
@@ -26,20 +25,20 @@ def display_order_book(
|
||||
----------
|
||||
exchange : str
|
||||
exchange id
|
||||
coin : str
|
||||
symbol : str
|
||||
coin symbol
|
||||
vs : str
|
||||
currency to compare coin against
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
market_book = ccxt_model.get_orderbook(exchange_id=exchange, coin=coin, vs=vs)
|
||||
market_book = ccxt_model.get_orderbook(exchange_id=exchange, symbol=symbol, vs=vs)
|
||||
bids = np.asarray(market_book["bids"], dtype=float)
|
||||
asks = np.asarray(market_book["asks"], dtype=float)
|
||||
bids = np.insert(bids, 2, bids[:, 1].cumsum(), axis=1)
|
||||
asks = np.insert(asks, 2, np.flipud(asks[:, 1]).cumsum(), axis=1)
|
||||
plot_order_book(
|
||||
bids, asks, f"{exchange.upper()}:{coin.upper()}/{vs.upper()}", external_axes
|
||||
bids, asks, f"{exchange.upper()}:{symbol.upper()}/{vs.upper()}", external_axes
|
||||
)
|
||||
|
||||
export_data(
|
||||
@@ -50,7 +49,9 @@ def display_order_book(
|
||||
)
|
||||
|
||||
|
||||
def display_trades(exchange: str, coin: str, vs: str, top: int = 10, export: str = ""):
|
||||
def display_trades(
|
||||
exchange: str, symbol: str, vs: str, limit: int = 10, export: str = ""
|
||||
):
|
||||
"""Displays trades for a coin in a given exchange
|
||||
[Source: https://docs.ccxt.com/en/latest/manual.html]
|
||||
|
||||
@@ -58,24 +59,21 @@ def display_trades(exchange: str, coin: str, vs: str, top: int = 10, export: str
|
||||
----------
|
||||
exchange : str
|
||||
exchange id
|
||||
coin : str
|
||||
symbol : str
|
||||
coin symbol
|
||||
vs : str
|
||||
currency to compare coin against
|
||||
top : int
|
||||
limit : int
|
||||
number of trades to display
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
df = ccxt_model.get_trades(exchange_id=exchange, coin=coin, vs=vs)
|
||||
df.rename(columns={"datetime": "date"}, inplace=True)
|
||||
|
||||
df.columns = prettify_column_names(df.columns)
|
||||
df = ccxt_model.get_trades(exchange_id=exchange, symbol=symbol, vs=vs)
|
||||
print_rich_table(
|
||||
df.head(top),
|
||||
df.head(limit),
|
||||
headers=list(df.columns),
|
||||
show_index=False,
|
||||
title=f"Trades for {exchange.upper()}:{coin.upper()}/{vs.upper()}",
|
||||
title=f"Trades for {exchange.upper()}:{symbol.upper()}/{vs.upper()}",
|
||||
)
|
||||
|
||||
export_data(
|
||||
|
||||
@@ -33,12 +33,12 @@ def show_available_pairs_for_given_symbol(symbol: str = "ETH") -> Tuple[str, lis
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_trading_pair_info(product_id: str) -> pd.DataFrame:
|
||||
def get_trading_pair_info(symbol: str) -> pd.DataFrame:
|
||||
"""Get information about chosen trading pair. [Source: Coinbase]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
product_id: str
|
||||
symbol: str
|
||||
Trading pair of coins on Coinbase e.g ETH-USDT or UNI-ETH
|
||||
|
||||
Returns
|
||||
@@ -47,7 +47,7 @@ def get_trading_pair_info(product_id: str) -> pd.DataFrame:
|
||||
Basic information about given trading pair
|
||||
"""
|
||||
|
||||
product_id = check_validity_of_product(product_id)
|
||||
product_id = check_validity_of_product(symbol)
|
||||
pair = make_coinbase_request(f"/products/{product_id}")
|
||||
df = pd.Series(pair).to_frame().reset_index()
|
||||
df.columns = ["Metric", "Value"]
|
||||
@@ -56,12 +56,12 @@ def get_trading_pair_info(product_id: str) -> pd.DataFrame:
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_order_book(product_id: str) -> Tuple[np.ndarray, np.ndarray, str, dict]:
|
||||
def get_order_book(symbol: str) -> Tuple[np.ndarray, np.ndarray, str, dict]:
|
||||
"""Get orders book for chosen trading pair. [Source: Coinbase]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
product_id: str
|
||||
symbol: str
|
||||
Trading pair of coins on Coinbase e.g ETH-USDT or UNI-ETH
|
||||
|
||||
Returns
|
||||
@@ -73,10 +73,10 @@ def get_order_book(product_id: str) -> Tuple[np.ndarray, np.ndarray, str, dict]:
|
||||
dict with raw data
|
||||
"""
|
||||
|
||||
# TODO: Order with price much higher then current price. E.g current price 200 USD, sell order with 10000 USD
|
||||
# TODO: Order price > current price. E.g current price 200 USD, sell order with 10000 USD
|
||||
# makes chart look very ugly (bad scaling). Think about removing outliers or add log scale ?
|
||||
|
||||
product_id = check_validity_of_product(product_id)
|
||||
product_id = check_validity_of_product(symbol)
|
||||
market_book = make_coinbase_request(f"/products/{product_id}/book?level=2")
|
||||
|
||||
size = min(
|
||||
@@ -99,13 +99,13 @@ def get_order_book(product_id: str) -> Tuple[np.ndarray, np.ndarray, str, dict]:
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_trades(
|
||||
product_id: str, limit: int = 1000, side: Optional[Any] = None
|
||||
symbol: str, limit: int = 1000, side: Optional[Any] = None
|
||||
) -> pd.DataFrame:
|
||||
"""Get last N trades for chosen trading pair. [Source: Coinbase]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
product_id: str
|
||||
symbol: str
|
||||
Trading pair of coins on Coinbase e.g ETH-USDT or UNI-ETH
|
||||
limit: int
|
||||
Last <limit> of trades. Maximum is 1000.
|
||||
@@ -121,18 +121,18 @@ def get_trades(
|
||||
if side is not None and side in ["buy", "sell"]:
|
||||
params["side"] = side
|
||||
|
||||
product_id = check_validity_of_product(product_id)
|
||||
product_id = check_validity_of_product(symbol)
|
||||
product = make_coinbase_request(f"/products/{product_id}/trades", params=params)
|
||||
return pd.DataFrame(product)[["time", "price", "size", "side"]]
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_candles(product_id: str, interval: str = "24h") -> pd.DataFrame:
|
||||
def get_candles(symbol: str, interval: str = "24h") -> pd.DataFrame:
|
||||
"""Get candles for chosen trading pair and time interval. [Source: Coinbase]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
product_id: str
|
||||
symbol: str
|
||||
Trading pair of coins on Coinbase e.g ETH-USDT or UNI-ETH
|
||||
interval: str
|
||||
Time interval. One from 1min, 5min ,15min, 1hour, 6hour, 24hour
|
||||
@@ -160,7 +160,7 @@ def get_candles(product_id: str, interval: str = "24h") -> pd.DataFrame:
|
||||
|
||||
granularity: int = interval_map[interval]
|
||||
|
||||
product_id = check_validity_of_product(product_id)
|
||||
product_id = check_validity_of_product(symbol)
|
||||
candles = make_coinbase_request(
|
||||
f"/products/{product_id}/candles", params={"granularity": granularity}
|
||||
)
|
||||
@@ -186,13 +186,13 @@ def get_candles(product_id: str, interval: str = "24h") -> pd.DataFrame:
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_product_stats(product_id: str) -> pd.DataFrame:
|
||||
def get_product_stats(symbol: str) -> pd.DataFrame:
|
||||
"""Get 24 hr stats for the product. Volume is in base currency units.
|
||||
Open, high and low are in quote currency units. [Source: Coinbase]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
product_id: str
|
||||
symbol: str
|
||||
Trading pair of coins on Coinbase e.g ETH-USDT or UNI-ETH
|
||||
|
||||
Returns
|
||||
@@ -201,7 +201,7 @@ def get_product_stats(product_id: str) -> pd.DataFrame:
|
||||
24h stats for chosen trading pair
|
||||
"""
|
||||
|
||||
product_id = check_validity_of_product(product_id)
|
||||
product_id = check_validity_of_product(symbol)
|
||||
product = make_coinbase_request(f"/products/{product_id}/stats")
|
||||
df = pd.Series(product).reset_index()
|
||||
df.columns = ["Metric", "Value"]
|
||||
|
||||
@@ -21,7 +21,7 @@ register_matplotlib_converters()
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_order_book(
|
||||
product_id: str,
|
||||
symbol: str,
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
) -> None:
|
||||
@@ -29,14 +29,14 @@ def display_order_book(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
product_id: str
|
||||
symbol: str
|
||||
Trading pair of coins on Coinbase e.g ETH-USDT or UNI-ETH
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
External axes (1 axis is expected in the list), by default None
|
||||
"""
|
||||
bids, asks, pair, market_book = coinbase_model.get_order_book(product_id)
|
||||
bids, asks, pair, market_book = coinbase_model.get_order_book(symbol)
|
||||
plot_order_book(bids, asks, pair, external_axes)
|
||||
|
||||
export_data(
|
||||
@@ -49,13 +49,13 @@ def display_order_book(
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_trades(
|
||||
product_id: str, limit: int = 20, side: Optional[str] = None, export: str = ""
|
||||
symbol: str, limit: int = 20, side: Optional[str] = None, export: str = ""
|
||||
) -> None:
|
||||
"""Display last N trades for chosen trading pair. [Source: Coinbase]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
product_id: str
|
||||
symbol: str
|
||||
Trading pair of coins on Coinbase e.g ETH-USDT or UNI-ETH
|
||||
limit: int
|
||||
Last <limit> of trades. Maximum is 1000.
|
||||
@@ -65,30 +65,20 @@ def display_trades(
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
|
||||
df = coinbase_model.get_trades(product_id, limit, side)
|
||||
df_data = df.copy()
|
||||
df = coinbase_model.get_trades(symbol, limit, side)
|
||||
|
||||
print_rich_table(
|
||||
df,
|
||||
headers=list(df.columns),
|
||||
show_index=False,
|
||||
)
|
||||
print_rich_table(df, headers=list(df.columns), show_index=False)
|
||||
|
||||
export_data(
|
||||
export,
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"trades",
|
||||
df_data,
|
||||
)
|
||||
export_data(export, os.path.dirname(os.path.abspath(__file__)), "trades", df)
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_candles(product_id: str, interval: str = "24h", export: str = "") -> None:
|
||||
def display_candles(symbol: str, interval: str = "24h", export: str = "") -> None:
|
||||
"""Get candles for chosen trading pair and time interval. [Source: Coinbase]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
product_id: str
|
||||
symbol: str
|
||||
Trading pair of coins on Coinbase e.g ETH-USDT or UNI-ETH
|
||||
interval: str
|
||||
Time interval. One from 1m, 5m ,15m, 1h, 6h, 24h
|
||||
@@ -96,44 +86,32 @@ def display_candles(product_id: str, interval: str = "24h", export: str = "") ->
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
|
||||
df = coinbase_model.get_candles(product_id, interval)
|
||||
df_data = df.copy()
|
||||
df = coinbase_model.get_candles(symbol, interval)
|
||||
|
||||
print_rich_table(
|
||||
df, headers=list(df.columns), show_index=True, title="Trading Pair Candles"
|
||||
)
|
||||
|
||||
export_data(
|
||||
export,
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"candles",
|
||||
df_data,
|
||||
)
|
||||
export_data(export, os.path.dirname(os.path.abspath(__file__)), "candles", df)
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_stats(product_id: str, export: str = "") -> None:
|
||||
def display_stats(symbol: str, export: str = "") -> None:
|
||||
"""Get 24 hr stats for the product. Volume is in base currency units.
|
||||
Open, high and low are in quote currency units. [Source: Coinbase]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
product_id: str
|
||||
symbol: str
|
||||
Trading pair of coins on Coinbase e.g ETH-USDT or UNI-ETH
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
|
||||
df = coinbase_model.get_product_stats(product_id)
|
||||
df_data = df.copy()
|
||||
df = coinbase_model.get_product_stats(symbol)
|
||||
|
||||
print_rich_table(
|
||||
df, headers=list(df.columns), show_index=False, title="24 hr Product Stats"
|
||||
)
|
||||
|
||||
export_data(
|
||||
export,
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"stats",
|
||||
df_data,
|
||||
)
|
||||
export_data(export, os.path.dirname(os.path.abspath(__file__)), "stats", df)
|
||||
|
||||
@@ -79,7 +79,7 @@ def get_funding_rate(symbol: str) -> pd.DataFrame:
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_open_interest_per_exchange(symbol: str, interval: int) -> pd.DataFrame:
|
||||
def get_open_interest_per_exchange(symbol: str, interval: int = 0) -> pd.DataFrame:
|
||||
"""Returns open interest by exchange for a certain symbol
|
||||
[Source: https://coinglass.github.io/API-Reference/]
|
||||
|
||||
@@ -88,7 +88,7 @@ def get_open_interest_per_exchange(symbol: str, interval: int) -> pd.DataFrame:
|
||||
symbol : str
|
||||
Crypto Symbol to search open interest futures (e.g., BTC)
|
||||
interval : int
|
||||
Interval frequency (e.g., 0)
|
||||
Frequency (possible values are: 0 for ALL, 2 for 1H, 1 for 4H, 4 for 12H), by default 0
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
||||
@@ -63,7 +63,7 @@ def display_open_interest(symbol: str, interval: int = 0, export: str = "") -> N
|
||||
symbol : str
|
||||
Crypto symbol to search open interest (e.g., BTC)
|
||||
interval : int
|
||||
Interval frequency (possible values are: 0 for ALL, 2 for 1H, 1 for 4H, 4 for 12H), by default 0
|
||||
Frequency (possible values are: 0 for ALL, 2 for 1H, 1 for 4H, 4 for 12H), by default 0
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file"""
|
||||
df = get_open_interest_per_exchange(symbol, interval)
|
||||
@@ -89,9 +89,9 @@ def display_open_interest(symbol: str, interval: int = 0, export: str = "") -> N
|
||||
@log_start_end(log=logger)
|
||||
def plot_data(
|
||||
df: pd.DataFrame,
|
||||
symbol: str,
|
||||
title: str,
|
||||
ylabel: str,
|
||||
symbol: str = "",
|
||||
title: str = "",
|
||||
ylabel: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
|
||||
@@ -119,12 +119,15 @@ def plot_data(
|
||||
ticker.FuncFormatter(lambda x, _: lambda_long_number_format(x))
|
||||
)
|
||||
ax1.legend(df_without_price.columns, fontsize="x-small", ncol=2)
|
||||
ax1.set_title(title)
|
||||
ax1.set_ylabel(ylabel)
|
||||
if title:
|
||||
ax1.set_title(title)
|
||||
if ylabel:
|
||||
ax1.set_ylabel(ylabel)
|
||||
|
||||
ax2.plot(df_price.index, df_price)
|
||||
ax2.legend([f"{symbol} price"])
|
||||
ax2.set_ylabel(f"{symbol} Price [$]")
|
||||
if symbol:
|
||||
ax2.legend([f"{symbol} price"])
|
||||
ax2.set_ylabel(f"{symbol} Price [$]")
|
||||
ax2.set_xlim([df_price.index[0], df_price.index[-1]])
|
||||
ax2.set_ylim(bottom=0.0)
|
||||
|
||||
|
||||
@@ -17,12 +17,12 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_coin(coin_id: str = "eth-ethereum") -> dict:
|
||||
def get_coin(symbol: str = "eth-ethereum") -> dict:
|
||||
"""Get coin by id [Source: CoinPaprika]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
coin_id: str
|
||||
symbol: str
|
||||
id of coin from coinpaprika e.g. Ethereum - > 'eth-ethereum'
|
||||
Returns
|
||||
-------
|
||||
@@ -31,18 +31,26 @@ def get_coin(coin_id: str = "eth-ethereum") -> dict:
|
||||
"""
|
||||
|
||||
session = PaprikaSession()
|
||||
coin = session.make_request(session.ENDPOINTS["coin"].format(coin_id))
|
||||
coin = session.make_request(session.ENDPOINTS["coin"].format(symbol))
|
||||
return coin
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_coin_twitter_timeline(coin_id: str = "eth-ethereum") -> pd.DataFrame:
|
||||
def get_coin_twitter_timeline(
|
||||
symbol: str = "eth-ethereum", sortby: str = "date", ascend: bool = True
|
||||
) -> pd.DataFrame:
|
||||
"""Get twitter timeline for given coin id. Not more than last 50 tweets [Source: CoinPaprika]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
coin_id: str
|
||||
symbol: str
|
||||
id of coin from coinpaprika e.g. Ethereum - > 'eth-ethereum'
|
||||
sortby: str
|
||||
Key by which to sort data. Every column name is valid
|
||||
(see for possible values:
|
||||
https://api.coinpaprika.com/docs#tag/Coins/paths/~1coins~1%7Bcoin_id%7D~1twitter/get).
|
||||
ascend: bool
|
||||
Flag to sort data descending
|
||||
Returns
|
||||
-------
|
||||
pandas.DataFrame
|
||||
@@ -51,7 +59,7 @@ def get_coin_twitter_timeline(coin_id: str = "eth-ethereum") -> pd.DataFrame:
|
||||
"""
|
||||
|
||||
session = PaprikaSession()
|
||||
res = session.make_request(session.ENDPOINTS["coin_tweeter"].format(coin_id))
|
||||
res = session.make_request(session.ENDPOINTS["coin_tweeter"].format(symbol))
|
||||
if "error" in res:
|
||||
console.print(res)
|
||||
return pd.DataFrame()
|
||||
@@ -67,34 +75,46 @@ def get_coin_twitter_timeline(coin_id: str = "eth-ethereum") -> pd.DataFrame:
|
||||
df["status"] = df["status"].apply(lambda x: x.replace(" ", ""))
|
||||
df["date"] = df["date"].apply(lambda x: x.replace("T", "\n"))
|
||||
df["date"] = df["date"].apply(lambda x: x.replace("Z", ""))
|
||||
df = df.sort_values(by=sortby, ascending=ascend)
|
||||
# Remove unicode chars (it breaks pretty tables)
|
||||
df["status"] = df["status"].apply(
|
||||
lambda text: "".join(i if ord(i) < 128 else "" for i in text)
|
||||
)
|
||||
return df
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_coin_events_by_id(coin_id: str = "eth-ethereum") -> pd.DataFrame:
|
||||
"""Get all events related to given coin like conferences, start date of futures trading etc. [Source: CoinPaprika]
|
||||
def get_coin_events_by_id(
|
||||
symbol: str = "eth-ethereum", sortby="date", ascend: bool = False
|
||||
) -> pd.DataFrame:
|
||||
"""Get all events related to given coin like conferences, start date of futures trading etc.
|
||||
[Source: CoinPaprika]
|
||||
|
||||
Example of response from API:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"id": "17398-cme-april-first-trade",
|
||||
"date": "2018-04-02T00:00:00Z",
|
||||
"date_to": "string",
|
||||
"name": "CME: April First Trade",
|
||||
"description": "First trade of Bitcoin futures contract for April 2018.",
|
||||
"is_conference": false,
|
||||
"link": "http://www.cmegroup.com/trading/equity-index/us-index/bitcoin_product_calendar_futures.html",
|
||||
"proof_image_link": "https://static.coinpaprika.com/storage/cdn/event_images/16635.jpg"
|
||||
}
|
||||
|
||||
.
|
||||
{
|
||||
"id": "17398-cme-april-first-trade",
|
||||
"date": "2018-04-02T00:00:00Z",
|
||||
"date_to": "string",
|
||||
"name": "CME: April First Trade",
|
||||
"description": "First trade of Bitcoin futures contract for April 2018.",
|
||||
"is_conference": false,
|
||||
"link": "http://www.cmegroup.com/trading/equity-index/us-index/bitcoin_product_calendar_futures.html",
|
||||
"proof_image_link": "https://static.coinpaprika.com/storage/cdn/event_images/16635.jpg"
|
||||
}
|
||||
|
||||
Parameters
|
||||
----------
|
||||
coin_id: str
|
||||
symbol: str
|
||||
id of coin from coinpaprika e.g. Ethereum - > 'eth-ethereum'
|
||||
sortby: str
|
||||
Key by which to sort data. Every column name is valid
|
||||
(see for possible values:
|
||||
https://api.coinpaprika.com/docs#tag/Coins/paths/~1coins~1%7Bcoin_id%7D~1events/get).
|
||||
ascend: bool
|
||||
Flag to sort data ascending
|
||||
Returns
|
||||
-------
|
||||
pandas.DataFrame
|
||||
@@ -103,7 +123,7 @@ def get_coin_events_by_id(coin_id: str = "eth-ethereum") -> pd.DataFrame:
|
||||
"""
|
||||
|
||||
session = PaprikaSession()
|
||||
res = session.make_request(session.ENDPOINTS["coin_events"].format(coin_id))
|
||||
res = session.make_request(session.ENDPOINTS["coin_events"].format(symbol))
|
||||
if not res or "error" in res:
|
||||
return pd.DataFrame()
|
||||
data = pd.DataFrame(res)
|
||||
@@ -118,17 +138,28 @@ def get_coin_events_by_id(coin_id: str = "eth-ethereum") -> pd.DataFrame:
|
||||
data[col] = data[col].apply(
|
||||
lambda x: x.replace("Z", "") if isinstance(x, str) else x
|
||||
)
|
||||
data = data.sort_values(by=sortby, ascending=ascend)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_coin_exchanges_by_id(coin_id: str = "eth-ethereum") -> pd.DataFrame:
|
||||
def get_coin_exchanges_by_id(
|
||||
symbol: str = "eth-ethereum",
|
||||
sortby: str = "adjusted_volume_24h_share",
|
||||
ascend: bool = True,
|
||||
) -> pd.DataFrame:
|
||||
"""Get all exchanges for given coin id. [Source: CoinPaprika]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
coin_id: str
|
||||
symbol: str
|
||||
Identifier of Coin from CoinPaprika
|
||||
sortby: str
|
||||
Key by which to sort data. Every column name is valid (see for possible values:
|
||||
https://api.coinpaprika.com/v1).
|
||||
ascend: bool
|
||||
Flag to sort data ascending
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -138,32 +169,42 @@ def get_coin_exchanges_by_id(coin_id: str = "eth-ethereum") -> pd.DataFrame:
|
||||
"""
|
||||
|
||||
session = PaprikaSession()
|
||||
res = session.make_request(session.ENDPOINTS["coin_exchanges"].format(coin_id))
|
||||
res = session.make_request(session.ENDPOINTS["coin_exchanges"].format(symbol))
|
||||
df = pd.DataFrame(res)
|
||||
|
||||
if "fiats" in df.columns.tolist():
|
||||
df["fiats"] = (
|
||||
df["fiats"].copy().apply(lambda x: len([i["symbol"] for i in x if x]))
|
||||
)
|
||||
df = df.sort_values(by=sortby, ascending=ascend)
|
||||
return df
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_coin_markets_by_id(
|
||||
coin_id: str = "eth-ethereum", quotes: str = "USD"
|
||||
symbol: str = "eth-ethereum",
|
||||
quotes: str = "USD",
|
||||
sortby: str = "pct_volume_share",
|
||||
ascend: bool = True,
|
||||
) -> pd.DataFrame:
|
||||
"""All markets for given coin and currency [Source: CoinPaprika]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
coin_id: str
|
||||
symbol: str
|
||||
Coin Parpika identifier of coin e.g. eth-ethereum
|
||||
quotes: str
|
||||
Comma separated list of quotes to return.
|
||||
Example: quotes=USD,BTC
|
||||
Allowed values:
|
||||
BTC, ETH, USD, EUR, PLN, KRW, GBP, CAD, JPY, RUB, TRY, NZD, AUD, CHF, UAH, HKD, SGD, NGN, PHP, MXN, BRL,
|
||||
THB, CLP, CNY, CZK, DKK, HUF, IDR, ILS, INR, MYR, NOK, PKR, SEK, TWD, ZAR, VND, BOB, COP, PEN, ARS, ISK
|
||||
BTC, ETH, USD, EUR, PLN, KRW, GBP, CAD, JPY, RUB, TRY, NZD, AUD, CHF, UAH, HKD, SGD, NGN,
|
||||
PHP, MXN, BRL, THB, CLP, CNY, CZK, DKK, HUF, IDR, ILS, INR, MYR, NOK, PKR, SEK, TWD, ZAR,
|
||||
VND, BOB, COP, PEN, ARS, ISK
|
||||
sortby: str
|
||||
Key by which to sort data. Every column name is valid (see for possible values:
|
||||
https://api.coinpaprika.com/v1).
|
||||
ascend: bool
|
||||
Flag to sort data ascending
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -173,7 +214,7 @@ def get_coin_markets_by_id(
|
||||
|
||||
session = PaprikaSession()
|
||||
markets = session.make_request(
|
||||
session.ENDPOINTS["coin_markets"].format(coin_id), quotes=quotes
|
||||
session.ENDPOINTS["coin_markets"].format(symbol), quotes=quotes
|
||||
)
|
||||
if "error" in markets:
|
||||
console.print(markets)
|
||||
@@ -194,12 +235,14 @@ def get_coin_markets_by_id(
|
||||
dct["market_url"] = r.get("market_url")
|
||||
data.append(dct)
|
||||
|
||||
return pd.DataFrame(data)
|
||||
df = pd.DataFrame(data)
|
||||
df = df.sort_values(by=sortby, ascending=ascend)
|
||||
return df
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_ohlc_historical(
|
||||
coin_id: str = "eth-ethereum", quotes: str = "USD", days: int = 90
|
||||
symbol: str = "eth-ethereum", quotes: str = "USD", days: int = 90
|
||||
) -> pd.DataFrame:
|
||||
"""
|
||||
Open/High/Low/Close values with volume and market_cap. [Source: CoinPaprika]
|
||||
@@ -209,7 +252,7 @@ def get_ohlc_historical(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
coin_id: str
|
||||
symbol: str
|
||||
Paprika coin identifier e.g. eth-ethereum
|
||||
quotes: str
|
||||
returned data quote (available values: usd btc)
|
||||
@@ -233,7 +276,7 @@ def get_ohlc_historical(
|
||||
|
||||
session = PaprikaSession()
|
||||
data = session.make_request(
|
||||
session.ENDPOINTS["ohlcv_hist"].format(coin_id),
|
||||
session.ENDPOINTS["ohlcv_hist"].format(symbol),
|
||||
quotes=quotes,
|
||||
start=start,
|
||||
end=end,
|
||||
@@ -248,7 +291,7 @@ def get_ohlc_historical(
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_tickers_info_for_coin(
|
||||
coin_id: str = "btc-bitcoin", quotes: str = "USD"
|
||||
symbol: str = "btc-bitcoin", quotes: str = "USD"
|
||||
) -> pd.DataFrame:
|
||||
"""Get all most important ticker related information for given coin id [Source: CoinPaprika]
|
||||
|
||||
@@ -290,7 +333,7 @@ def get_tickers_info_for_coin(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
coin_id: str
|
||||
symbol: str
|
||||
Id of coin from CoinPaprika
|
||||
quotes: str
|
||||
Comma separated quotes to return e.g quotes = USD, BTC
|
||||
@@ -304,7 +347,7 @@ def get_tickers_info_for_coin(
|
||||
|
||||
session = PaprikaSession()
|
||||
tickers = session.make_request(
|
||||
session.ENDPOINTS["ticker_info"].format(coin_id), quotes=quotes
|
||||
session.ENDPOINTS["ticker_info"].format(symbol), quotes=quotes
|
||||
)
|
||||
|
||||
for key, date in tickers.items():
|
||||
@@ -336,12 +379,12 @@ def get_tickers_info_for_coin(
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def validate_coin(coin: str, coins_dct: dict) -> Tuple[Optional[Any], Optional[Any]]:
|
||||
def validate_coin(symbol: str, coins_dct: dict) -> Tuple[Optional[Any], Optional[Any]]:
|
||||
"""Helper method that validates if proper coin id or symbol was provided [Source: CoinPaprika]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
coin: str
|
||||
symbol: str
|
||||
id or symbol of coin for CoinPaprika
|
||||
coins_dct: dict
|
||||
dictionary of coins
|
||||
@@ -353,18 +396,18 @@ def validate_coin(coin: str, coins_dct: dict) -> Tuple[Optional[Any], Optional[A
|
||||
"""
|
||||
|
||||
for key, value in coins_dct.items():
|
||||
if coin == value:
|
||||
if symbol == value:
|
||||
return key, value.lower()
|
||||
return None, None
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def basic_coin_info(coin_id: str = "btc-bitcoin") -> pd.DataFrame:
|
||||
def basic_coin_info(symbol: str = "btc-bitcoin") -> pd.DataFrame:
|
||||
"""Basic coin information [Source: CoinPaprika]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
coin_id: str
|
||||
symbol: str
|
||||
Coin id
|
||||
|
||||
Returns
|
||||
@@ -373,7 +416,7 @@ def basic_coin_info(coin_id: str = "btc-bitcoin") -> pd.DataFrame:
|
||||
Metric, Value
|
||||
"""
|
||||
|
||||
coin = get_coin(coin_id)
|
||||
coin = get_coin(symbol)
|
||||
tags = coin.get("tags") or []
|
||||
keys = [
|
||||
"id",
|
||||
|
||||
@@ -86,9 +86,9 @@ CURRENCIES = [
|
||||
@log_start_end(log=logger)
|
||||
def display_twitter(
|
||||
symbol: str = "BTC",
|
||||
top: int = 10,
|
||||
limit: int = 10,
|
||||
sortby: str = "date",
|
||||
descend: bool = False,
|
||||
ascend: bool = True,
|
||||
export: str = "",
|
||||
) -> None:
|
||||
"""Get twitter timeline for given coin id. Not more than last 50 tweets [Source: CoinPaprika]
|
||||
@@ -97,14 +97,14 @@ def display_twitter(
|
||||
----------
|
||||
symbol: str
|
||||
Cryptocurrency symbol (e.g. BTC)
|
||||
top: int
|
||||
limit: int
|
||||
Number of records to display
|
||||
sortby: str
|
||||
Key by which to sort data. Every column name is valid
|
||||
(see for possible values:
|
||||
https://api.coinpaprika.com/docs#tag/Coins/paths/~1coins~1%7Bcoin_id%7D~1twitter/get).
|
||||
descend: bool
|
||||
Flag to sort data descending
|
||||
ascend: bool
|
||||
Flag to sort data ascending
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
@@ -112,19 +112,14 @@ def display_twitter(
|
||||
# get coinpaprika id using crypto symbol
|
||||
cp_id = cryptocurrency_helpers.get_coinpaprika_id(symbol)
|
||||
|
||||
df = coinpaprika_model.get_coin_twitter_timeline(cp_id)
|
||||
df = coinpaprika_model.get_coin_twitter_timeline(cp_id, sortby, ascend)
|
||||
|
||||
if df.empty:
|
||||
console.print(f"Couldn't find any tweets for coin {symbol}", "\n")
|
||||
return
|
||||
|
||||
df = df.sort_values(by=sortby, ascending=descend)
|
||||
# Remove unicode chars (it breaks pretty tables)
|
||||
df["status"] = df["status"].apply(
|
||||
lambda text: "".join(i if ord(i) < 128 else "" for i in text)
|
||||
)
|
||||
print_rich_table(
|
||||
df.head(top),
|
||||
df.head(limit),
|
||||
headers=list(df.columns),
|
||||
show_index=False,
|
||||
title="Twitter Timeline",
|
||||
@@ -141,9 +136,9 @@ def display_twitter(
|
||||
@log_start_end(log=logger)
|
||||
def display_events(
|
||||
symbol: str = "BTC",
|
||||
top: int = 10,
|
||||
limit: int = 10,
|
||||
sortby: str = "date",
|
||||
descend: bool = False,
|
||||
ascend: bool = False,
|
||||
links: bool = False,
|
||||
export: str = "",
|
||||
) -> None:
|
||||
@@ -153,14 +148,14 @@ def display_events(
|
||||
----------
|
||||
symbol: str
|
||||
Cryptocurrency symbol (e.g. BTC)
|
||||
top: int
|
||||
limit: int
|
||||
Number of records to display
|
||||
sortby: str
|
||||
Key by which to sort data. Every column name is valid
|
||||
(see for possible values:
|
||||
https://api.coinpaprika.com/docs#tag/Coins/paths/~1coins~1%7Bcoin_id%7D~1events/get).
|
||||
descend: bool
|
||||
Flag to sort data descending
|
||||
ascend: bool
|
||||
Flag to sort data ascending
|
||||
links: bool
|
||||
Flag to display urls
|
||||
export : str
|
||||
@@ -169,14 +164,12 @@ def display_events(
|
||||
# get coinpaprika id using crypto symbol
|
||||
cp_id = cryptocurrency_helpers.get_coinpaprika_id(symbol)
|
||||
|
||||
df = coinpaprika_model.get_coin_events_by_id(cp_id)
|
||||
df = coinpaprika_model.get_coin_events_by_id(cp_id, sortby, ascend)
|
||||
|
||||
if df.empty:
|
||||
console.print(f"Couldn't find any events for coin {symbol}\n")
|
||||
return
|
||||
|
||||
df = df.sort_values(by=sortby, ascending=descend)
|
||||
|
||||
df_data = df.copy()
|
||||
|
||||
if links is True:
|
||||
@@ -185,7 +178,7 @@ def display_events(
|
||||
df.drop("link", axis=1, inplace=True)
|
||||
|
||||
print_rich_table(
|
||||
df.head(top), headers=list(df.columns), show_index=False, title="All Events"
|
||||
df.head(limit), headers=list(df.columns), show_index=False, title="All Events"
|
||||
)
|
||||
|
||||
export_data(
|
||||
@@ -199,9 +192,9 @@ def display_events(
|
||||
@log_start_end(log=logger)
|
||||
def display_exchanges(
|
||||
symbol: str = "btc",
|
||||
top: int = 10,
|
||||
limit: int = 10,
|
||||
sortby: str = "adjusted_volume_24h_share",
|
||||
descend: bool = False,
|
||||
ascend: bool = True,
|
||||
export: str = "",
|
||||
) -> None:
|
||||
"""Get all exchanges for given coin id. [Source: CoinPaprika]
|
||||
@@ -210,12 +203,13 @@ def display_exchanges(
|
||||
----------
|
||||
symbol: str
|
||||
Cryptocurrency symbol (e.g. BTC)
|
||||
top: int
|
||||
limit: int
|
||||
Number of records to display
|
||||
sortby: str
|
||||
Key by which to sort data. Every column name is valid (see for possible values: https://api.coinpaprika.com/v1).
|
||||
descend: bool
|
||||
Flag to sort data descending
|
||||
Key by which to sort data. Every column name is valid (see for possible values:
|
||||
https://api.coinpaprika.com/v1).
|
||||
ascend: bool
|
||||
Flag to sort data ascending
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
@@ -223,16 +217,17 @@ def display_exchanges(
|
||||
# get coinpaprika id using crypto symbol
|
||||
cp_id = cryptocurrency_helpers.get_coinpaprika_id(symbol)
|
||||
|
||||
df = coinpaprika_model.get_coin_exchanges_by_id(cp_id)
|
||||
df = coinpaprika_model.get_coin_exchanges_by_id(cp_id, sortby, ascend)
|
||||
|
||||
if df.empty:
|
||||
console.print("No data found", "\n")
|
||||
return
|
||||
|
||||
df = df.sort_values(by=sortby, ascending=descend)
|
||||
|
||||
print_rich_table(
|
||||
df.head(top), headers=list(df.columns), show_index=False, title="All Exchanges"
|
||||
df.head(limit),
|
||||
headers=list(df.columns),
|
||||
show_index=False,
|
||||
title="All Exchanges",
|
||||
)
|
||||
|
||||
export_data(
|
||||
@@ -245,11 +240,11 @@ def display_exchanges(
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_markets(
|
||||
symbol: str = "BTC",
|
||||
currency: str = "USD",
|
||||
top: int = 20,
|
||||
from_symbol: str = "BTC",
|
||||
to_symbol: str = "USD",
|
||||
limit: int = 20,
|
||||
sortby: str = "pct_volume_share",
|
||||
descend: bool = False,
|
||||
ascend: bool = True,
|
||||
links: bool = False,
|
||||
export: str = "",
|
||||
) -> None:
|
||||
@@ -257,16 +252,17 @@ def display_markets(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
symbol: str
|
||||
from_symbol: str
|
||||
Cryptocurrency symbol (e.g. BTC)
|
||||
currency: str
|
||||
to_symbol: str
|
||||
Quoted currency
|
||||
top: int
|
||||
limit: int
|
||||
Number of records to display
|
||||
sortby: str
|
||||
Key by which to sort data. Every column name is valid (see for possible values: https://api.coinpaprika.com/v1).
|
||||
descend: bool
|
||||
Flag to sort data descending
|
||||
Key by which to sort data. Every column name is valid (see for possible values:
|
||||
https://api.coinpaprika.com/v1).
|
||||
ascend: bool
|
||||
Flag to sort data ascending
|
||||
links: bool
|
||||
Flag to display urls
|
||||
export : str
|
||||
@@ -274,19 +270,17 @@ def display_markets(
|
||||
"""
|
||||
|
||||
if sortby in ["volume", "price"]:
|
||||
sortby = f"{str(currency).lower()}_{sortby}"
|
||||
sortby = f"{str(to_symbol).lower()}_{sortby}"
|
||||
|
||||
# get coinpaprika id using crypto symbol
|
||||
cp_id = cryptocurrency_helpers.get_coinpaprika_id(symbol)
|
||||
cp_id = cryptocurrency_helpers.get_coinpaprika_id(from_symbol)
|
||||
|
||||
df = coinpaprika_model.get_coin_markets_by_id(cp_id, currency)
|
||||
df = coinpaprika_model.get_coin_markets_by_id(cp_id, to_symbol, sortby, ascend)
|
||||
|
||||
if df.empty:
|
||||
console.print("There is no data \n")
|
||||
return
|
||||
|
||||
df = df.sort_values(by=sortby, ascending=descend)
|
||||
|
||||
df_data = df.copy()
|
||||
|
||||
if links is True:
|
||||
@@ -295,7 +289,7 @@ def display_markets(
|
||||
df.drop("market_url", axis=1, inplace=True)
|
||||
|
||||
print_rich_table(
|
||||
df.head(top), headers=list(df.columns), show_index=False, title="All Markets"
|
||||
df.head(limit), headers=list(df.columns), show_index=False, title="All Markets"
|
||||
)
|
||||
|
||||
export_data(
|
||||
@@ -308,26 +302,26 @@ def display_markets(
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_price_supply(
|
||||
symbol: str = "BTC",
|
||||
currency: str = "USD",
|
||||
from_symbol: str = "BTC",
|
||||
to_symbol: str = "USD",
|
||||
export: str = "",
|
||||
) -> None:
|
||||
"""Get ticker information for single coin [Source: CoinPaprika]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
symbol: str
|
||||
from_symbol: str
|
||||
Cryptocurrency symbol (e.g. BTC)
|
||||
currency: str
|
||||
to_symbol: str
|
||||
Quoted currency
|
||||
export: str
|
||||
Export dataframe data to csv,json,xlsx
|
||||
|
||||
"""
|
||||
# get coinpaprika id using crypto symbol
|
||||
cp_id = cryptocurrency_helpers.get_coinpaprika_id(symbol)
|
||||
cp_id = cryptocurrency_helpers.get_coinpaprika_id(from_symbol)
|
||||
|
||||
df = coinpaprika_model.get_tickers_info_for_coin(cp_id, currency)
|
||||
df = coinpaprika_model.get_tickers_info_for_coin(cp_id, to_symbol)
|
||||
|
||||
if df.empty:
|
||||
console.print("No data found", "\n")
|
||||
@@ -353,7 +347,8 @@ def display_basic(
|
||||
export: str = "",
|
||||
) -> None:
|
||||
"""Get basic information for coin. Like:
|
||||
name, symbol, rank, type, description, platform, proof_type, contract, tags, parent. [Source: CoinPaprika]
|
||||
name, symbol, rank, type, description, platform, proof_type, contract, tags, parent.
|
||||
[Source: CoinPaprika]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
||||
@@ -4,7 +4,6 @@ __docformat__ = "numpy"
|
||||
import logging
|
||||
import os
|
||||
from typing import Optional
|
||||
import pandas as pd
|
||||
|
||||
from openbb_terminal.cryptocurrency.overview import cryptopanic_model
|
||||
from openbb_terminal.decorators import log_start_end
|
||||
@@ -23,8 +22,8 @@ def display_news(
|
||||
filter_: Optional[str] = None,
|
||||
source: str = "cp",
|
||||
currency: Optional[str] = None,
|
||||
top: int = 25,
|
||||
descend: bool = False,
|
||||
limit: int = 25,
|
||||
ascend: bool = True,
|
||||
export: str = "",
|
||||
) -> None:
|
||||
"""Display recent posts from CryptoPanic news aggregator platform.
|
||||
@@ -32,7 +31,7 @@ def display_news(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
top: int
|
||||
limit: int
|
||||
number of news to display
|
||||
post_kind: str
|
||||
Filter by category of news. Available values: news or media.
|
||||
@@ -41,30 +40,29 @@ def display_news(
|
||||
region: str
|
||||
Filter news by regions. Available regions are: en (English), de (Deutsch), nl (Dutch),
|
||||
es (Español), fr (Français), it (Italiano), pt (Português), ru (Русский)
|
||||
descend: bool
|
||||
Sort in descending order.
|
||||
ascend: bool
|
||||
Sort in ascending order.
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
|
||||
df = cryptopanic_model.get_news(
|
||||
limit=top,
|
||||
limit=limit,
|
||||
post_kind=post_kind,
|
||||
filter_=filter_,
|
||||
region=region,
|
||||
currency=currency,
|
||||
source=source,
|
||||
ascend=ascend,
|
||||
)
|
||||
|
||||
if not df.empty:
|
||||
df = df.sort_values(by="published_at", ascending=descend)
|
||||
df["published_at"] = pd.to_datetime(df["published_at"]).dt.date
|
||||
df.drop(["negative_votes", "positive_votes", "domain"], axis=1, inplace=True)
|
||||
|
||||
df.columns = prettify_column_names(df.columns)
|
||||
|
||||
print_rich_table(
|
||||
df.head(top),
|
||||
df.head(limit),
|
||||
headers=list(df.columns),
|
||||
show_index=False,
|
||||
title="Most Recent News",
|
||||
|
||||
@@ -267,9 +267,9 @@ class DueDiligenceController(CryptoBaseController):
|
||||
|
||||
if ns_parser:
|
||||
glassnode_view.display_non_zero_addresses(
|
||||
asset=self.symbol.upper(),
|
||||
since=int(datetime.timestamp(ns_parser.since)),
|
||||
until=int(datetime.timestamp(ns_parser.until)),
|
||||
symbol=self.symbol.upper(),
|
||||
start_date=int(datetime.timestamp(ns_parser.since)),
|
||||
end_date=int(datetime.timestamp(ns_parser.until)),
|
||||
export=ns_parser.export,
|
||||
)
|
||||
|
||||
@@ -355,10 +355,10 @@ class DueDiligenceController(CryptoBaseController):
|
||||
|
||||
if ns_parser:
|
||||
glassnode_view.display_active_addresses(
|
||||
asset=self.symbol.upper(),
|
||||
symbol=self.symbol.upper(),
|
||||
interval=ns_parser.interval,
|
||||
since=int(datetime.timestamp(ns_parser.since)),
|
||||
until=int(datetime.timestamp(ns_parser.until)),
|
||||
start_date=int(datetime.timestamp(ns_parser.since)),
|
||||
end_date=int(datetime.timestamp(ns_parser.until)),
|
||||
export=ns_parser.export,
|
||||
)
|
||||
|
||||
@@ -419,10 +419,10 @@ class DueDiligenceController(CryptoBaseController):
|
||||
|
||||
if ns_parser:
|
||||
glassnode_view.display_exchange_net_position_change(
|
||||
asset=self.symbol.upper(),
|
||||
symbol=self.symbol.upper(),
|
||||
exchange=ns_parser.exchange,
|
||||
since=int(datetime.timestamp(ns_parser.since)),
|
||||
until=int(datetime.timestamp(ns_parser.until)),
|
||||
start_date=int(datetime.timestamp(ns_parser.since)),
|
||||
end_date=int(datetime.timestamp(ns_parser.until)),
|
||||
export=ns_parser.export,
|
||||
)
|
||||
else:
|
||||
@@ -489,10 +489,10 @@ class DueDiligenceController(CryptoBaseController):
|
||||
|
||||
if ns_parser:
|
||||
glassnode_view.display_exchange_balances(
|
||||
asset=self.symbol.upper(),
|
||||
symbol=self.symbol.upper(),
|
||||
exchange=ns_parser.exchange,
|
||||
since=int(datetime.timestamp(ns_parser.since)),
|
||||
until=int(datetime.timestamp(ns_parser.until)),
|
||||
start_date=int(datetime.timestamp(ns_parser.since)),
|
||||
end_date=int(datetime.timestamp(ns_parser.until)),
|
||||
percentage=ns_parser.percentage,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
@@ -801,7 +801,7 @@ class DueDiligenceController(CryptoBaseController):
|
||||
if ns_parser:
|
||||
ccxt_view.display_order_book(
|
||||
ns_parser.exchange,
|
||||
coin=self.symbol,
|
||||
symbol=self.symbol,
|
||||
vs=ns_parser.vs,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
@@ -845,10 +845,10 @@ class DueDiligenceController(CryptoBaseController):
|
||||
if ns_parser:
|
||||
ccxt_view.display_trades(
|
||||
ns_parser.exchange,
|
||||
coin=self.symbol,
|
||||
symbol=self.symbol,
|
||||
vs=ns_parser.vs,
|
||||
export=ns_parser.export,
|
||||
top=ns_parser.limit,
|
||||
limit=ns_parser.limit,
|
||||
)
|
||||
|
||||
@log_start_end(log=logger)
|
||||
@@ -879,7 +879,7 @@ class DueDiligenceController(CryptoBaseController):
|
||||
|
||||
if ns_parser:
|
||||
binance_view.display_balance(
|
||||
coin=coin, currency=ns_parser.vs, export=ns_parser.export
|
||||
to_symbol=coin, from_symbol=ns_parser.vs, export=ns_parser.export
|
||||
)
|
||||
|
||||
@log_start_end(log=logger)
|
||||
@@ -1001,9 +1001,9 @@ class DueDiligenceController(CryptoBaseController):
|
||||
coinpaprika_view.display_markets(
|
||||
symbol=self.symbol,
|
||||
currency=ns_parser.vs,
|
||||
top=ns_parser.limit,
|
||||
limit=ns_parser.limit,
|
||||
sortby=ns_parser.sortby,
|
||||
descend=ns_parser.descend,
|
||||
ascend=not ns_parser.descend,
|
||||
links=ns_parser.urls,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
@@ -1057,9 +1057,9 @@ class DueDiligenceController(CryptoBaseController):
|
||||
if self.symbol:
|
||||
coinpaprika_view.display_exchanges(
|
||||
symbol=self.symbol,
|
||||
top=ns_parser.limit,
|
||||
limit=ns_parser.limit,
|
||||
sortby=ns_parser.sortby,
|
||||
descend=ns_parser.descend,
|
||||
ascend=not ns_parser.descend,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
|
||||
@@ -1123,9 +1123,9 @@ class DueDiligenceController(CryptoBaseController):
|
||||
if self.symbol:
|
||||
coinpaprika_view.display_events(
|
||||
symbol=self.symbol,
|
||||
top=ns_parser.limit,
|
||||
limit=ns_parser.limit,
|
||||
sortby=ns_parser.sortby,
|
||||
descend=ns_parser.descend,
|
||||
ascend=not ns_parser.descend,
|
||||
links=ns_parser.urls,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
@@ -1180,9 +1180,9 @@ class DueDiligenceController(CryptoBaseController):
|
||||
if self.symbol:
|
||||
coinpaprika_view.display_twitter(
|
||||
symbol=self.symbol,
|
||||
top=ns_parser.limit,
|
||||
limit=ns_parser.limit,
|
||||
sortby=ns_parser.sortby,
|
||||
descend=ns_parser.descend,
|
||||
ascend=not ns_parser.descend,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
|
||||
@@ -1234,10 +1234,10 @@ class DueDiligenceController(CryptoBaseController):
|
||||
|
||||
if ns_parser:
|
||||
messari_view.display_marketcap_dominance(
|
||||
coin=self.symbol.upper(),
|
||||
symbol=self.symbol.upper(),
|
||||
interval=ns_parser.interval,
|
||||
start=ns_parser.start,
|
||||
end=ns_parser.end,
|
||||
start_date=ns_parser.start,
|
||||
end_date=ns_parser.end,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
|
||||
@@ -1260,7 +1260,7 @@ class DueDiligenceController(CryptoBaseController):
|
||||
|
||||
if ns_parser:
|
||||
messari_view.display_links(
|
||||
coin=self.symbol.upper(),
|
||||
symbol=self.symbol.upper(),
|
||||
export=ns_parser.export,
|
||||
)
|
||||
|
||||
@@ -1323,7 +1323,7 @@ class DueDiligenceController(CryptoBaseController):
|
||||
|
||||
if ns_parser:
|
||||
santiment_view.display_github_activity(
|
||||
coin=self.symbol.upper(),
|
||||
symbol=self.symbol.upper(),
|
||||
interval=ns_parser.interval,
|
||||
dev_activity=ns_parser.dev,
|
||||
start=ns_parser.start.strftime("%Y-%m-%dT%H:%M:%SZ"),
|
||||
@@ -1357,8 +1357,8 @@ class DueDiligenceController(CryptoBaseController):
|
||||
|
||||
if ns_parser:
|
||||
messari_view.display_roadmap(
|
||||
descend=ns_parser.descend,
|
||||
coin=self.symbol.upper(),
|
||||
ascend=not ns_parser.descend,
|
||||
symbol=self.symbol.upper(),
|
||||
limit=ns_parser.limit,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
@@ -1384,7 +1384,7 @@ class DueDiligenceController(CryptoBaseController):
|
||||
if ns_parser:
|
||||
if self.symbol:
|
||||
messari_view.display_tokenomics(
|
||||
coin=self.symbol.upper(),
|
||||
symbol=self.symbol.upper(),
|
||||
export=ns_parser.export,
|
||||
)
|
||||
|
||||
@@ -1408,7 +1408,7 @@ class DueDiligenceController(CryptoBaseController):
|
||||
|
||||
if ns_parser:
|
||||
messari_view.display_project_info(
|
||||
coin=self.symbol.upper(),
|
||||
symbol=self.symbol.upper(),
|
||||
export=ns_parser.export,
|
||||
)
|
||||
|
||||
@@ -1432,7 +1432,7 @@ class DueDiligenceController(CryptoBaseController):
|
||||
|
||||
if ns_parser:
|
||||
messari_view.display_team(
|
||||
coin=self.symbol.upper(),
|
||||
symbol=self.symbol.upper(),
|
||||
export=ns_parser.export,
|
||||
)
|
||||
|
||||
@@ -1456,7 +1456,7 @@ class DueDiligenceController(CryptoBaseController):
|
||||
|
||||
if ns_parser:
|
||||
messari_view.display_investors(
|
||||
coin=self.symbol.upper(),
|
||||
symbol=self.symbol.upper(),
|
||||
export=ns_parser.export,
|
||||
)
|
||||
|
||||
@@ -1480,7 +1480,7 @@ class DueDiligenceController(CryptoBaseController):
|
||||
|
||||
if ns_parser:
|
||||
messari_view.display_fundraising(
|
||||
coin=self.symbol.upper(),
|
||||
symbol=self.symbol.upper(),
|
||||
export=ns_parser.export,
|
||||
)
|
||||
|
||||
@@ -1504,7 +1504,7 @@ class DueDiligenceController(CryptoBaseController):
|
||||
|
||||
if ns_parser:
|
||||
messari_view.display_governance(
|
||||
coin=self.symbol.upper(),
|
||||
symbol=self.symbol.upper(),
|
||||
export=ns_parser.export,
|
||||
)
|
||||
|
||||
@@ -1607,10 +1607,10 @@ class DueDiligenceController(CryptoBaseController):
|
||||
else:
|
||||
messari_view.display_messari_timeseries(
|
||||
timeseries_id=ns_parser.timeseries,
|
||||
coin=self.symbol.upper(),
|
||||
symbol=self.symbol.upper(),
|
||||
interval=ns_parser.interval,
|
||||
start=ns_parser.start,
|
||||
end=ns_parser.end,
|
||||
start_date=ns_parser.start,
|
||||
end_date=ns_parser.end,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
|
||||
@@ -1648,7 +1648,7 @@ class DueDiligenceController(CryptoBaseController):
|
||||
"--filter",
|
||||
dest="filter",
|
||||
type=str,
|
||||
help="Filter by kind of news. One from list: rising|hot|bullish|bearish|important|saved|lol",
|
||||
help="Filter by kind of news. From: rising|hot|bullish|bearish|important|saved|lol",
|
||||
default=None,
|
||||
required=False,
|
||||
choices=cryptopanic_model.FILTERS,
|
||||
@@ -1659,8 +1659,11 @@ class DueDiligenceController(CryptoBaseController):
|
||||
"--region",
|
||||
dest="region",
|
||||
type=str,
|
||||
help="Filter news by regions. Available regions are: en (English), de (Deutsch), nl (Dutch), es (Español), "
|
||||
"fr (Français), it (Italiano), pt (Português), ru (Русский)",
|
||||
help=(
|
||||
"Filter news by regions. Available regions are: en (English), de (Deutsch), nl"
|
||||
" (Dutch), es (Español), fr (Français), it (Italiano), pt (Português), ru "
|
||||
"(Русский)"
|
||||
),
|
||||
default="en",
|
||||
choices=cryptopanic_model.REGIONS,
|
||||
)
|
||||
@@ -1688,7 +1691,7 @@ class DueDiligenceController(CryptoBaseController):
|
||||
"--urls",
|
||||
dest="urls",
|
||||
action="store_false",
|
||||
help="Flag to disable urls. If you will use the flag you will hide the column with urls",
|
||||
help="Flag to disable urls. Hides column with URL.",
|
||||
default=True,
|
||||
)
|
||||
|
||||
@@ -1698,11 +1701,11 @@ class DueDiligenceController(CryptoBaseController):
|
||||
|
||||
if ns_parser:
|
||||
cryptopanic_view.display_news(
|
||||
top=ns_parser.limit,
|
||||
limit=ns_parser.limit,
|
||||
source=self.source,
|
||||
currency=self.symbol,
|
||||
export=ns_parser.export,
|
||||
descend=ns_parser.descend,
|
||||
ascend=not ns_parser.descend,
|
||||
post_kind=ns_parser.kind,
|
||||
filter_=ns_parser.filter,
|
||||
region=ns_parser.region,
|
||||
|
||||
@@ -37,7 +37,7 @@ except ValueError:
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_crypto_sentiment_analysis(
|
||||
coin: str,
|
||||
symbol: str,
|
||||
raw: bool = False,
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
@@ -53,7 +53,7 @@ def display_crypto_sentiment_analysis(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
coin: str
|
||||
symbol: str
|
||||
Cryptocurrency
|
||||
raw : False
|
||||
Display raw table data
|
||||
@@ -63,10 +63,10 @@ def display_crypto_sentiment_analysis(
|
||||
External axes (1 axis is expected in the list), by default None
|
||||
"""
|
||||
|
||||
sentiment = get_sentiment(f"{coin}-USD") # Currently only USD pairs are available
|
||||
sentiment = get_sentiment(f"{symbol}-USD") # Currently only USD pairs are available
|
||||
|
||||
if sentiment.empty:
|
||||
console.print(f"Couldn't find Sentiment Data for {coin}\n")
|
||||
console.print(f"Couldn't find Sentiment Data for {symbol}\n")
|
||||
return
|
||||
|
||||
if not raw:
|
||||
@@ -85,7 +85,9 @@ def display_crypto_sentiment_analysis(
|
||||
ax.set_xlabel("Time")
|
||||
ax.set_ylabel("Finbrain's Sentiment Score")
|
||||
start_date = sentiment.index[0].strftime("%Y/%m/%d")
|
||||
ax.set_title(f"FinBrain's Sentiment Analysis for {coin}-USD since {start_date}")
|
||||
ax.set_title(
|
||||
f"FinBrain's Sentiment Analysis for {symbol}-USD since {start_date}"
|
||||
)
|
||||
ax.set_ylim([-1.1, 1.1])
|
||||
senValues = np.array(pd.to_numeric(sentiment["Sentiment Analysis"].values))
|
||||
senNone = np.array(0 * len(sentiment))
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import json
|
||||
import logging
|
||||
from datetime import datetime
|
||||
|
||||
import pandas as pd
|
||||
import requests
|
||||
@@ -173,18 +174,21 @@ INTERVALS_ACTIVE_ADDRESSES = ["24h", "1w", "1month"]
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_close_price(
|
||||
asset: str, since: int, until: int, print_errors: bool = True
|
||||
symbol: str,
|
||||
start_date: int = int(datetime(2010, 1, 1).timestamp()),
|
||||
end_date: int = int(datetime.now().timestamp()),
|
||||
print_errors: bool = True,
|
||||
) -> pd.DataFrame:
|
||||
"""Returns the price of a cryptocurrency
|
||||
[Source: https://glassnode.com]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
asset : str
|
||||
symbol : str
|
||||
Crypto to check close price (BTC or ETH)
|
||||
since : int
|
||||
start_date : int
|
||||
Initial date timestamp (e.g., 1_614_556_800)
|
||||
until : int
|
||||
end_date : int
|
||||
End date timestamp (e.g., 1_641_227_783_561)
|
||||
print_errors: bool
|
||||
Flag to print errors. Default: True
|
||||
@@ -199,10 +203,10 @@ def get_close_price(
|
||||
|
||||
parameters = {
|
||||
"api_key": cfg.API_GLASSNODE_KEY,
|
||||
"a": asset,
|
||||
"a": symbol,
|
||||
"i": "24h",
|
||||
"s": str(since),
|
||||
"u": str(until),
|
||||
"s": str(start_date),
|
||||
"u": str(end_date),
|
||||
}
|
||||
|
||||
r = requests.get(url, params=parameters)
|
||||
@@ -214,7 +218,7 @@ def get_close_price(
|
||||
|
||||
if df.empty:
|
||||
if print_errors:
|
||||
console.print(f"No data found for {asset} price.\n")
|
||||
console.print(f"No data found for {symbol} price.\n")
|
||||
else:
|
||||
df = df.set_index("t")
|
||||
df.index = pd.to_datetime(df.index, unit="s")
|
||||
@@ -230,17 +234,21 @@ def get_close_price(
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_non_zero_addresses(asset: str, since: int, until: int) -> pd.DataFrame:
|
||||
"""Returns addresses with non-zero balance of a certain asset
|
||||
def get_non_zero_addresses(
|
||||
symbol: str,
|
||||
start_date: int = int(datetime(2010, 1, 1).timestamp()),
|
||||
end_date: int = int(datetime.now().timestamp()),
|
||||
) -> pd.DataFrame:
|
||||
"""Returns addresses with non-zero balance of a certain symbol
|
||||
[Source: https://glassnode.com]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
asset : str
|
||||
symbol : str
|
||||
Asset to search (e.g., BTC)
|
||||
since : int
|
||||
start_date : int
|
||||
Initial date timestamp (e.g., 1_577_836_800)
|
||||
until : int
|
||||
end_date : int
|
||||
End date timestamp (e.g., 1_609_459_200)
|
||||
|
||||
Returns
|
||||
@@ -253,10 +261,10 @@ def get_non_zero_addresses(asset: str, since: int, until: int) -> pd.DataFrame:
|
||||
|
||||
parameters = {
|
||||
"api_key": cfg.API_GLASSNODE_KEY,
|
||||
"a": asset,
|
||||
"a": symbol,
|
||||
"i": "24h",
|
||||
"s": str(since),
|
||||
"u": str(until),
|
||||
"s": str(start_date),
|
||||
"u": str(end_date),
|
||||
}
|
||||
|
||||
r = requests.get(url, params=parameters)
|
||||
@@ -267,7 +275,7 @@ def get_non_zero_addresses(asset: str, since: int, until: int) -> pd.DataFrame:
|
||||
df = pd.DataFrame(json.loads(r.text))
|
||||
|
||||
if df.empty:
|
||||
console.print(f"No data found for {asset}'s non-zero addresses.\n")
|
||||
console.print(f"No data found for {symbol}'s non-zero addresses.\n")
|
||||
else:
|
||||
df["t"] = pd.to_datetime(df["t"], unit="s")
|
||||
df = df.set_index("t")
|
||||
@@ -282,18 +290,21 @@ def get_non_zero_addresses(asset: str, since: int, until: int) -> pd.DataFrame:
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_active_addresses(
|
||||
asset: str, interval: str, since: int, until: int
|
||||
symbol: str,
|
||||
interval: str = "24h",
|
||||
start_date: int = int(datetime(2010, 1, 1).timestamp()),
|
||||
end_date: int = int(datetime.now().timestamp()),
|
||||
) -> pd.DataFrame:
|
||||
"""Returns active addresses of a certain asset
|
||||
"""Returns active addresses of a certain symbol
|
||||
[Source: https://glassnode.com]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
asset : str
|
||||
symbol : str
|
||||
Asset to search active addresses (e.g., BTC)
|
||||
since : int
|
||||
start_date : int
|
||||
Initial date timestamp (e.g., 1_614_556_800)
|
||||
until : int
|
||||
end_date : int
|
||||
End date timestamp (e.g., 1_614_556_800)
|
||||
interval : str
|
||||
Interval frequency (e.g., 24h)
|
||||
@@ -308,10 +319,10 @@ def get_active_addresses(
|
||||
|
||||
parameters = {
|
||||
"api_key": cfg.API_GLASSNODE_KEY,
|
||||
"a": asset,
|
||||
"a": symbol,
|
||||
"i": interval,
|
||||
"s": str(since),
|
||||
"u": str(until),
|
||||
"s": str(start_date),
|
||||
"u": str(end_date),
|
||||
}
|
||||
|
||||
r = requests.get(url, params=parameters)
|
||||
@@ -321,7 +332,7 @@ def get_active_addresses(
|
||||
df = pd.DataFrame(json.loads(r.text))
|
||||
|
||||
if df.empty:
|
||||
console.print(f"No data found for {asset}'s active addresses.\n")
|
||||
console.print(f"No data found for {symbol}'s active addresses.\n")
|
||||
else:
|
||||
df["t"] = pd.to_datetime(df["t"], unit="s")
|
||||
df = df.set_index("t")
|
||||
@@ -335,17 +346,22 @@ def get_active_addresses(
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_hashrate(asset: str, interval: str, since: int, until: int) -> pd.DataFrame:
|
||||
"""Returns dataframe with mean hashrate of btc or eth blockchain and asset price
|
||||
def get_hashrate(
|
||||
symbol: str,
|
||||
interval: str = "24h",
|
||||
start_date: int = int(datetime(2010, 1, 1).timestamp()),
|
||||
end_date: int = int(datetime.now().timestamp()),
|
||||
) -> pd.DataFrame:
|
||||
"""Returns dataframe with mean hashrate of btc or eth blockchain and symbol price
|
||||
[Source: https://glassnode.com]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
asset : str
|
||||
symbol : str
|
||||
Blockchain to check hashrate (BTC or ETH)
|
||||
since : int
|
||||
start_date : int
|
||||
Initial date timestamp (e.g., 1_614_556_800)
|
||||
until : int
|
||||
end_date : int
|
||||
End date timestamp (e.g., 1_614_556_800)
|
||||
interval : str
|
||||
Interval frequency (e.g., 24h)
|
||||
@@ -353,7 +369,7 @@ def get_hashrate(asset: str, interval: str, since: int, until: int) -> pd.DataFr
|
||||
Returns
|
||||
-------
|
||||
pd.DataFrame
|
||||
mean hashrate and asset price over time
|
||||
mean hashrate and symbol price over time
|
||||
"""
|
||||
|
||||
url = api_url + "mining/hash_rate_mean"
|
||||
@@ -361,10 +377,10 @@ def get_hashrate(asset: str, interval: str, since: int, until: int) -> pd.DataFr
|
||||
|
||||
parameters = {
|
||||
"api_key": cfg.API_GLASSNODE_KEY,
|
||||
"a": asset,
|
||||
"a": symbol,
|
||||
"i": interval,
|
||||
"s": str(since),
|
||||
"u": str(until),
|
||||
"s": str(start_date),
|
||||
"u": str(end_date),
|
||||
}
|
||||
|
||||
df = pd.DataFrame()
|
||||
@@ -377,7 +393,7 @@ def get_hashrate(asset: str, interval: str, since: int, until: int) -> pd.DataFr
|
||||
df2 = pd.DataFrame(json.loads(r2.text))
|
||||
|
||||
if df.empty or df2.empty:
|
||||
console.print(f"No data found for {asset}'s hashrate or price.\n")
|
||||
console.print(f"No data found for {symbol}'s hashrate or price.\n")
|
||||
else:
|
||||
df = df.set_index("t")
|
||||
df.index = pd.to_datetime(df.index, unit="s")
|
||||
@@ -392,33 +408,36 @@ def get_hashrate(asset: str, interval: str, since: int, until: int) -> pd.DataFr
|
||||
console.print(f"Error getting hashrate: {r.text}")
|
||||
|
||||
if r2.status_code != 200:
|
||||
console.print(f"Error getting {asset} price: {r2.text}")
|
||||
console.print(f"Error getting {symbol} price: {r2.text}")
|
||||
|
||||
return df
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_exchange_balances(
|
||||
asset: str, exchange: str, since: int, until: int
|
||||
symbol: str,
|
||||
exchange: str = "binance",
|
||||
start_date: int = int(datetime(2010, 1, 1).timestamp()),
|
||||
end_date: int = int(datetime.now().timestamp()),
|
||||
) -> pd.DataFrame:
|
||||
"""Returns the total amount of coins held on exchange addresses in units and percentage.
|
||||
[Source: https://glassnode.com]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
asset : str
|
||||
symbol : str
|
||||
Asset to search active addresses (e.g., BTC)
|
||||
exchange : str
|
||||
Exchange to check net position change (e.g., binance)
|
||||
since : int
|
||||
start_date : int
|
||||
Initial date timestamp (e.g., 1_614_556_800)
|
||||
until : int
|
||||
end_date : int
|
||||
End date timestamp (e.g., 1_614_556_800)
|
||||
|
||||
Returns
|
||||
-------
|
||||
pd.DataFrame
|
||||
total amount of coins in units/percentage and asset price over time
|
||||
total amount of coins in units/percentage and symbol price over time
|
||||
"""
|
||||
|
||||
url = api_url + "distribution/balance_exchanges"
|
||||
@@ -427,11 +446,11 @@ def get_exchange_balances(
|
||||
|
||||
parameters = {
|
||||
"api_key": cfg.API_GLASSNODE_KEY,
|
||||
"a": asset,
|
||||
"a": symbol,
|
||||
"i": "24h",
|
||||
"e": exchange,
|
||||
"s": str(since),
|
||||
"u": str(until),
|
||||
"s": str(start_date),
|
||||
"u": str(end_date),
|
||||
}
|
||||
df = pd.DataFrame()
|
||||
|
||||
@@ -454,41 +473,44 @@ def get_exchange_balances(
|
||||
df.rename(columns={"v": "stacked"}, inplace=True)
|
||||
|
||||
if df.empty or df2.empty or df3.empty:
|
||||
console.print(f"No data found for {asset}'s exchange balance or price.\n")
|
||||
console.print(f"No data found for {symbol}'s exchange balance or price.\n")
|
||||
|
||||
elif r.status_code == 401 or r2.status_code == 401 or r3.status_code == 401:
|
||||
console.print("[red]Invalid API Key[/red]\n")
|
||||
else:
|
||||
if r.status_code != 200:
|
||||
console.print(f"Error getting {asset}'s exchange balance: {r.text}")
|
||||
console.print(f"Error getting {symbol}'s exchange balance: {r.text}")
|
||||
|
||||
if r2.status_code != 200:
|
||||
console.print(
|
||||
f"Error getting {asset}'s exchange balance relatives: {r2.text}"
|
||||
f"Error getting {symbol}'s exchange balance relatives: {r2.text}"
|
||||
)
|
||||
|
||||
if r3.status_code != 200:
|
||||
console.print(f"Error getting {asset} price: {r3.text}")
|
||||
console.print(f"Error getting {symbol} price: {r3.text}")
|
||||
|
||||
return df
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_exchange_net_position_change(
|
||||
asset: str, exchange: str, since: int, until: int
|
||||
symbol: str,
|
||||
exchange: str = "binance",
|
||||
start_date: int = int(datetime(2010, 1, 1).timestamp()),
|
||||
end_date: int = int(datetime.now().timestamp()),
|
||||
) -> pd.DataFrame:
|
||||
"""Returns 30d change of the supply held in exchange wallets of a certain asset.
|
||||
"""Returns 30d change of the supply held in exchange wallets of a certain symbol.
|
||||
[Source: https://glassnode.com]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
asset : str
|
||||
symbol : str
|
||||
Asset symbol to search supply (e.g., BTC)
|
||||
exchange : str
|
||||
Exchange to check net position change (e.g., binance)
|
||||
since : int
|
||||
start_date : int
|
||||
Initial date timestamp (e.g., 1_614_556_800)
|
||||
until : int
|
||||
end_date : int
|
||||
End date timestamp (e.g., 1_614_556_800)
|
||||
|
||||
Returns
|
||||
@@ -501,11 +523,11 @@ def get_exchange_net_position_change(
|
||||
|
||||
parameters = {
|
||||
"api_key": cfg.API_GLASSNODE_KEY,
|
||||
"a": asset,
|
||||
"a": symbol,
|
||||
"i": "24h",
|
||||
"e": exchange,
|
||||
"s": str(since),
|
||||
"u": str(until),
|
||||
"s": str(start_date),
|
||||
"u": str(end_date),
|
||||
}
|
||||
|
||||
r = requests.get(url, params=parameters)
|
||||
@@ -515,7 +537,7 @@ def get_exchange_net_position_change(
|
||||
df = pd.DataFrame(json.loads(r.text))
|
||||
|
||||
if df.empty:
|
||||
console.print(f"No data found for {asset}'s net position change.\n")
|
||||
console.print(f"No data found for {symbol}'s net position change.\n")
|
||||
else:
|
||||
df["t"] = pd.to_datetime(df["t"], unit="s")
|
||||
df = df.set_index("t")
|
||||
|
||||
@@ -35,8 +35,8 @@ logger = logging.getLogger(__name__)
|
||||
@log_start_end(log=logger)
|
||||
@check_api_key(["API_GLASSNODE_KEY"])
|
||||
def display_btc_rainbow(
|
||||
since: int = int(datetime(2010, 1, 1).timestamp()),
|
||||
until: int = int(datetime.now().timestamp()),
|
||||
start_date: int = int(datetime(2010, 1, 1).timestamp()),
|
||||
end_date: int = int(datetime.now().timestamp()),
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
@@ -46,16 +46,16 @@ def display_btc_rainbow(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
since : int
|
||||
start_date : int
|
||||
Initial date timestamp. Default is initial BTC timestamp: 1_325_376_000
|
||||
until : int
|
||||
end_date : int
|
||||
Final date timestamp. Default is current BTC timestamp
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
External axes (1 axis is expected in the list), by default None
|
||||
"""
|
||||
df_data = get_close_price("BTC", since, until)
|
||||
df_data = get_close_price("BTC", start_date, end_date)
|
||||
|
||||
if df_data.empty:
|
||||
return
|
||||
@@ -69,7 +69,7 @@ def display_btc_rainbow(
|
||||
return
|
||||
|
||||
d0 = datetime.strptime("2012-01-01", "%Y-%m-%d")
|
||||
dend = datetime.fromtimestamp(until)
|
||||
dend = datetime.fromtimestamp(end_date)
|
||||
|
||||
x = range((df_data.index[0] - d0).days, (dend - d0).days + 1)
|
||||
|
||||
@@ -155,23 +155,23 @@ def display_btc_rainbow(
|
||||
@log_start_end(log=logger)
|
||||
@check_api_key(["API_GLASSNODE_KEY"])
|
||||
def display_active_addresses(
|
||||
asset: str,
|
||||
since: int = 1577836800,
|
||||
until: int = 1609459200,
|
||||
symbol: str,
|
||||
start_date: int = 1577836800,
|
||||
end_date: int = 1609459200,
|
||||
interval: str = "24h",
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
) -> None:
|
||||
"""Display active addresses of a certain asset over time
|
||||
"""Display active addresses of a certain symbol over time
|
||||
[Source: https://glassnode.org]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
asset : str
|
||||
symbol : str
|
||||
Asset to search active addresses (e.g., BTC)
|
||||
since : int
|
||||
start_date : int
|
||||
Initial date timestamp (e.g., 1_614_556_800)
|
||||
until : int
|
||||
end_date : int
|
||||
End date timestamp (e.g., 1_614_556_800)
|
||||
interval : str
|
||||
Interval frequency (possible values are: 24h, 1w, 1month)
|
||||
@@ -181,7 +181,7 @@ def display_active_addresses(
|
||||
External axes (1 axis is expected in the list), by default None
|
||||
"""
|
||||
|
||||
df_addresses = get_active_addresses(asset, interval, since, until)
|
||||
df_addresses = get_active_addresses(symbol, interval, start_date, end_date)
|
||||
|
||||
if df_addresses.empty:
|
||||
return
|
||||
@@ -196,7 +196,7 @@ def display_active_addresses(
|
||||
|
||||
ax.plot(df_addresses.index, df_addresses["v"] / 1_000, linewidth=1.5)
|
||||
|
||||
ax.set_title(f"Active {asset} addresses over time")
|
||||
ax.set_title(f"Active {symbol} addresses over time")
|
||||
ax.set_ylabel("Addresses [thousands]")
|
||||
ax.set_xlim(df_addresses.index[0], df_addresses.index[-1])
|
||||
|
||||
@@ -216,22 +216,22 @@ def display_active_addresses(
|
||||
@log_start_end(log=logger)
|
||||
@check_api_key(["API_GLASSNODE_KEY"])
|
||||
def display_non_zero_addresses(
|
||||
asset: str,
|
||||
since: int = 1577836800,
|
||||
until: int = 1609459200,
|
||||
symbol: str,
|
||||
start_date: int = 1577836800,
|
||||
end_date: int = 1609459200,
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
) -> None:
|
||||
"""Display addresses with non-zero balance of a certain asset
|
||||
"""Display addresses with non-zero balance of a certain symbol
|
||||
[Source: https://glassnode.org]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
asset : str
|
||||
symbol : str
|
||||
Asset to search (e.g., BTC)
|
||||
since : int
|
||||
start_date : int
|
||||
Initial date timestamp (e.g., 1_577_836_800)
|
||||
until : int
|
||||
end_date : int
|
||||
End date timestamp (e.g., 1_609_459_200)
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
@@ -239,7 +239,7 @@ def display_non_zero_addresses(
|
||||
External axes (1 axis is expected in the list), by default None
|
||||
"""
|
||||
|
||||
df_addresses = get_non_zero_addresses(asset, since, until)
|
||||
df_addresses = get_non_zero_addresses(symbol, start_date, end_date)
|
||||
|
||||
if df_addresses.empty:
|
||||
return
|
||||
@@ -254,7 +254,7 @@ def display_non_zero_addresses(
|
||||
|
||||
ax.plot(df_addresses.index, df_addresses["v"] / 1_000, linewidth=1.5)
|
||||
|
||||
ax.set_title(f"{asset} Addresses with non-zero balances")
|
||||
ax.set_title(f"{symbol} Addresses with non-zero balances")
|
||||
ax.set_ylabel("Number of Addresses")
|
||||
ax.set_xlim(df_addresses.index[0], df_addresses.index[-1])
|
||||
|
||||
@@ -274,10 +274,10 @@ def display_non_zero_addresses(
|
||||
@log_start_end(log=logger)
|
||||
@check_api_key(["API_GLASSNODE_KEY"])
|
||||
def display_exchange_net_position_change(
|
||||
asset: str,
|
||||
symbol: str,
|
||||
exchange: str = "binance",
|
||||
since: int = 1577836800,
|
||||
until: int = 1609459200,
|
||||
start_date: int = 1577836800,
|
||||
end_date: int = 1609459200,
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
) -> None:
|
||||
@@ -286,15 +286,15 @@ def display_exchange_net_position_change(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
asset : str
|
||||
symbol : str
|
||||
Asset to search active addresses (e.g., BTC)
|
||||
exchange : str
|
||||
Exchange to check net position change (possible values are: aggregated, binance,
|
||||
bittrex, coinex, gate.io, gemini, huobi, kucoin, poloniex, bibox, bigone, bitfinex,
|
||||
hitbtc, kraken, okex, bithumb, zb.com, cobinhood, bitmex, bitstamp, coinbase, coincheck, luno)
|
||||
since : int
|
||||
start_date : int
|
||||
Initial date timestamp (e.g., 1_614_556_800)
|
||||
until : int
|
||||
end_date : int
|
||||
End date timestamp (e.g., 1_614_556_800)
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
@@ -302,7 +302,9 @@ def display_exchange_net_position_change(
|
||||
External axes (1 axis is expected in the list), by default None
|
||||
"""
|
||||
|
||||
df_addresses = get_exchange_net_position_change(asset, exchange, since, until)
|
||||
df_addresses = get_exchange_net_position_change(
|
||||
symbol, exchange, start_date, end_date
|
||||
)
|
||||
|
||||
if df_addresses.empty:
|
||||
return
|
||||
@@ -328,9 +330,9 @@ def display_exchange_net_position_change(
|
||||
facecolor=theme.up_color,
|
||||
)
|
||||
|
||||
ax.set_ylabel(f"30d change of {asset} supply held in exchange wallets [thousands]")
|
||||
ax.set_ylabel(f"30d change of {symbol} supply held in exchange wallets [thousands]")
|
||||
ax.set_title(
|
||||
f"{asset}: Exchange Net Position Change - {'all exchanges' if exchange == 'aggregated' else exchange}"
|
||||
f"{symbol}: Exchange Net Position Change - {'all exchanges' if exchange == 'aggregated' else exchange}"
|
||||
)
|
||||
ax.set_xlim(df_addresses.index[0], df_addresses.index[-1])
|
||||
|
||||
@@ -350,10 +352,10 @@ def display_exchange_net_position_change(
|
||||
@log_start_end(log=logger)
|
||||
@check_api_key(["API_GLASSNODE_KEY"])
|
||||
def display_exchange_balances(
|
||||
asset: str,
|
||||
symbol: str,
|
||||
exchange: str = "binance",
|
||||
since: int = 1577836800,
|
||||
until: int = 1609459200,
|
||||
start_date: int = 1577836800,
|
||||
end_date: int = 1609459200,
|
||||
percentage: bool = False,
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
@@ -363,15 +365,15 @@ def display_exchange_balances(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
asset : str
|
||||
symbol : str
|
||||
Asset to search active addresses (e.g., BTC)
|
||||
exchange : str
|
||||
Exchange to check net position change (possible values are: aggregated, binance, bittrex,
|
||||
coinex, gate.io, gemini, huobi, kucoin, poloniex, bibox, bigone, bitfinex, hitbtc, kraken,
|
||||
okex, bithumb, zb.com, cobinhood, bitmex, bitstamp, coinbase, coincheck, luno)
|
||||
since : int
|
||||
start_date : int
|
||||
Initial date timestamp (e.g., 1_614_556_800)
|
||||
until : int
|
||||
end_date : int
|
||||
End date timestamp (e.g., 1_614_556_800)
|
||||
percentage : bool
|
||||
Show percentage instead of stacked value.
|
||||
@@ -381,7 +383,7 @@ def display_exchange_balances(
|
||||
External axes (2 axes are expected in the list), by default None
|
||||
"""
|
||||
|
||||
df_balance = get_exchange_balances(asset, exchange, since, until)
|
||||
df_balance = get_exchange_balances(symbol, exchange, start_date, end_date)
|
||||
|
||||
if df_balance.empty:
|
||||
return
|
||||
@@ -401,17 +403,17 @@ def display_exchange_balances(
|
||||
else:
|
||||
ax1.plot(df_balance.index, df_balance["stacked"] / 1000)
|
||||
|
||||
ax1.set_ylabel(f"{asset} units [{'%' if percentage else 'thousands'}]")
|
||||
ax1.set_ylabel(f"{symbol} units [{'%' if percentage else 'thousands'}]")
|
||||
ax1.set_title(
|
||||
f"{asset}: Total Balance in {'all exchanges' if exchange == 'aggregated' else exchange}"
|
||||
f"{symbol}: Total Balance in {'all exchanges' if exchange == 'aggregated' else exchange}"
|
||||
)
|
||||
ax1.tick_params(axis="x", labelrotation=10)
|
||||
ax1.legend([f"{asset} Unit"], loc="upper right")
|
||||
ax1.legend([f"{symbol} Unit"], loc="upper right")
|
||||
|
||||
ax2.grid(visible=False)
|
||||
ax2.plot(df_balance.index, df_balance["price"], color="orange")
|
||||
ax2.set_ylabel(f"{asset} price [$]")
|
||||
ax2.legend([f"{asset} Price"], loc="upper left")
|
||||
ax2.set_ylabel(f"{symbol} price [$]")
|
||||
ax2.legend([f"{symbol} Price"], loc="upper left")
|
||||
|
||||
if not external_axes:
|
||||
theme.visualize_output()
|
||||
@@ -427,23 +429,23 @@ def display_exchange_balances(
|
||||
@log_start_end(log=logger)
|
||||
@check_api_key(["API_GLASSNODE_KEY"])
|
||||
def display_hashrate(
|
||||
asset: str,
|
||||
since: int = int((datetime.now() - timedelta(days=365)).timestamp()),
|
||||
until: int = int(datetime.now().timestamp()),
|
||||
symbol: str,
|
||||
start_date: int = int((datetime.now() - timedelta(days=365)).timestamp()),
|
||||
end_date: int = int(datetime.now().timestamp()),
|
||||
interval: str = "24h",
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
) -> None:
|
||||
"""Display dataframe with mean hashrate of btc or eth blockchain and asset price.
|
||||
"""Display dataframe with mean hashrate of btc or eth blockchain and symbol price.
|
||||
[Source: https://glassnode.org]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
asset : str
|
||||
symbol : str
|
||||
Blockchain to check mean hashrate (BTC or ETH)
|
||||
since : int
|
||||
start_date : int
|
||||
Initial date timestamp (e.g., 1_614_556_800)
|
||||
until : int
|
||||
end_date : int
|
||||
End date timestamp (e.g., 1_614_556_800)
|
||||
interval : str
|
||||
Interval frequency (possible values are: 24, 1w, 1month)
|
||||
@@ -453,7 +455,7 @@ def display_hashrate(
|
||||
External axes (2 axes are expected in the list), by default None
|
||||
"""
|
||||
|
||||
df = get_hashrate(asset, interval, since, until)
|
||||
df = get_hashrate(symbol, interval, start_date, end_date)
|
||||
|
||||
if df.empty:
|
||||
return
|
||||
@@ -472,15 +474,15 @@ def display_hashrate(
|
||||
df.index, df["hashrate"] / 1_000_000_000_000, color=theme.down_color, lw=0.8
|
||||
)
|
||||
ax1.yaxis.set_major_formatter(ticker.StrMethodFormatter("{x:.0f}T"))
|
||||
ax1.set_ylabel(f"{asset} hashrate (Terahashes/second)")
|
||||
ax1.set_title(f"{asset}: Mean hashrate")
|
||||
ax1.set_ylabel(f"{symbol} hashrate (Terahashes/second)")
|
||||
ax1.set_title(f"{symbol}: Mean hashrate")
|
||||
ax1.tick_params(axis="x", labelrotation=10)
|
||||
|
||||
ax2.set_xlim(left=df.index[0])
|
||||
ax2.grid(visible=False)
|
||||
ax2.plot(df.index, df["price"] / 1_000, color=theme.up_color, lw=0.8)
|
||||
ax2.yaxis.set_major_formatter(ticker.StrMethodFormatter("${x:.1f}k"))
|
||||
ax2.set_ylabel(f"{asset} price [$]")
|
||||
ax2.set_ylabel(f"{symbol} price [$]")
|
||||
|
||||
# Manually construct the chart legend
|
||||
lines = [
|
||||
|
||||
@@ -5,6 +5,7 @@ __docformat__ = "numpy"
|
||||
|
||||
import logging
|
||||
from typing import Any, Tuple
|
||||
from datetime import datetime, timedelta
|
||||
import re
|
||||
import pandas as pd
|
||||
import requests
|
||||
@@ -27,10 +28,15 @@ INTERVALS_TIMESERIES = ["5m", "15m", "30m", "1h", "1d", "1w"]
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_available_timeseries() -> pd.DataFrame:
|
||||
def get_available_timeseries(only_free: bool = True) -> pd.DataFrame:
|
||||
"""Returns available messari timeseries
|
||||
[Source: https://messari.io/]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
only_free : bool
|
||||
Display only timeseries available for free
|
||||
|
||||
Returns
|
||||
-------
|
||||
pd.DataFrame
|
||||
@@ -58,6 +64,8 @@ def get_available_timeseries() -> pd.DataFrame:
|
||||
)
|
||||
df = pd.DataFrame(arr)
|
||||
df.set_index("id", inplace=True)
|
||||
if only_free:
|
||||
df = df.drop(df[df["Requires Paid Key"]].index)
|
||||
return df
|
||||
return pd.DataFrame()
|
||||
|
||||
@@ -68,21 +76,24 @@ base_url2 = "https://data.messari.io/api/v2/"
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_marketcap_dominance(
|
||||
coin: str, interval: str, start: str, end: str
|
||||
symbol: str,
|
||||
interval: str = "1d",
|
||||
start_date: str = (datetime.now() - timedelta(days=365)).strftime("%Y-%m-%d"),
|
||||
end_date: str = datetime.now().strftime("%Y-%m-%d"),
|
||||
) -> pd.DataFrame:
|
||||
"""Returns market dominance of a coin over time
|
||||
[Source: https://messari.io/]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
coin : str
|
||||
symbol : str
|
||||
Crypto symbol to check market cap dominance
|
||||
start : int
|
||||
Initial date like string (e.g., 2021-10-01)
|
||||
end : int
|
||||
End date like string (e.g., 2021-10-01)
|
||||
interval : str
|
||||
Interval frequency (e.g., 1d)
|
||||
Interval frequency (possible values are: 5m, 15m, 30m, 1h, 1d, 1w)
|
||||
start_date : int
|
||||
Initial date like string (e.g., 2021-10-01)
|
||||
end_date : int
|
||||
End date like string (e.g., 2021-10-01)
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -91,30 +102,38 @@ def get_marketcap_dominance(
|
||||
"""
|
||||
|
||||
df, _ = get_messari_timeseries(
|
||||
coin=coin, end=end, start=start, interval=interval, timeseries_id="mcap.dom"
|
||||
symbol=symbol,
|
||||
end_date=end_date,
|
||||
start_date=start_date,
|
||||
interval=interval,
|
||||
timeseries_id="mcap.dom",
|
||||
)
|
||||
return df
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_messari_timeseries(
|
||||
coin: str, timeseries_id: str, interval: str, start: str, end: str
|
||||
symbol: str,
|
||||
timeseries_id: str,
|
||||
interval: str = "1d",
|
||||
start_date: str = (datetime.now() - timedelta(days=365)).strftime("%Y-%m-%d"),
|
||||
end_date: str = datetime.now().strftime("%Y-%m-%d"),
|
||||
) -> Tuple[pd.DataFrame, str]:
|
||||
"""Returns messari timeseries
|
||||
[Source: https://messari.io/]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
coin : str
|
||||
symbol : str
|
||||
Crypto symbol to check messari timeseries
|
||||
timeseries_id : str
|
||||
Messari timeserie id
|
||||
interval : str
|
||||
Interval frequency (possible values are: 5m, 15m, 30m, 1h, 1d, 1w)
|
||||
start : int
|
||||
Initial date like string (e.g., 2021-10-01)
|
||||
end : int
|
||||
End date like string (e.g., 2021-10-01)
|
||||
interval : str
|
||||
Interval frequency (e.g., 1d)
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -124,13 +143,13 @@ def get_messari_timeseries(
|
||||
timeserie title
|
||||
"""
|
||||
|
||||
url = base_url + f"assets/{coin}/metrics/{timeseries_id}/time-series"
|
||||
url = base_url + f"assets/{symbol}/metrics/{timeseries_id}/time-series"
|
||||
|
||||
headers = {"x-messari-api-key": cfg.API_MESSARI_KEY}
|
||||
|
||||
parameters = {
|
||||
"start": start,
|
||||
"end": end,
|
||||
"start": start_date,
|
||||
"end": end_date,
|
||||
"interval": interval,
|
||||
}
|
||||
|
||||
@@ -145,7 +164,7 @@ def get_messari_timeseries(
|
||||
df = pd.DataFrame(data["values"], columns=data["parameters"]["columns"])
|
||||
|
||||
if df.empty:
|
||||
console.print(f"No data found for {coin}.\n")
|
||||
console.print(f"No data found for {symbol}.\n")
|
||||
else:
|
||||
df = df.set_index("timestamp")
|
||||
df.index = pd.to_datetime(df.index, unit="ms")
|
||||
@@ -198,7 +217,7 @@ def get_links(symbol: str) -> pd.DataFrame:
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_roadmap(symbol: str) -> pd.DataFrame:
|
||||
def get_roadmap(symbol: str, ascend: bool = True) -> pd.DataFrame:
|
||||
"""Returns coin roadmap
|
||||
[Source: https://messari.io/]
|
||||
|
||||
@@ -206,6 +225,8 @@ def get_roadmap(symbol: str) -> pd.DataFrame:
|
||||
----------
|
||||
symbol : str
|
||||
Crypto symbol to check roadmap
|
||||
ascend: bool
|
||||
reverse order
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -229,6 +250,10 @@ def get_roadmap(symbol: str) -> pd.DataFrame:
|
||||
df["date"] = pd.to_datetime(df["date"])
|
||||
df.columns = map(str.capitalize, df.columns)
|
||||
df = df.dropna(axis=1, how="all")
|
||||
df["Date"] = df["Date"].dt.date
|
||||
show_df = df
|
||||
show_df = show_df.sort_values(by="Date", ascending=ascend)
|
||||
show_df.fillna("Unknown", inplace=True)
|
||||
elif r.status_code == 401:
|
||||
console.print("[red]Invalid API Key[/red]\n")
|
||||
else:
|
||||
@@ -292,7 +317,7 @@ def get_tokenomics(symbol: str, coingecko_id: str) -> Tuple[pd.DataFrame, pd.Dat
|
||||
df = pd.concat([df, cg_df], ignore_index=True, sort=False)
|
||||
df.fillna("-", inplace=True)
|
||||
circ_df, _ = get_messari_timeseries(
|
||||
coin=symbol,
|
||||
symbol=symbol,
|
||||
timeseries_id="sply.circ",
|
||||
interval="1d",
|
||||
start="",
|
||||
|
||||
@@ -68,10 +68,8 @@ def display_messari_timeseries_list(
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
|
||||
df = get_available_timeseries()
|
||||
df = get_available_timeseries(only_free)
|
||||
if not df.empty:
|
||||
if only_free:
|
||||
df = df.drop(df[df["Requires Paid Key"]].index)
|
||||
if query:
|
||||
mask = np.column_stack(
|
||||
[
|
||||
@@ -104,10 +102,10 @@ def display_messari_timeseries_list(
|
||||
@log_start_end(log=logger)
|
||||
@check_api_key(["API_MESSARI_KEY"])
|
||||
def display_messari_timeseries(
|
||||
coin: str,
|
||||
symbol: str,
|
||||
timeseries_id: str,
|
||||
start: str = (datetime.now() - timedelta(days=365)).strftime("%Y-%m-%d"),
|
||||
end: str = datetime.now().strftime("%Y-%m-%d"),
|
||||
start_date: str = (datetime.now() - timedelta(days=365)).strftime("%Y-%m-%d"),
|
||||
end_date: str = datetime.now().strftime("%Y-%m-%d"),
|
||||
interval: str = "1d",
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
@@ -117,13 +115,13 @@ def display_messari_timeseries(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
coin : str
|
||||
symbol : str
|
||||
Crypto symbol to check market cap dominance
|
||||
timeseries_id: str
|
||||
Obtained by api.crypto.dd.get_mt command
|
||||
start : int
|
||||
start_date : int
|
||||
Initial date like string (e.g., 2021-10-01)
|
||||
end : int
|
||||
end_date : int
|
||||
End date like string (e.g., 2021-10-01)
|
||||
interval : str
|
||||
Interval frequency (possible values are: 5m, 15m, 30m, 1h, 1d, 1w)
|
||||
@@ -134,7 +132,11 @@ def display_messari_timeseries(
|
||||
"""
|
||||
|
||||
df, title = get_messari_timeseries(
|
||||
coin=coin, timeseries_id=timeseries_id, start=start, end=end, interval=interval
|
||||
symbol=symbol,
|
||||
timeseries_id=timeseries_id,
|
||||
start_date=start_date,
|
||||
end_date=end_date,
|
||||
interval=interval,
|
||||
)
|
||||
|
||||
if not df.empty:
|
||||
@@ -152,7 +154,7 @@ def display_messari_timeseries(
|
||||
|
||||
ax.plot(df.index, df[df.columns[0]])
|
||||
|
||||
ax.set_title(f"{coin}'s {title}")
|
||||
ax.set_title(f"{symbol}'s {title}")
|
||||
ax.set_ylabel(title)
|
||||
ax.set_xlim(df.index[0], df.index[-1])
|
||||
|
||||
@@ -172,9 +174,9 @@ def display_messari_timeseries(
|
||||
@log_start_end(log=logger)
|
||||
@check_api_key(["API_MESSARI_KEY"])
|
||||
def display_marketcap_dominance(
|
||||
coin: str,
|
||||
start: str = (datetime.now() - timedelta(days=365)).strftime("%Y-%m-%d"),
|
||||
end: str = datetime.now().strftime("%Y-%m-%d"),
|
||||
symbol: str,
|
||||
start_date: str = (datetime.now() - timedelta(days=365)).strftime("%Y-%m-%d"),
|
||||
end_date: str = datetime.now().strftime("%Y-%m-%d"),
|
||||
interval: str = "1d",
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
@@ -184,11 +186,11 @@ def display_marketcap_dominance(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
coin : str
|
||||
symbol : str
|
||||
Crypto symbol to check market cap dominance
|
||||
start : int
|
||||
start_date : int
|
||||
Initial date like string (e.g., 2021-10-01)
|
||||
end : int
|
||||
end_date : int
|
||||
End date like string (e.g., 2021-10-01)
|
||||
interval : str
|
||||
Interval frequency (possible values are: 5m, 15m, 30m, 1h, 1d, 1w)
|
||||
@@ -198,7 +200,9 @@ def display_marketcap_dominance(
|
||||
External axes (1 axis is expected in the list), by default None
|
||||
"""
|
||||
|
||||
df = get_marketcap_dominance(coin=coin, start=start, end=end, interval=interval)
|
||||
df = get_marketcap_dominance(
|
||||
symbol=symbol, start_date=start_date, end_date=end_date, interval=interval
|
||||
)
|
||||
|
||||
if not df.empty:
|
||||
|
||||
@@ -212,8 +216,8 @@ def display_marketcap_dominance(
|
||||
|
||||
ax.plot(df.index, df["marketcap_dominance"])
|
||||
|
||||
ax.set_title(f"{coin}'s Market Cap Dominance over time")
|
||||
ax.set_ylabel(f"{coin} Percentage share")
|
||||
ax.set_title(f"{symbol}'s Market Cap Dominance over time")
|
||||
ax.set_ylabel(f"{symbol} Percentage share")
|
||||
ax.set_xlim(df.index[0], df.index[-1])
|
||||
|
||||
theme.style_primary_axis(ax)
|
||||
@@ -231,13 +235,13 @@ def display_marketcap_dominance(
|
||||
|
||||
@log_start_end(log=logger)
|
||||
@check_api_key(["API_MESSARI_KEY"])
|
||||
def display_links(coin: str, export: str = "") -> None:
|
||||
def display_links(symbol: str, export: str = "") -> None:
|
||||
"""Display coin links
|
||||
[Source: https://messari.io/]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
coin : str
|
||||
symbol : str
|
||||
Crypto symbol to check links
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
@@ -245,13 +249,13 @@ def display_links(coin: str, export: str = "") -> None:
|
||||
External axes (1 axis is expected in the list), by default None
|
||||
"""
|
||||
|
||||
df = get_links(coin)
|
||||
df = get_links(symbol)
|
||||
if not df.empty:
|
||||
print_rich_table(
|
||||
df,
|
||||
headers=list(df.columns),
|
||||
show_index=False,
|
||||
title=f"{coin} Links",
|
||||
title=f"{symbol} Links",
|
||||
)
|
||||
|
||||
export_data(
|
||||
@@ -267,8 +271,8 @@ def display_links(coin: str, export: str = "") -> None:
|
||||
@log_start_end(log=logger)
|
||||
@check_api_key(["API_MESSARI_KEY"])
|
||||
def display_roadmap(
|
||||
coin: str,
|
||||
descend: bool = False,
|
||||
symbol: str,
|
||||
ascend: bool = True,
|
||||
limit: int = 5,
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
@@ -278,9 +282,9 @@ def display_roadmap(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
coin : str
|
||||
symbol : str
|
||||
Crypto symbol to check roadmap
|
||||
descend: bool
|
||||
ascend: bool
|
||||
reverse order
|
||||
limit : int
|
||||
number to show
|
||||
@@ -289,21 +293,17 @@ def display_roadmap(
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
External axes (1 axis is expected in the list), by default None
|
||||
"""
|
||||
df = get_roadmap(coin)
|
||||
df = get_roadmap(symbol, ascend)
|
||||
|
||||
if not df.empty:
|
||||
df["Date"] = df["Date"].dt.date
|
||||
show_df = df
|
||||
show_df = show_df.sort_values(by="Date", ascending=descend)
|
||||
show_df.fillna("Unknown", inplace=True)
|
||||
print_rich_table(
|
||||
show_df.head(limit),
|
||||
headers=list(show_df.columns),
|
||||
df.head(limit),
|
||||
headers=list(df.columns),
|
||||
show_index=False,
|
||||
title=f"{coin} Roadmap",
|
||||
title=f"{symbol} Roadmap",
|
||||
)
|
||||
df_prices, _ = cryptocurrency_helpers.load_yf_data(
|
||||
symbol=coin,
|
||||
symbol=symbol,
|
||||
currency="USD",
|
||||
days=4380,
|
||||
interval="1d",
|
||||
@@ -352,7 +352,7 @@ def display_roadmap(
|
||||
ax.get_yaxis().set_major_formatter(
|
||||
ticker.FuncFormatter(lambda x, _: lambda_long_number_format(x))
|
||||
)
|
||||
ax.set_title(f"{coin.upper()} Price and Roadmap")
|
||||
ax.set_title(f"{symbol.upper()} Price and Roadmap")
|
||||
ax.set_ylabel("Price [$]")
|
||||
ax.set_xlim(df_prices.index[0], df_prices.index[-1])
|
||||
theme.style_primary_axis(ax)
|
||||
@@ -373,7 +373,7 @@ def display_roadmap(
|
||||
@log_start_end(log=logger)
|
||||
@check_api_key(["API_MESSARI_KEY"])
|
||||
def display_tokenomics(
|
||||
coin: str,
|
||||
symbol: str,
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
) -> None:
|
||||
@@ -382,15 +382,15 @@ def display_tokenomics(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
coin : str
|
||||
symbol : str
|
||||
Crypto symbol to check tokenomics
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
External axes (2 axes are expected in the list), by default None
|
||||
"""
|
||||
coingecko_id = cryptocurrency_helpers.get_coingecko_id(coin)
|
||||
df, circ_df = get_tokenomics(coin, coingecko_id)
|
||||
coingecko_id = cryptocurrency_helpers.get_coingecko_id(symbol)
|
||||
df, circ_df = get_tokenomics(symbol, coingecko_id)
|
||||
|
||||
if not df.empty and not circ_df.empty:
|
||||
df = df.applymap(lambda x: lambda_long_number_format(x, 2))
|
||||
@@ -398,7 +398,7 @@ def display_tokenomics(
|
||||
df,
|
||||
headers=list(df.columns),
|
||||
show_index=False,
|
||||
title=f"{coin} Tokenomics",
|
||||
title=f"{symbol} Tokenomics",
|
||||
)
|
||||
if not external_axes:
|
||||
_, ax = plt.subplots(figsize=plot_autoscale(), dpi=cfgPlot.PLOT_DPI)
|
||||
@@ -408,7 +408,7 @@ def display_tokenomics(
|
||||
else:
|
||||
return
|
||||
df_prices, _ = cryptocurrency_helpers.load_yf_data(
|
||||
symbol=coin,
|
||||
symbol=symbol,
|
||||
currency="USD",
|
||||
days=4380,
|
||||
interval="1d",
|
||||
@@ -428,14 +428,14 @@ def display_tokenomics(
|
||||
ax2.get_yaxis().set_major_formatter(
|
||||
ticker.FuncFormatter(lambda x, _: lambda_long_number_format(x))
|
||||
)
|
||||
ax2.set_ylabel(f"{coin} price [$]")
|
||||
ax2.set_ylabel(f"{symbol} price [$]")
|
||||
theme.style_twin_axis(ax2)
|
||||
ax2.yaxis.set_label_position("right")
|
||||
ax.legend()
|
||||
ax.get_yaxis().set_major_formatter(
|
||||
ticker.FuncFormatter(lambda x, _: lambda_long_number_format(x))
|
||||
)
|
||||
ax.set_title(f"{coin} circulating supply over time")
|
||||
ax.set_title(f"{symbol} circulating supply over time")
|
||||
ax.set_ylabel("Number of tokens")
|
||||
ax.set_xlim(merged_df.index[0], merged_df.index[-1])
|
||||
theme.style_primary_axis(ax)
|
||||
@@ -457,7 +457,7 @@ def display_tokenomics(
|
||||
@log_start_end(log=logger)
|
||||
@check_api_key(["API_MESSARI_KEY"])
|
||||
def display_project_info(
|
||||
coin: str,
|
||||
symbol: str,
|
||||
export: str = "",
|
||||
) -> None:
|
||||
"""Display project info
|
||||
@@ -465,49 +465,26 @@ def display_project_info(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
coin : str
|
||||
symbol : str
|
||||
Crypto symbol to check project info
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
(df_info, df_repos, df_audits, df_vulns) = get_project_product_info(coin)
|
||||
(df_info, df_repos, df_audits, df_vulns) = get_project_product_info(symbol)
|
||||
|
||||
if not df_info.empty:
|
||||
print_rich_table(
|
||||
df_info,
|
||||
headers=list(df_info.columns),
|
||||
show_index=False,
|
||||
title=f"{coin} General Info",
|
||||
)
|
||||
else:
|
||||
console.print("\nGeneral info not found\n")
|
||||
if not df_repos.empty:
|
||||
print_rich_table(
|
||||
df_repos,
|
||||
headers=list(df_repos.columns),
|
||||
show_index=False,
|
||||
title=f"{coin} Public Repositories",
|
||||
)
|
||||
else:
|
||||
console.print("\nPublic repositories not found\n")
|
||||
if not df_audits.empty:
|
||||
print_rich_table(
|
||||
df_audits,
|
||||
headers=list(df_audits.columns),
|
||||
show_index=False,
|
||||
title=f"{coin} Audits",
|
||||
)
|
||||
else:
|
||||
console.print("\nAudits not found\n")
|
||||
if not df_vulns.empty:
|
||||
print_rich_table(
|
||||
df_vulns,
|
||||
headers=list(df_vulns.columns),
|
||||
show_index=False,
|
||||
title=f"{coin} Vulnerabilities",
|
||||
)
|
||||
else:
|
||||
console.print("\nVulnerabilities not found\n")
|
||||
for df, title in zip(
|
||||
[df_info, df_repos, df_audits, df_vulns],
|
||||
["General Info", "Public Repos", "Audits", "Vulnerabilities"],
|
||||
):
|
||||
if not df.empty:
|
||||
print_rich_table(
|
||||
df,
|
||||
headers=list(df.columns),
|
||||
show_index=False,
|
||||
title=f"{symbol} {title}",
|
||||
)
|
||||
else:
|
||||
console.print(f"\n{title} not found\n")
|
||||
|
||||
export_data(
|
||||
export,
|
||||
@@ -520,7 +497,7 @@ def display_project_info(
|
||||
@log_start_end(log=logger)
|
||||
@check_api_key(["API_MESSARI_KEY"])
|
||||
def display_investors(
|
||||
coin: str,
|
||||
symbol: str,
|
||||
export: str = "",
|
||||
) -> None:
|
||||
"""Display coin investors
|
||||
@@ -528,19 +505,19 @@ def display_investors(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
coin : str
|
||||
symbol : str
|
||||
Crypto symbol to check coin investors
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
(df_individuals, df_organizations) = get_investors(coin)
|
||||
(df_individuals, df_organizations) = get_investors(symbol)
|
||||
if not df_individuals.empty or not df_organizations.empty:
|
||||
if not df_individuals.empty:
|
||||
print_rich_table(
|
||||
df_individuals,
|
||||
headers=list(df_individuals.columns),
|
||||
show_index=False,
|
||||
title=f"{coin} Investors - Individuals",
|
||||
title=f"{symbol} Investors - Individuals",
|
||||
)
|
||||
else:
|
||||
console.print("\nIndividual investors not found\n")
|
||||
@@ -549,7 +526,7 @@ def display_investors(
|
||||
df_organizations,
|
||||
headers=list(df_organizations.columns),
|
||||
show_index=False,
|
||||
title=f"{coin} Investors - Organizations",
|
||||
title=f"{symbol} Investors - Organizations",
|
||||
)
|
||||
else:
|
||||
console.print("\nInvestors - Organizations not found\n")
|
||||
@@ -566,7 +543,7 @@ def display_investors(
|
||||
@log_start_end(log=logger)
|
||||
@check_api_key(["API_MESSARI_KEY"])
|
||||
def display_team(
|
||||
coin: str,
|
||||
symbol: str,
|
||||
export: str = "",
|
||||
) -> None:
|
||||
"""Display coin team
|
||||
@@ -574,19 +551,19 @@ def display_team(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
coin : str
|
||||
symbol : str
|
||||
Crypto symbol to check coin team
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
(df_individuals, df_organizations) = get_team(coin)
|
||||
(df_individuals, df_organizations) = get_team(symbol)
|
||||
if not df_individuals.empty or not df_organizations.empty:
|
||||
if not df_individuals.empty:
|
||||
print_rich_table(
|
||||
df_individuals,
|
||||
headers=list(df_individuals.columns),
|
||||
show_index=False,
|
||||
title=f"{coin} Team - Individuals",
|
||||
title=f"{symbol} Team - Individuals",
|
||||
)
|
||||
else:
|
||||
console.print("\nIndividual team members not found\n")
|
||||
@@ -595,7 +572,7 @@ def display_team(
|
||||
df_organizations,
|
||||
headers=list(df_organizations.columns),
|
||||
show_index=False,
|
||||
title=f"{coin} Team - Organizations",
|
||||
title=f"{symbol} Team - Organizations",
|
||||
)
|
||||
else:
|
||||
console.print("\nTeam organizations not found\n")
|
||||
@@ -612,7 +589,7 @@ def display_team(
|
||||
@log_start_end(log=logger)
|
||||
@check_api_key(["API_MESSARI_KEY"])
|
||||
def display_governance(
|
||||
coin: str,
|
||||
symbol: str,
|
||||
export: str = "",
|
||||
) -> None:
|
||||
"""Display coin governance
|
||||
@@ -620,12 +597,12 @@ def display_governance(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
coin : str
|
||||
symbol : str
|
||||
Crypto symbol to check coin governance
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
(summary, df) = get_governance(coin)
|
||||
(summary, df) = get_governance(symbol)
|
||||
if summary:
|
||||
summary = prettify_paragraph(summary)
|
||||
console.print(summary, "\n")
|
||||
@@ -634,7 +611,7 @@ def display_governance(
|
||||
df,
|
||||
headers=list(df.columns),
|
||||
show_index=False,
|
||||
title=f"{coin} Governance details",
|
||||
title=f"{symbol} Governance details",
|
||||
)
|
||||
export_data(
|
||||
export,
|
||||
@@ -643,13 +620,13 @@ def display_governance(
|
||||
df,
|
||||
)
|
||||
else:
|
||||
console.print(f"\n{coin} governance details not found\n")
|
||||
console.print(f"\n{symbol} governance details not found\n")
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
@check_api_key(["API_MESSARI_KEY"])
|
||||
def display_fundraising(
|
||||
coin: str,
|
||||
symbol: str,
|
||||
export: str = "",
|
||||
) -> None:
|
||||
"""Display coin fundraising
|
||||
@@ -657,12 +634,12 @@ def display_fundraising(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
coin : str
|
||||
symbol : str
|
||||
Crypto symbol to check coin fundraising
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
(summary, df_sales_rounds, df_treasury_accs, df_details) = get_fundraising(coin)
|
||||
(summary, df_sales_rounds, df_treasury_accs, df_details) = get_fundraising(symbol)
|
||||
if summary:
|
||||
summary = prettify_paragraph(summary)
|
||||
console.print(summary, "\n")
|
||||
@@ -674,7 +651,7 @@ def display_fundraising(
|
||||
df_sales_rounds,
|
||||
headers=list(df_sales_rounds.columns),
|
||||
show_index=False,
|
||||
title=f"{coin} Sales Rounds",
|
||||
title=f"{symbol} Sales Rounds",
|
||||
)
|
||||
else:
|
||||
console.print("\nSales rounds not found\n")
|
||||
@@ -683,7 +660,7 @@ def display_fundraising(
|
||||
df_treasury_accs,
|
||||
headers=list(df_treasury_accs.columns),
|
||||
show_index=False,
|
||||
title=f"{coin} Treasury Accounts",
|
||||
title=f"{symbol} Treasury Accounts",
|
||||
)
|
||||
else:
|
||||
console.print("\nTreasury accounts not found\n")
|
||||
@@ -723,7 +700,7 @@ def display_fundraising(
|
||||
startangle=90,
|
||||
colors=theme.get_colors()[1:4],
|
||||
)
|
||||
ax.set_title(f"{coin} Fundraising Distribution")
|
||||
ax.set_title(f"{symbol} Fundraising Distribution")
|
||||
if obbff.USE_ION:
|
||||
plt.ion()
|
||||
plt.show()
|
||||
@@ -734,7 +711,7 @@ def display_fundraising(
|
||||
df_details,
|
||||
headers=list(df_details.columns),
|
||||
show_index=False,
|
||||
title=f"{coin} Fundraising Details",
|
||||
title=f"{symbol} Fundraising Details",
|
||||
)
|
||||
else:
|
||||
console.print("\nFundraising details not found\n")
|
||||
|
||||
@@ -48,11 +48,22 @@ BASE_INFO = [
|
||||
]
|
||||
|
||||
|
||||
def format_df(df: pd.DataFrame):
|
||||
df["Potential Market Cap ($)"] = df.apply(
|
||||
lambda x: f"{int(x['Potential Market Cap ($)']):n}", axis=1
|
||||
)
|
||||
|
||||
df["Current Market Cap ($)"] = df.apply(
|
||||
lambda x: f"{int(x['Current Market Cap ($)']):n}", axis=1
|
||||
)
|
||||
return df
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_coin_potential_returns(
|
||||
main_coin: str,
|
||||
vs: Union[str, None] = None,
|
||||
top: Union[int, None] = None,
|
||||
limit: Union[int, None] = None,
|
||||
price: Union[int, None] = None,
|
||||
) -> pd.DataFrame:
|
||||
"""Fetch data to calculate potential returns of a certain coin. [Source: CoinGecko]
|
||||
@@ -63,7 +74,7 @@ def get_coin_potential_returns(
|
||||
Coin loaded to check potential returns for (e.g., algorand)
|
||||
vs : str | None
|
||||
Coin to compare main_coin with (e.g., bitcoin)
|
||||
top : int | None
|
||||
limit : int | None
|
||||
Number of coins with highest market cap to compare main_coin with (e.g., 5)
|
||||
price
|
||||
Target price of main_coin to check potential returns (e.g., 5)
|
||||
@@ -84,7 +95,7 @@ def get_coin_potential_returns(
|
||||
"Potential Market Cap ($)",
|
||||
"Change (%)",
|
||||
]
|
||||
if top and top > 0: # user wants to compare with top coins
|
||||
if limit and limit > 0: # user wants to compare with top coins
|
||||
data = client.get_price(
|
||||
ids=f"{main_coin}",
|
||||
vs_currencies="usd",
|
||||
@@ -94,7 +105,7 @@ def get_coin_potential_returns(
|
||||
include_last_updated_at=False,
|
||||
)
|
||||
top_coins_data = client.get_coins_markets(
|
||||
vs_currency="usd", per_page=top, order="market_cap_desc"
|
||||
vs_currency="usd", per_page=limit, order="market_cap_desc"
|
||||
)
|
||||
main_coin_data = data[main_coin]
|
||||
diff_arr = []
|
||||
@@ -116,10 +127,11 @@ def get_coin_potential_returns(
|
||||
market_cap_difference_percentage,
|
||||
]
|
||||
)
|
||||
return pd.DataFrame(
|
||||
df = pd.DataFrame(
|
||||
data=diff_arr,
|
||||
columns=COLUMNS,
|
||||
)
|
||||
return format_df(df)
|
||||
|
||||
if vs: # user passed a coin
|
||||
data = client.get_price(
|
||||
@@ -140,7 +152,7 @@ def get_coin_potential_returns(
|
||||
future_price = main_coin_data["usd"] * (
|
||||
1 + market_cap_difference_percentage / 100
|
||||
)
|
||||
return pd.DataFrame(
|
||||
df = pd.DataFrame(
|
||||
data=[
|
||||
[
|
||||
main_coin,
|
||||
@@ -154,6 +166,7 @@ def get_coin_potential_returns(
|
||||
],
|
||||
columns=COLUMNS,
|
||||
)
|
||||
return format_df(df)
|
||||
|
||||
if price and price > 0: # user passed a price
|
||||
data = client.get_price(
|
||||
@@ -175,7 +188,7 @@ def get_coin_potential_returns(
|
||||
future_price = main_coin_data["usd"] * (
|
||||
1 + market_cap_difference_percentage / 100
|
||||
)
|
||||
return pd.DataFrame(
|
||||
df = pd.DataFrame(
|
||||
data=[
|
||||
[
|
||||
main_coin,
|
||||
@@ -189,24 +202,25 @@ def get_coin_potential_returns(
|
||||
],
|
||||
columns=COLUMNS,
|
||||
)
|
||||
return format_df(df)
|
||||
|
||||
return pd.DataFrame()
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def check_coin(coin_id: str):
|
||||
def check_coin(symbol: str):
|
||||
coins = read_file_data("coingecko_coins.json")
|
||||
for coin in coins:
|
||||
if coin["id"] == coin_id:
|
||||
if coin["id"] == symbol:
|
||||
return coin["id"]
|
||||
if coin["symbol"] == coin_id:
|
||||
if coin["symbol"] == symbol:
|
||||
return coin["id"]
|
||||
return None
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_coin_market_chart(
|
||||
coin_id: str = "", vs_currency: str = "usd", days: int = 30, **kwargs: Any
|
||||
symbol: str = "", vs_currency: str = "usd", days: int = 30, **kwargs: Any
|
||||
) -> pd.DataFrame:
|
||||
"""Get prices for given coin. [Source: CoinGecko]
|
||||
|
||||
@@ -225,7 +239,7 @@ def get_coin_market_chart(
|
||||
Columns: time, price, currency
|
||||
"""
|
||||
client = CoinGeckoAPI()
|
||||
prices = client.get_coin_market_chart_by_id(coin_id, vs_currency, days, **kwargs)
|
||||
prices = client.get_coin_market_chart_by_id(symbol, vs_currency, days, **kwargs)
|
||||
prices = prices["prices"]
|
||||
df = pd.DataFrame(data=prices, columns=["time", "price"])
|
||||
df["time"] = pd.to_datetime(df.time, unit="ms")
|
||||
|
||||
@@ -3,7 +3,7 @@ __docformat__ = "numpy"
|
||||
|
||||
import logging
|
||||
import os
|
||||
from typing import Union
|
||||
from typing import Optional
|
||||
from pandas.plotting import register_matplotlib_converters
|
||||
import openbb_terminal.cryptocurrency.due_diligence.pycoingecko_model as gecko
|
||||
from openbb_terminal.cryptocurrency import cryptocurrency_helpers
|
||||
@@ -18,36 +18,28 @@ register_matplotlib_converters()
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_coin_potential_returns(
|
||||
main_coin: str,
|
||||
vs: Union[str, None] = None,
|
||||
top: Union[int, None] = None,
|
||||
price: Union[int, None] = None,
|
||||
to_symbol: str,
|
||||
from_symbol: Optional[str] = None,
|
||||
limit: Optional[int] = None,
|
||||
price: Optional[int] = None,
|
||||
export: str = "",
|
||||
) -> None:
|
||||
"""Displays potential returns of a certain coin. [Source: CoinGecko]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
main_coin : str
|
||||
to_symbol : str
|
||||
Coin loaded to check potential returns for (e.g., algorand)
|
||||
vs : str | None
|
||||
from_symbol : str | None
|
||||
Coin to compare main_coin with (e.g., bitcoin)
|
||||
top : int | None
|
||||
limit : int | None
|
||||
Number of coins with highest market cap to compare main_coin with (e.g., 5)
|
||||
price
|
||||
Target price of main_coin to check potential returns (e.g., 5)
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
df = gecko.get_coin_potential_returns(main_coin, vs, top, price)
|
||||
|
||||
df["Potential Market Cap ($)"] = df.apply(
|
||||
lambda x: f"{int(x['Potential Market Cap ($)']):n}", axis=1
|
||||
)
|
||||
|
||||
df["Current Market Cap ($)"] = df.apply(
|
||||
lambda x: f"{int(x['Current Market Cap ($)']):n}", axis=1
|
||||
)
|
||||
df = gecko.get_coin_potential_returns(to_symbol, from_symbol, limit, price)
|
||||
|
||||
print_rich_table(
|
||||
df, headers=list(df.columns), show_index=False, title="Potential Coin Returns"
|
||||
|
||||
@@ -12,24 +12,24 @@ from openbb_terminal.cryptocurrency.discovery.pycoingecko_model import read_file
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def get_slug(coin: str) -> str:
|
||||
def get_slug(symbol: str) -> str:
|
||||
"""
|
||||
Get Santiment slug mapping and return corresponding slug for a given coin
|
||||
"""
|
||||
df = pd.DataFrame(read_file_data("santiment_slugs.json"))
|
||||
|
||||
slug = df.loc[df["ticker"] == coin.upper()]["slug"].values[0]
|
||||
slug = df.loc[df["ticker"] == symbol.upper()]["slug"].values[0]
|
||||
|
||||
return slug
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_github_activity(
|
||||
coin: str,
|
||||
symbol: str,
|
||||
dev_activity: bool,
|
||||
interval: str,
|
||||
start: str,
|
||||
end: str,
|
||||
start_date: str,
|
||||
end_date: str,
|
||||
) -> pd.DataFrame:
|
||||
"""Returns a list of developer activity for a given coin and time interval.
|
||||
|
||||
@@ -37,13 +37,13 @@ def get_github_activity(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
coin : str
|
||||
symbol : str
|
||||
Crypto symbol to check github activity
|
||||
dev_activity: bool
|
||||
Whether to filter only for development activity
|
||||
start : int
|
||||
start_date : int
|
||||
Initial date like string (e.g., 2021-10-01)
|
||||
end : int
|
||||
end_date : int
|
||||
End date like string (e.g., 2021-10-01)
|
||||
interval : str
|
||||
Interval frequency (e.g., 1d)
|
||||
@@ -56,15 +56,17 @@ def get_github_activity(
|
||||
|
||||
activity_type = "dev_activity" if dev_activity else "github_activity"
|
||||
|
||||
slug = get_slug(coin)
|
||||
slug = get_slug(symbol)
|
||||
|
||||
headers = {
|
||||
"Content-Type": "application/graphql",
|
||||
"Authorization": f"Apikey {cfg.API_SANTIMENT_KEY}",
|
||||
}
|
||||
|
||||
# pylint: disable=line-too-long
|
||||
data = f'\n{{ getMetric(metric: "{activity_type}"){{ timeseriesData( slug: "{slug}" from: "{start}" to: "{end}" interval: "{interval}"){{ datetime value }} }} }}' # noqa: E501
|
||||
data = (
|
||||
f'\n{{ getMetric(metric: "{activity_type}"){{ timeseriesData( slug: "{slug}"'
|
||||
f'from: "{start_date}" to: "{end_date}" interval: "{interval}"){{ datetime value }} }} }}'
|
||||
)
|
||||
|
||||
response = requests.post(
|
||||
"https://api.santiment.net/graphql", headers=headers, data=data
|
||||
@@ -79,7 +81,7 @@ def get_github_activity(
|
||||
df["datetime"] = pd.to_datetime(df["datetime"])
|
||||
df = df.set_index("datetime")
|
||||
else:
|
||||
console.print(f"Could not find github activity found for {coin}\n")
|
||||
console.print(f"Could not find github activity found for {symbol}\n")
|
||||
|
||||
elif response.status_code == 400:
|
||||
if "Apikey" in response.json()["errors"]["details"]:
|
||||
|
||||
@@ -25,10 +25,12 @@ logger = logging.getLogger(__name__)
|
||||
@log_start_end(log=logger)
|
||||
@check_api_key(["API_SANTIMENT_KEY"])
|
||||
def display_github_activity(
|
||||
coin: str,
|
||||
start: str = (datetime.now() - timedelta(days=365)).strftime("%Y-%m-%dT%H:%M:%SZ"),
|
||||
symbol: str,
|
||||
start_date: str = (datetime.now() - timedelta(days=365)).strftime(
|
||||
"%Y-%m-%dT%H:%M:%SZ"
|
||||
),
|
||||
dev_activity: bool = False,
|
||||
end: str = (datetime.now()).strftime("%Y-%m-%dT%H:%M:%SZ"),
|
||||
end_date: str = (datetime.now()).strftime("%Y-%m-%dT%H:%M:%SZ"),
|
||||
interval: str = "1d",
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
@@ -39,13 +41,13 @@ def display_github_activity(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
coin : str
|
||||
symbol : str
|
||||
Crypto symbol to check github activity
|
||||
dev_activity: bool
|
||||
Whether to filter only for development activity
|
||||
start : int
|
||||
start_date : int
|
||||
Initial date like string (e.g., 2021-10-01)
|
||||
end : int
|
||||
end_date : int
|
||||
End date like string (e.g., 2021-10-01)
|
||||
interval : str
|
||||
Interval frequency (some possible values are: 1h, 1d, 1w)
|
||||
@@ -56,7 +58,11 @@ def display_github_activity(
|
||||
"""
|
||||
|
||||
df = get_github_activity(
|
||||
coin=coin, dev_activity=dev_activity, start=start, end=end, interval=interval
|
||||
symbol=symbol,
|
||||
dev_activity=dev_activity,
|
||||
start_date=start_date,
|
||||
end_date=end_date,
|
||||
interval=interval,
|
||||
)
|
||||
|
||||
if df.empty:
|
||||
@@ -72,8 +78,8 @@ def display_github_activity(
|
||||
|
||||
ax.plot(df.index, df["value"])
|
||||
|
||||
ax.set_title(f"{coin}'s Github activity over time")
|
||||
ax.set_ylabel(f"{coin}'s Activity count")
|
||||
ax.set_title(f"{symbol}'s Github activity over time")
|
||||
ax.set_ylabel(f"{symbol}'s Activity count")
|
||||
ax.set_xlim(df.index[0], df.index[-1])
|
||||
|
||||
theme.style_primary_axis(ax)
|
||||
|
||||
@@ -13,7 +13,7 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_nft_today_drops(num: int, export: str):
|
||||
def display_nft_today_drops(num: int = 5, export: str = ""):
|
||||
"""Display NFT today drops. [Source: nftcalendar.io]
|
||||
|
||||
Parameters
|
||||
@@ -43,7 +43,7 @@ def display_nft_today_drops(num: int, export: str):
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_nft_upcoming_drops(num: int, export: str):
|
||||
def display_nft_upcoming_drops(num: int = 5, export: str = ""):
|
||||
"""Display NFT upcoming drops. [Source: nftcalendar.io]
|
||||
|
||||
Parameters
|
||||
@@ -73,7 +73,7 @@ def display_nft_upcoming_drops(num: int, export: str):
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_nft_ongoing_drops(num: int, export: str):
|
||||
def display_nft_ongoing_drops(num: int = 5, export: str = ""):
|
||||
"""Display NFT ongoing drops. [Source: nftcalendar.io]
|
||||
|
||||
Parameters
|
||||
@@ -103,7 +103,7 @@ def display_nft_ongoing_drops(num: int, export: str):
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_nft_newest_drops(num: int, export: str):
|
||||
def display_nft_newest_drops(num: int = 5, export: str = ""):
|
||||
"""Display NFT newest drops. [Source: nftcalendar.io]
|
||||
|
||||
Parameters
|
||||
|
||||
@@ -13,6 +13,9 @@ import requests
|
||||
from requests.adapters import HTTPAdapter
|
||||
from requests.exceptions import HTTPError
|
||||
|
||||
from openbb_terminal.cryptocurrency.dataframe_helpers import (
|
||||
prettify_column_names,
|
||||
)
|
||||
from openbb_terminal import config_terminal as cfg
|
||||
from openbb_terminal.rich_config import console
|
||||
from openbb_terminal.decorators import log_start_end
|
||||
@@ -224,15 +227,16 @@ def get_erc20_tokens() -> pd.DataFrame:
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def find_token_address(token: str) -> Optional[str]:
|
||||
def find_token_address(symbol: str) -> Optional[str]:
|
||||
"""Helper methods that search for ERC20 coin base on provided symbol or token address.
|
||||
If erc20 token address is provided, then function checks if it's proper address and returns it back.
|
||||
In other case mapping data is loaded from file (or cache), and function lookup for belonging token address.
|
||||
If erc20 token address is provided, then checks if it's proper address and returns it back.
|
||||
In other case mapping data is loaded from file, and lookup for belonging token address.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
token: str
|
||||
ERC20 token symbol e.g. UNI, SUSHI, ETH, WBTC or token address e.g. 0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
|
||||
symbol: str
|
||||
ERC20 token symbol e.g. UNI, SUSHI, ETH, WBTC or token address e.g.
|
||||
0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -240,13 +244,13 @@ def find_token_address(token: str) -> Optional[str]:
|
||||
ERC20 token address, or None if nothing found.
|
||||
"""
|
||||
|
||||
if token.startswith("0x") and len(token) >= 38:
|
||||
return token
|
||||
if symbol.startswith("0x") and len(symbol) >= 38:
|
||||
return symbol
|
||||
|
||||
if token == "ETH":
|
||||
return token
|
||||
if symbol == "ETH":
|
||||
return symbol
|
||||
|
||||
token = "WBTC" if token == "BTC" else token
|
||||
token = "WBTC" if symbol == "BTC" else symbol
|
||||
tokens_map: pd.DataFrame = get_erc20_tokens()
|
||||
|
||||
found_token = tokens_map.loc[tokens_map["symbol"] == token]
|
||||
@@ -259,7 +263,10 @@ def find_token_address(token: str) -> Optional[str]:
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_dex_trades_by_exchange(
|
||||
trade_amount_currency: str = "USD", limit: int = 90
|
||||
trade_amount_currency: str = "USD",
|
||||
limit: int = 90,
|
||||
sortby: str = "tradeAmount",
|
||||
ascend: bool = True,
|
||||
) -> pd.DataFrame:
|
||||
"""Get trades on Decentralized Exchanges aggregated by DEX [Source: https://graphql.bitquery.io/]
|
||||
|
||||
@@ -270,6 +277,10 @@ def get_dex_trades_by_exchange(
|
||||
limit: int
|
||||
Last n days to query data. Maximum 365 (bigger numbers can cause timeouts
|
||||
on server side)
|
||||
sortby: str
|
||||
Key by which to sort data
|
||||
ascend: bool
|
||||
Flag to sort data ascending
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -309,16 +320,20 @@ def get_dex_trades_by_exchange(
|
||||
df = _extract_dex_trades(data)
|
||||
df.columns = ["trades", "tradeAmount", "exchange"]
|
||||
df = df[~df["exchange"].isin([None, np.NaN, ""])]
|
||||
return df[["exchange", "trades", "tradeAmount"]].sort_values(
|
||||
df = df[["exchange", "trades", "tradeAmount"]].sort_values(
|
||||
by="tradeAmount", ascending=True
|
||||
)
|
||||
df = df.sort_values(by=sortby, ascending=ascend)
|
||||
df.columns = prettify_column_names(df.columns)
|
||||
return df
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_dex_trades_monthly(
|
||||
trade_amount_currency: str = "USD", limit: int = 90
|
||||
trade_amount_currency: str = "USD", limit: int = 90, ascend: bool = True
|
||||
) -> pd.DataFrame:
|
||||
"""Get list of trades on Decentralized Exchanges monthly aggregated. [Source: https://graphql.bitquery.io/]
|
||||
"""Get list of trades on Decentralized Exchanges monthly aggregated.
|
||||
[Source: https://graphql.bitquery.io/]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
@@ -327,6 +342,8 @@ def get_dex_trades_monthly(
|
||||
limit: int
|
||||
Last n days to query data. Maximum 365 (bigger numbers can cause timeouts
|
||||
on server side)
|
||||
ascend: bool
|
||||
Flag to sort data ascending
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -372,14 +389,19 @@ def get_dex_trades_monthly(
|
||||
lambda x: datetime.date(int(x["date.year"]), int(x["date.month"]), 1), axis=1
|
||||
)
|
||||
df.rename(columns={"count": "trades"}, inplace=True)
|
||||
return df[["date", "trades", "tradeAmount"]]
|
||||
df = df[["date", "trades", "tradeAmount"]]
|
||||
df = df.sort_values(by="date", ascending=ascend)
|
||||
df.columns = prettify_column_names(df.columns)
|
||||
return df
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_daily_dex_volume_for_given_pair(
|
||||
limit: int = 100,
|
||||
token: str = "UNI",
|
||||
symbol: str = "UNI",
|
||||
vs: str = "USDT",
|
||||
sortby: str = "date",
|
||||
ascend: bool = True,
|
||||
) -> pd.DataFrame:
|
||||
"""Get daily volume for given pair [Source: https://graphql.bitquery.io/]
|
||||
|
||||
@@ -387,10 +409,14 @@ def get_daily_dex_volume_for_given_pair(
|
||||
-------
|
||||
limit: int
|
||||
Last n days to query data
|
||||
token: str
|
||||
symbol: str
|
||||
ERC20 token symbol
|
||||
vs: str
|
||||
Quote currency.
|
||||
sortby: str
|
||||
Key by which to sort data
|
||||
ascend: bool
|
||||
Flag to sort data ascending
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -402,7 +428,7 @@ def get_daily_dex_volume_for_given_pair(
|
||||
"%Y-%m-%d"
|
||||
)
|
||||
|
||||
base, quote = find_token_address(token), find_token_address(vs)
|
||||
base, quote = find_token_address(symbol), find_token_address(vs)
|
||||
if not base or not quote:
|
||||
raise ValueError("Provided coin or quote currency doesn't exist\n")
|
||||
|
||||
@@ -463,7 +489,7 @@ def get_daily_dex_volume_for_given_pair(
|
||||
"quote",
|
||||
"exchange",
|
||||
]
|
||||
return df[
|
||||
df = df[
|
||||
[
|
||||
"date",
|
||||
"exchange",
|
||||
@@ -476,22 +502,31 @@ def get_daily_dex_volume_for_given_pair(
|
||||
"tradeAmount",
|
||||
"trades",
|
||||
]
|
||||
].sort_values(by="date", ascending=False)
|
||||
]
|
||||
df = df.sort_values(by=sortby, ascending=ascend)
|
||||
df.columns = prettify_column_names(df.columns)
|
||||
return df
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_token_volume_on_dexes(
|
||||
token: str = "UNI",
|
||||
symbol: str = "UNI",
|
||||
trade_amount_currency: str = "USD",
|
||||
sortby: str = "tradeAmount",
|
||||
ascend: bool = True,
|
||||
) -> pd.DataFrame:
|
||||
"""Get token volume on different Decentralized Exchanges. [Source: https://graphql.bitquery.io/]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
token: str
|
||||
symbol: str
|
||||
ERC20 token symbol.
|
||||
trade_amount_currency: str
|
||||
Currency to display trade amount in.
|
||||
sortby: str
|
||||
Key by which to sort data
|
||||
ascend: bool
|
||||
Flag to sort data ascending
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -502,9 +537,9 @@ def get_token_volume_on_dexes(
|
||||
if trade_amount_currency not in CURRENCIES:
|
||||
trade_amount_currency = "USD"
|
||||
|
||||
token_address = find_token_address(token)
|
||||
token_address = find_token_address(symbol)
|
||||
if token_address is None:
|
||||
raise ValueError(f"Couldn't find token with symbol {token}\n")
|
||||
raise ValueError(f"Couldn't find token with symbol {symbol}\n")
|
||||
query = f"""
|
||||
{{
|
||||
ethereum {{
|
||||
@@ -538,21 +573,32 @@ def get_token_volume_on_dexes(
|
||||
|
||||
df = _extract_dex_trades(data)[["exchange.fullName", "tradeAmount", "count"]]
|
||||
df.columns = LT_FILTERS
|
||||
return df[~df["exchange"].str.startswith("<")].sort_values(
|
||||
by="tradeAmount", ascending=False
|
||||
)
|
||||
df = df[~df["exchange"].str.startswith("<")]
|
||||
df = df.sort_values(by=sortby, ascending=ascend)
|
||||
df.columns = prettify_column_names(df.columns)
|
||||
return df
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_ethereum_unique_senders(interval: str = "day", limit: int = 90) -> pd.DataFrame:
|
||||
def get_ethereum_unique_senders(
|
||||
interval: str = "day",
|
||||
limit: int = 90,
|
||||
sortby: str = "tradeAmount",
|
||||
ascend: bool = True,
|
||||
) -> pd.DataFrame:
|
||||
"""Get number of unique ethereum addresses which made a transaction in given time interval.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
interval: str
|
||||
Time interval in which count unique ethereum addresses which made transaction. day, month or week.
|
||||
Time interval in which count unique ethereum addresses which made transaction. day,
|
||||
month or week.
|
||||
limit: int
|
||||
Number of records for data query.
|
||||
sortby: str
|
||||
Key by which to sort data
|
||||
ascend: bool
|
||||
Flag to sort data ascending
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -601,12 +647,19 @@ def get_ethereum_unique_senders(interval: str = "day", limit: int = 90) -> pd.Da
|
||||
|
||||
df = pd.DataFrame(data["ethereum"]["transactions"])
|
||||
df["date"] = df["date"].apply(lambda x: x["date"])
|
||||
return df[UEAT_FILTERS]
|
||||
df = df[UEAT_FILTERS]
|
||||
df = df.sort_values(by=sortby, ascending=ascend)
|
||||
df.columns = prettify_column_names(df.columns)
|
||||
return df
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_most_traded_pairs(
|
||||
network: str = "ethereum", exchange: str = "Uniswap", limit: int = 90
|
||||
network: str = "ethereum",
|
||||
exchange: str = "Uniswap",
|
||||
limit: int = 90,
|
||||
sortby: str = "tradeAmount",
|
||||
ascend: bool = True,
|
||||
) -> pd.DataFrame:
|
||||
"""Get most traded crypto pairs on given decentralized exchange in chosen time period.
|
||||
[Source: https://graphql.bitquery.io/]
|
||||
@@ -619,6 +672,10 @@ def get_most_traded_pairs(
|
||||
Decentralized exchange name
|
||||
limit:
|
||||
Number of days taken into calculation account.
|
||||
sortby: str
|
||||
Key by which to sort data
|
||||
ascend: bool
|
||||
Flag to sort data ascending
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -656,12 +713,19 @@ def get_most_traded_pairs(
|
||||
|
||||
df = _extract_dex_trades(data)
|
||||
df.columns = ["trades", "tradeAmount", "base", "quoted"]
|
||||
return df[TTCP_FILTERS]
|
||||
df = df[TTCP_FILTERS]
|
||||
df = df.sort_values(by=sortby, ascending=ascend)
|
||||
df.columns = prettify_column_names(df.columns)
|
||||
return df
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_spread_for_crypto_pair(
|
||||
token: str = "WETH", vs: str = "USDT", limit: int = 30
|
||||
symbol: str = "WETH",
|
||||
vs: str = "USDT",
|
||||
limit: int = 30,
|
||||
sortby: str = "tradeAmount",
|
||||
ascend: bool = True,
|
||||
) -> pd.DataFrame:
|
||||
"""Get an average bid and ask prices, average spread for given crypto pair for chosen time period.
|
||||
[Source: https://graphql.bitquery.io/]
|
||||
@@ -670,10 +734,14 @@ def get_spread_for_crypto_pair(
|
||||
----------
|
||||
limit: int
|
||||
Last n days to query data
|
||||
token: str
|
||||
symbol: str
|
||||
ERC20 token symbol
|
||||
vs: str
|
||||
Quoted currency.
|
||||
sortby: str
|
||||
Key by which to sort data
|
||||
ascend: bool
|
||||
Flag to sort data ascending
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -682,7 +750,7 @@ def get_spread_for_crypto_pair(
|
||||
"""
|
||||
|
||||
dt = (datetime.date.today() - datetime.timedelta(limit)).strftime("%Y-%m-%d")
|
||||
base, quote = find_token_address(token), find_token_address(vs)
|
||||
base, quote = find_token_address(symbol), find_token_address(vs)
|
||||
|
||||
if not base or not quote:
|
||||
raise ValueError("Provided coin or quote currency doesn't exist\n")
|
||||
@@ -729,7 +797,7 @@ def get_spread_for_crypto_pair(
|
||||
daily_spread["dailySpread"] = abs(
|
||||
daily_spread["averageBidPrice"] - daily_spread["averageAskPrice"]
|
||||
)
|
||||
return daily_spread[
|
||||
df = daily_spread[
|
||||
[
|
||||
"date",
|
||||
"baseCurrency",
|
||||
@@ -738,7 +806,10 @@ def get_spread_for_crypto_pair(
|
||||
"averageBidPrice",
|
||||
"averageAskPrice",
|
||||
]
|
||||
].sort_values(by="date", ascending=True)
|
||||
]
|
||||
df = df.sort_values(by=sortby, ascending=ascend)
|
||||
df.columns = prettify_column_names(df.columns)
|
||||
return df
|
||||
|
||||
|
||||
POSSIBLE_CRYPTOS = list(get_erc20_tokens()["symbol"].unique())
|
||||
|
||||
@@ -5,7 +5,6 @@ import logging
|
||||
import os
|
||||
|
||||
from openbb_terminal.cryptocurrency.dataframe_helpers import (
|
||||
prettify_column_names,
|
||||
lambda_very_long_number_formatter,
|
||||
)
|
||||
from openbb_terminal.cryptocurrency.onchain import bitquery_model
|
||||
@@ -24,10 +23,11 @@ def display_dex_trades(
|
||||
top: int = 20,
|
||||
days: int = 90,
|
||||
sortby: str = "tradeAmount",
|
||||
descend: bool = False,
|
||||
ascend: bool = True,
|
||||
export: str = "",
|
||||
) -> None:
|
||||
"""Trades on Decentralized Exchanges aggregated by DEX or Month [Source: https://graphql.bitquery.io/]
|
||||
"""Trades on Decentralized Exchanges aggregated by DEX or Month
|
||||
[Source: https://graphql.bitquery.io/]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
@@ -39,8 +39,8 @@ def display_dex_trades(
|
||||
Number of records to display
|
||||
sortby: str
|
||||
Key by which to sort data
|
||||
descend: bool
|
||||
Flag to sort data descending
|
||||
ascend: bool
|
||||
Flag to sort data ascending
|
||||
days: int
|
||||
Last n days to query data. Maximum 365 (bigger numbers can cause timeouts
|
||||
on server side)
|
||||
@@ -49,13 +49,11 @@ def display_dex_trades(
|
||||
"""
|
||||
|
||||
if kind == "time":
|
||||
df = bitquery_model.get_dex_trades_monthly(trade_amount_currency, days)
|
||||
if not df.empty:
|
||||
df = df.sort_values(by="date", ascending=descend)
|
||||
df = bitquery_model.get_dex_trades_monthly(trade_amount_currency, days, ascend)
|
||||
else:
|
||||
df = bitquery_model.get_dex_trades_by_exchange(trade_amount_currency, days)
|
||||
if not df.empty:
|
||||
df = df.sort_values(by=sortby, ascending=descend)
|
||||
df = bitquery_model.get_dex_trades_by_exchange(
|
||||
trade_amount_currency, days, sortby, ascend
|
||||
)
|
||||
|
||||
if not df.empty:
|
||||
df_data = df.copy()
|
||||
@@ -64,8 +62,6 @@ def display_dex_trades(
|
||||
lambda x: lambda_very_long_number_formatter(x)
|
||||
)
|
||||
|
||||
df.columns = prettify_column_names(df.columns)
|
||||
|
||||
print_rich_table(
|
||||
df.head(top),
|
||||
headers=list(df.columns),
|
||||
@@ -84,11 +80,11 @@ def display_dex_trades(
|
||||
@log_start_end(log=logger)
|
||||
@check_api_key(["API_BITQUERY_KEY"])
|
||||
def display_daily_volume_for_given_pair(
|
||||
token: str = "WBTC",
|
||||
symbol: str = "WBTC",
|
||||
vs: str = "USDT",
|
||||
top: int = 20,
|
||||
sortby: str = "date",
|
||||
descend: bool = False,
|
||||
ascend: bool = True,
|
||||
export: str = "",
|
||||
) -> None:
|
||||
"""Display daily volume for given pair
|
||||
@@ -96,7 +92,7 @@ def display_daily_volume_for_given_pair(
|
||||
|
||||
Parameters
|
||||
----------
|
||||
token: str
|
||||
symbol: str
|
||||
ERC20 token symbol or address
|
||||
vs: str
|
||||
Quote currency.
|
||||
@@ -104,10 +100,11 @@ def display_daily_volume_for_given_pair(
|
||||
Number of records to display
|
||||
sortby: str
|
||||
Key by which to sort data
|
||||
descend: bool
|
||||
Flag to sort data descending
|
||||
ascend: bool
|
||||
Flag to sort data ascending
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
|
||||
Returns
|
||||
-------
|
||||
pd.DataFrame
|
||||
@@ -115,21 +112,21 @@ def display_daily_volume_for_given_pair(
|
||||
"""
|
||||
|
||||
df = bitquery_model.get_daily_dex_volume_for_given_pair(
|
||||
token=token,
|
||||
symbol=symbol,
|
||||
vs=vs,
|
||||
limit=top,
|
||||
sortby=sortby,
|
||||
ascend=ascend,
|
||||
)
|
||||
|
||||
if df.empty:
|
||||
return
|
||||
df = df.sort_values(by=sortby, ascending=descend)
|
||||
|
||||
df_data = df.copy()
|
||||
|
||||
df[["tradeAmount", "trades"]] = df[["tradeAmount", "trades"]].applymap(
|
||||
lambda x: lambda_very_long_number_formatter(x)
|
||||
)
|
||||
df.columns = prettify_column_names(df.columns)
|
||||
|
||||
print_rich_table(
|
||||
df.head(top),
|
||||
@@ -149,18 +146,19 @@ def display_daily_volume_for_given_pair(
|
||||
@log_start_end(log=logger)
|
||||
@check_api_key(["API_BITQUERY_KEY"])
|
||||
def display_dex_volume_for_token(
|
||||
token: str = "WBTC",
|
||||
symbol: str = "WBTC",
|
||||
trade_amount_currency: str = "USD",
|
||||
top: int = 10,
|
||||
sortby: str = "tradeAmount",
|
||||
descend: bool = False,
|
||||
ascend: bool = True,
|
||||
export: str = "",
|
||||
) -> None:
|
||||
"""Display token volume on different Decentralized Exchanges. [Source: https://graphql.bitquery.io/]
|
||||
"""Display token volume on different Decentralized Exchanges.
|
||||
[Source: https://graphql.bitquery.io/]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
token: str
|
||||
symbol: str
|
||||
ERC20 token symbol or address
|
||||
trade_amount_currency: str
|
||||
Currency of displayed trade amount. Default: USD
|
||||
@@ -168,8 +166,8 @@ def display_dex_volume_for_token(
|
||||
Number of records to display
|
||||
sortby: str
|
||||
Key by which to sort data
|
||||
descend: bool
|
||||
Flag to sort data descending
|
||||
ascend: bool
|
||||
Flag to sort data ascending
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
Returns
|
||||
@@ -179,18 +177,17 @@ def display_dex_volume_for_token(
|
||||
"""
|
||||
|
||||
df = bitquery_model.get_token_volume_on_dexes(
|
||||
token=token, trade_amount_currency=trade_amount_currency
|
||||
symbol=symbol,
|
||||
trade_amount_currency=trade_amount_currency,
|
||||
sortby=sortby,
|
||||
ascend=ascend,
|
||||
)
|
||||
if not df.empty:
|
||||
df = df.sort_values(by=sortby, ascending=descend)
|
||||
|
||||
df_data = df.copy()
|
||||
df[["tradeAmount", "trades"]] = df[["tradeAmount", "trades"]].applymap(
|
||||
lambda x: lambda_very_long_number_formatter(x)
|
||||
)
|
||||
|
||||
df.columns = prettify_column_names(df.columns)
|
||||
|
||||
print_rich_table(
|
||||
df.head(top),
|
||||
headers=list(df.columns),
|
||||
@@ -212,7 +209,7 @@ def display_ethereum_unique_senders(
|
||||
interval: str = "days",
|
||||
limit: int = 10,
|
||||
sortby: str = "date",
|
||||
descend: bool = False,
|
||||
ascend: bool = True,
|
||||
export: str = "",
|
||||
) -> None:
|
||||
"""Display number of unique ethereum addresses which made a transaction in given time interval
|
||||
@@ -229,8 +226,8 @@ def display_ethereum_unique_senders(
|
||||
For better user experience maximum time period in days is equal to 90.
|
||||
sortby: str
|
||||
Key by which to sort data
|
||||
descend: bool
|
||||
Flag to sort data descending
|
||||
ascend: bool
|
||||
Flag to sort data ascending
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
Returns
|
||||
@@ -239,17 +236,13 @@ def display_ethereum_unique_senders(
|
||||
Number of unique ethereum addresses which made a transaction in given time interval
|
||||
"""
|
||||
|
||||
df = bitquery_model.get_ethereum_unique_senders(interval, limit)
|
||||
df = bitquery_model.get_ethereum_unique_senders(interval, limit, sortby, ascend)
|
||||
if not df.empty:
|
||||
|
||||
df = df.sort_values(by=sortby, ascending=descend)
|
||||
|
||||
df[["uniqueSenders", "transactions", "maximumGasPrice"]] = df[
|
||||
["uniqueSenders", "transactions", "maximumGasPrice"]
|
||||
].applymap(lambda x: lambda_very_long_number_formatter(x))
|
||||
|
||||
df_data = df.copy()
|
||||
df.columns = prettify_column_names(df.columns)
|
||||
|
||||
print_rich_table(
|
||||
df,
|
||||
@@ -273,7 +266,7 @@ def display_most_traded_pairs(
|
||||
days: int = 10,
|
||||
top: int = 10,
|
||||
sortby: str = "tradeAmount",
|
||||
descend: bool = False,
|
||||
ascend: bool = True,
|
||||
export: str = "",
|
||||
) -> None:
|
||||
"""Display most traded crypto pairs on given decentralized exchange in chosen time period.
|
||||
@@ -287,8 +280,8 @@ def display_most_traded_pairs(
|
||||
Number of days taken into calculation account.
|
||||
sortby: str
|
||||
Key by which to sort data
|
||||
descend: bool
|
||||
Flag to sort data descending
|
||||
ascend: bool
|
||||
Flag to sort data ascending
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
Returns
|
||||
@@ -297,14 +290,14 @@ def display_most_traded_pairs(
|
||||
Most traded crypto pairs on given decentralized exchange in chosen time period.
|
||||
"""
|
||||
|
||||
df = bitquery_model.get_most_traded_pairs(exchange=exchange, limit=days)
|
||||
df = bitquery_model.get_most_traded_pairs(
|
||||
exchange=exchange, limit=days, sortby=sortby, ascend=ascend
|
||||
)
|
||||
if not df.empty:
|
||||
df = df.sort_values(by=sortby, ascending=descend)
|
||||
df_data = df.copy()
|
||||
df[["tradeAmount", "trades"]] = df[["tradeAmount", "trades"]].applymap(
|
||||
lambda x: lambda_very_long_number_formatter(x)
|
||||
)
|
||||
df.columns = prettify_column_names(df.columns)
|
||||
|
||||
print_rich_table(
|
||||
df.head(top),
|
||||
@@ -324,28 +317,28 @@ def display_most_traded_pairs(
|
||||
@log_start_end(log=logger)
|
||||
@check_api_key(["API_BITQUERY_KEY"])
|
||||
def display_spread_for_crypto_pair(
|
||||
token="ETH",
|
||||
symbol="ETH",
|
||||
vs="USDC",
|
||||
days: int = 10,
|
||||
sortby: str = "date",
|
||||
descend: bool = False,
|
||||
ascend: bool = True,
|
||||
export: str = "",
|
||||
) -> None:
|
||||
"""Display an average bid and ask prices, average spread for given crypto pair for chosen time period.
|
||||
[Source: https://graphql.bitquery.io/]
|
||||
"""Display an average bid and ask prices, average spread for given crypto pair for chosen
|
||||
time period. [Source: https://graphql.bitquery.io/]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
days: int
|
||||
Last n days to query data
|
||||
token: str
|
||||
symbol: str
|
||||
ERC20 token symbol
|
||||
vs: str
|
||||
Quoted currency.
|
||||
sortby: str
|
||||
Key by which to sort data
|
||||
descend: bool
|
||||
Flag to sort data descending
|
||||
ascend: bool
|
||||
Flag to sort data ascending
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
|
||||
@@ -355,11 +348,10 @@ def display_spread_for_crypto_pair(
|
||||
Average bid and ask prices, spread for given crypto pair for chosen time period
|
||||
"""
|
||||
|
||||
df = bitquery_model.get_spread_for_crypto_pair(token=token, vs=vs, limit=days)
|
||||
df = bitquery_model.get_spread_for_crypto_pair(
|
||||
symbol=symbol, vs=vs, limit=days, sortby=sortby, ascend=ascend
|
||||
)
|
||||
if not df.empty:
|
||||
df = df.sort_values(by=sortby, ascending=descend)
|
||||
|
||||
df.columns = prettify_column_names(df.columns)
|
||||
|
||||
print_rich_table(
|
||||
df,
|
||||
|
||||
@@ -25,8 +25,8 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_btc_circulating_supply(
|
||||
since: int,
|
||||
until: int,
|
||||
since: int = int(datetime(2010, 1, 1).timestamp()),
|
||||
until: int = int(datetime.now().timestamp()),
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
) -> None:
|
||||
@@ -78,8 +78,8 @@ def display_btc_circulating_supply(
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_btc_confirmed_transactions(
|
||||
since: int,
|
||||
until: int,
|
||||
since: int = int(datetime(2010, 1, 1).timestamp()),
|
||||
until: int = int(datetime.now().timestamp()),
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
) -> None:
|
||||
|
||||
@@ -11,7 +11,7 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_gwei_fees(export: str) -> None:
|
||||
def display_gwei_fees(export: str = "") -> None:
|
||||
"""Current gwei fees
|
||||
[Source: https://ethgasstation.info]
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ def split_cols_with_dot(column: str) -> str:
|
||||
Returns
|
||||
-------
|
||||
str:
|
||||
Camel case string with removed dots. E.g. price.availableSupply -> priceAvailableSupply.
|
||||
Camel case string with no dots. E.g. price.availableSupply -> priceAvailableSupply.
|
||||
"""
|
||||
|
||||
return string[:index] + char + string[index + 1 :]
|
||||
@@ -102,8 +102,8 @@ def split_cols_with_dot(column: str) -> str:
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def enrich_social_media(dct: dict) -> None:
|
||||
"""Searching inside dictionary if there are any information about twitter, reddit or coingecko. If yes it
|
||||
updates dictionary with url to given social media site.
|
||||
"""Searching inside dictionary if there are any information about twitter, reddit or coingecko.
|
||||
If yes it updates dictionary with url to given social media site.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
@@ -131,7 +131,7 @@ def make_request(
|
||||
Parameters
|
||||
----------
|
||||
endpoint: str
|
||||
endpoint which we want to query e.g. https://api.ethplorer.io/<endpoint><arg>?=apiKey=freekey
|
||||
endpoint we want to query e.g. https://api.ethplorer.io/<endpoint><arg>?=apiKey=freekey
|
||||
address: str
|
||||
balance argument for given endpoint. In most cases it's tx hash, or eth balance.
|
||||
kwargs: Any
|
||||
@@ -193,7 +193,9 @@ def get_token_decimals(address: str) -> Optional[int]:
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_address_info(address: str) -> pd.DataFrame:
|
||||
def get_address_info(
|
||||
address: str, sortby: str = "index", ascend: bool = False
|
||||
) -> pd.DataFrame:
|
||||
"""Get info about tokens on you ethereum blockchain balance. Eth balance, balance of all tokens which
|
||||
have name and symbol. [Source: Ethplorer]
|
||||
|
||||
@@ -201,6 +203,10 @@ def get_address_info(address: str) -> pd.DataFrame:
|
||||
----------
|
||||
address: str
|
||||
Blockchain balance e.g. 0x3cD751E6b0078Be393132286c442345e5DC49699
|
||||
sortby: str
|
||||
Key to sort by.
|
||||
ascend: str
|
||||
Sort in descending order.
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -254,11 +260,12 @@ def get_address_info(address: str) -> pd.DataFrame:
|
||||
df = pd.concat([eth_row_df, df], ignore_index=True)
|
||||
df = df[df["tokenName"].notna()][cols]
|
||||
create_df_index(df, "index")
|
||||
df = df.sort_values(by=sortby, ascending=ascend)
|
||||
return df
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_top_tokens() -> pd.DataFrame:
|
||||
def get_top_tokens(sortby: str = "rank", ascend: bool = False) -> pd.DataFrame:
|
||||
"""Get top 50 tokens. [Source: Ethplorer]
|
||||
|
||||
Returns
|
||||
@@ -283,17 +290,24 @@ def get_top_tokens() -> pd.DataFrame:
|
||||
]
|
||||
df["price"] = df["price"].apply(lambda x: x["rate"] if x and "rate" in x else None)
|
||||
create_df_index(df, "rank")
|
||||
df = df.sort_values(by=sortby, ascending=ascend)
|
||||
return df
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_top_token_holders(address) -> pd.DataFrame:
|
||||
def get_top_token_holders(
|
||||
address, sortby: str = "balance", ascend: bool = True
|
||||
) -> pd.DataFrame:
|
||||
"""Get info about top token holders. [Source: Ethplorer]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
address: str
|
||||
Token balance e.g. 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984
|
||||
sortby: str
|
||||
Key to sort by.
|
||||
ascend: str
|
||||
Sort in descending order.
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -307,17 +321,24 @@ def get_top_token_holders(address) -> pd.DataFrame:
|
||||
token_decimals_divider = get_token_decimals(address)
|
||||
if token_decimals_divider:
|
||||
df["balance"] = df["balance"] / token_decimals_divider
|
||||
df = df.sort_values(by=sortby, ascending=ascend)
|
||||
return df
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_address_history(address) -> pd.DataFrame:
|
||||
def get_address_history(
|
||||
address, sortby: str = "timestamp", ascend: bool = True
|
||||
) -> pd.DataFrame:
|
||||
"""Get information about balance historical transactions. [Source: Ethplorer]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
address: str
|
||||
Blockchain balance e.g. 0x3cD751E6b0078Be393132286c442345e5DC49699
|
||||
sortby: str
|
||||
Key to sort by.
|
||||
ascend: str
|
||||
Sort in ascending order.
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -343,7 +364,9 @@ def get_address_history(address) -> pd.DataFrame:
|
||||
console.print(f"No historical transaction found for {address}")
|
||||
return pd.DataFrame(columns=cols)
|
||||
|
||||
return df[cols]
|
||||
df = df[cols]
|
||||
df = df.sort_values(by=sortby, ascending=ascend)
|
||||
return df
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
@@ -456,13 +479,19 @@ def get_tx_info(tx_hash) -> pd.DataFrame:
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_token_history(address) -> pd.DataFrame:
|
||||
def get_token_history(
|
||||
address, sortby: str = "timestamp", ascend: bool = False
|
||||
) -> pd.DataFrame:
|
||||
"""Get info about token historical transactions. [Source: Ethplorer]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
address: str
|
||||
Token e.g. 0xf3db5fa2c66b7af3eb0c0b782510816cbe4813b8
|
||||
sortby: str
|
||||
Key to sort by.
|
||||
ascend: str
|
||||
Sort in descending order.
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -500,17 +529,27 @@ def get_token_history(address) -> pd.DataFrame:
|
||||
|
||||
df[["name", "symbol"]] = name, symbol
|
||||
df["value"] = df["value"].astype(float) / (10 ** int(decimals))
|
||||
return df[["timestamp", "name", "symbol", "value", "from", "to", "transactionHash"]]
|
||||
df = df[["timestamp", "name", "symbol", "value", "from", "to", "transactionHash"]]
|
||||
df = df.sort_values(by=sortby, ascending=ascend)
|
||||
return df
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_token_historical_price(address) -> pd.DataFrame:
|
||||
def get_token_historical_price(
|
||||
address,
|
||||
sortby: str = "date",
|
||||
ascend: bool = False,
|
||||
) -> pd.DataFrame:
|
||||
"""Get token historical prices with volume and market cap, and average price. [Source: Ethplorer]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
address: str
|
||||
Token e.g. 0xf3db5fa2c66b7af3eb0c0b782510816cbe4813b8
|
||||
sortby: str
|
||||
Key to sort by.
|
||||
ascend: str
|
||||
Sort in descending order.
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -533,6 +572,8 @@ def get_token_historical_price(address) -> pd.DataFrame:
|
||||
if "tmp" in prices_df.columns:
|
||||
prices_df.drop("tmp", axis=1, inplace=True)
|
||||
|
||||
return prices_df[
|
||||
df = prices_df[
|
||||
["date", "open", "close", "high", "low", "volumeConverted", "cap", "average"]
|
||||
]
|
||||
df = df.sort_values(by=sortby, ascending=ascend)
|
||||
return df
|
||||
|
||||
@@ -22,11 +22,11 @@ def display_address_info(
|
||||
address: str,
|
||||
top: int = 15,
|
||||
sortby: str = "index",
|
||||
descend: bool = True,
|
||||
ascend: bool = False,
|
||||
export: str = "",
|
||||
) -> None:
|
||||
"""Display info about tokens for given ethereum blockchain balance e.g. ETH balance, balance of all tokens with
|
||||
name and symbol. [Source: Ethplorer]
|
||||
"""Display info about tokens for given ethereum blockchain balance e.g. ETH balance,
|
||||
balance of all tokens with name and symbol. [Source: Ethplorer]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
@@ -36,15 +36,14 @@ def display_address_info(
|
||||
Limit of transactions. Maximum 100
|
||||
sortby: str
|
||||
Key to sort by.
|
||||
descend: str
|
||||
ascend: str
|
||||
Sort in descending order.
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
|
||||
df = ethplorer_model.get_address_info(address)
|
||||
df = ethplorer_model.get_address_info(address, sortby=sortby, ascend=ascend)
|
||||
df_data = df.copy()
|
||||
df = df.sort_values(by=sortby, ascending=descend)
|
||||
df["balance"] = df["balance"].apply(
|
||||
lambda x: lambda_very_long_number_formatter(x)
|
||||
if x >= 10000
|
||||
@@ -71,7 +70,7 @@ def display_address_info(
|
||||
def display_top_tokens(
|
||||
top: int = 15,
|
||||
sortby: str = "rank",
|
||||
descend: bool = True,
|
||||
ascend: bool = True,
|
||||
export: str = "",
|
||||
) -> None:
|
||||
"""Display top ERC20 tokens [Source: Ethplorer]
|
||||
@@ -82,16 +81,15 @@ def display_top_tokens(
|
||||
Limit of transactions. Maximum 100
|
||||
sortby: str
|
||||
Key to sort by.
|
||||
descend: str
|
||||
ascend: str
|
||||
Sort in descending order.
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
|
||||
df = ethplorer_model.get_top_tokens()
|
||||
df = ethplorer_model.get_top_tokens(sortby, ascend)
|
||||
df_data = df.copy()
|
||||
df.fillna("", inplace=True)
|
||||
df = df.sort_values(by=sortby, ascending=descend)
|
||||
for col in ["txsCount", "transfersCount", "holdersCount"]:
|
||||
if col in df.columns:
|
||||
df[col] = df[col].apply(lambda x: lambda_very_long_number_formatter(x))
|
||||
@@ -117,7 +115,7 @@ def display_top_token_holders(
|
||||
address: str,
|
||||
top: int = 10,
|
||||
sortby: str = "balance",
|
||||
descend: bool = False,
|
||||
ascend: bool = True,
|
||||
export: str = "",
|
||||
) -> None:
|
||||
"""Display info about top ERC20 token holders. [Source: Ethplorer]
|
||||
@@ -130,15 +128,14 @@ def display_top_token_holders(
|
||||
Limit of transactions. Maximum 100
|
||||
sortby: str
|
||||
Key to sort by.
|
||||
descend: str
|
||||
ascend: str
|
||||
Sort in descending order.
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
|
||||
df = ethplorer_model.get_top_token_holders(address)
|
||||
df = ethplorer_model.get_top_token_holders(address, sortby, ascend)
|
||||
df_data = df.copy()
|
||||
df = df.sort_values(by=sortby, ascending=descend)
|
||||
df["balance"] = df["balance"].apply(lambda x: lambda_very_long_number_formatter(x))
|
||||
|
||||
print_rich_table(
|
||||
@@ -162,7 +159,7 @@ def display_address_history(
|
||||
address: str,
|
||||
top: int = 10,
|
||||
sortby: str = "timestamp",
|
||||
descend: bool = False,
|
||||
ascend: bool = True,
|
||||
export: str = "",
|
||||
) -> None:
|
||||
"""Display information about balance historical transactions. [Source: Ethplorer]
|
||||
@@ -175,15 +172,14 @@ def display_address_history(
|
||||
Limit of transactions. Maximum 100
|
||||
sortby: str
|
||||
Key to sort by.
|
||||
descend: str
|
||||
Sort in descending order.
|
||||
ascend: str
|
||||
Sort in ascending order.
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
|
||||
df = ethplorer_model.get_address_history(address)
|
||||
df = ethplorer_model.get_address_history(address, sortby, ascend)
|
||||
df_data = df.copy()
|
||||
df = df.sort_values(by=sortby, ascending=descend)
|
||||
df["value"] = df["value"].apply(
|
||||
lambda x: lambda_very_long_number_formatter(x)
|
||||
if x >= 10000
|
||||
@@ -265,7 +261,6 @@ def display_tx_info(
|
||||
"""
|
||||
|
||||
df = ethplorer_model.get_tx_info(tx_hash)
|
||||
df_data = df.copy()
|
||||
print_rich_table(
|
||||
df,
|
||||
headers=list(df.columns),
|
||||
@@ -273,12 +268,7 @@ def display_tx_info(
|
||||
title="Information About Transactions",
|
||||
)
|
||||
|
||||
export_data(
|
||||
export,
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"tx",
|
||||
df_data,
|
||||
)
|
||||
export_data(export, os.path.dirname(os.path.abspath(__file__)), "tx", df)
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
@@ -287,8 +277,8 @@ def display_token_history(
|
||||
address: str,
|
||||
top: int = 10,
|
||||
sortby: str = "timestamp",
|
||||
ascend: bool = False,
|
||||
hash_: bool = False,
|
||||
descend: bool = False,
|
||||
export: str = "",
|
||||
) -> None:
|
||||
"""Display info about token history. [Source: Ethplorer]
|
||||
@@ -301,7 +291,7 @@ def display_token_history(
|
||||
Limit of transactions. Maximum 100
|
||||
sortby: str
|
||||
Key to sort by.
|
||||
descend: str
|
||||
ascend: str
|
||||
Sort in descending order.
|
||||
hash_: bool,
|
||||
Flag to show transaction hash.
|
||||
@@ -309,7 +299,7 @@ def display_token_history(
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
|
||||
df = ethplorer_model.get_token_history(address)
|
||||
df = ethplorer_model.get_token_history(address, sortby, ascend)
|
||||
df_data = df.copy()
|
||||
if df.empty:
|
||||
console.print(f"No results found for balance: {address}\n")
|
||||
@@ -318,7 +308,6 @@ def display_token_history(
|
||||
df.loc[:, "value"] = df["value"].apply(
|
||||
lambda x: lambda_very_long_number_formatter(x)
|
||||
)
|
||||
df = df.sort_values(by=sortby, ascending=descend)
|
||||
|
||||
if hash_:
|
||||
df.drop(["from", "to"], axis=1, inplace=True)
|
||||
@@ -346,10 +335,11 @@ def display_token_historical_prices(
|
||||
address: str,
|
||||
top: int = 30,
|
||||
sortby: str = "date",
|
||||
descend: bool = False,
|
||||
ascend: bool = False,
|
||||
export: str = "",
|
||||
) -> None:
|
||||
"""Display token historical prices with volume and market cap, and average price. [Source: Ethplorer]
|
||||
"""Display token historical prices with volume and market cap, and average price.
|
||||
[Source: Ethplorer]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
@@ -359,13 +349,13 @@ def display_token_historical_prices(
|
||||
Limit of transactions. Maximum 100
|
||||
sortby: str
|
||||
Key to sort by.
|
||||
descend: str
|
||||
ascend: str
|
||||
Sort in descending order.
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
|
||||
df = ethplorer_model.get_token_historical_price(address)
|
||||
df = ethplorer_model.get_token_historical_price(address, sortby, ascend)
|
||||
df_data = df.copy()
|
||||
|
||||
if df.empty:
|
||||
@@ -376,7 +366,6 @@ def display_token_historical_prices(
|
||||
lambda x: lambda_very_long_number_formatter(x)
|
||||
)
|
||||
df.loc[:, "cap"] = df["cap"].apply(lambda x: lambda_very_long_number_formatter(x))
|
||||
df = df.sort_values(by=sortby, ascending=descend)
|
||||
|
||||
print_rich_table(
|
||||
df.head(top),
|
||||
|
||||
@@ -305,7 +305,7 @@ class OnchainController(BaseController):
|
||||
|
||||
if ns_parser:
|
||||
display_hashrate(
|
||||
asset=ns_parser.coin,
|
||||
symbol=ns_parser.coin,
|
||||
interval=ns_parser.interval,
|
||||
since=int(datetime.timestamp(ns_parser.since)),
|
||||
until=int(datetime.timestamp(ns_parser.until)),
|
||||
@@ -398,7 +398,7 @@ class OnchainController(BaseController):
|
||||
min_value=ns_parser.min,
|
||||
top=ns_parser.limit,
|
||||
sortby=ns_parser.sortby,
|
||||
descend=ns_parser.descend,
|
||||
ascend=not ns_parser.descend,
|
||||
show_address=ns_parser.address,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
@@ -527,7 +527,7 @@ class OnchainController(BaseController):
|
||||
ethplorer_view.display_address_info(
|
||||
top=ns_parser.limit,
|
||||
sortby=ns_parser.sortby,
|
||||
descend=ns_parser.descend,
|
||||
ascend=not ns_parser.descend,
|
||||
address=self.address,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
@@ -583,7 +583,7 @@ class OnchainController(BaseController):
|
||||
ethplorer_view.display_address_history(
|
||||
top=ns_parser.limit,
|
||||
sortby=ns_parser.sortby,
|
||||
descend=ns_parser.descend,
|
||||
ascend=not ns_parser.descend,
|
||||
address=self.address,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
@@ -638,7 +638,7 @@ class OnchainController(BaseController):
|
||||
ethplorer_view.display_top_token_holders(
|
||||
top=ns_parser.limit,
|
||||
sortby=ns_parser.sortby,
|
||||
descend=ns_parser.descend,
|
||||
ascend=not ns_parser.descend,
|
||||
address=self.address,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
@@ -693,7 +693,7 @@ class OnchainController(BaseController):
|
||||
ethplorer_view.display_top_tokens(
|
||||
top=ns_parser.limit,
|
||||
sortby=ns_parser.sortby,
|
||||
descend=ns_parser.descend,
|
||||
ascend=not ns_parser.descend,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
|
||||
@@ -789,7 +789,7 @@ class OnchainController(BaseController):
|
||||
top=ns_parser.limit,
|
||||
hash_=ns_parser.hash,
|
||||
sortby=ns_parser.sortby,
|
||||
descend=ns_parser.descend,
|
||||
ascend=not ns_parser.descend,
|
||||
address=self.address,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
@@ -870,7 +870,7 @@ class OnchainController(BaseController):
|
||||
ethplorer_view.display_token_historical_prices(
|
||||
top=ns_parser.limit,
|
||||
sortby=ns_parser.sortby,
|
||||
descend=ns_parser.descend,
|
||||
ascend=not ns_parser.descend,
|
||||
address=self.address,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
@@ -957,7 +957,7 @@ class OnchainController(BaseController):
|
||||
top=ns_parser.limit,
|
||||
days=ns_parser.days,
|
||||
sortby=ns_parser.sortby,
|
||||
descend=ns_parser.descend,
|
||||
ascend=not ns_parser.descend,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
|
||||
@@ -1036,7 +1036,7 @@ class OnchainController(BaseController):
|
||||
vs=ns_parser.vs,
|
||||
top=ns_parser.days,
|
||||
sortby=ns_parser.sortby,
|
||||
descend=ns_parser.descend,
|
||||
ascend=not ns_parser.descend,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
|
||||
@@ -1111,7 +1111,7 @@ class OnchainController(BaseController):
|
||||
trade_amount_currency=ns_parser.vs,
|
||||
top=ns_parser.limit,
|
||||
sortby=ns_parser.sortby,
|
||||
descend=ns_parser.descend,
|
||||
ascend=not ns_parser.descend,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
|
||||
@@ -1177,7 +1177,7 @@ class OnchainController(BaseController):
|
||||
interval=ns_parser.interval,
|
||||
limit=ns_parser.limit,
|
||||
sortby=ns_parser.sortby,
|
||||
descend=ns_parser.descend,
|
||||
ascend=not ns_parser.descend,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
|
||||
@@ -1286,7 +1286,7 @@ class OnchainController(BaseController):
|
||||
top=ns_parser.limit,
|
||||
exchange=exchange,
|
||||
sortby=ns_parser.sortby,
|
||||
descend=ns_parser.descend,
|
||||
ascend=not ns_parser.descend,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
|
||||
@@ -1357,7 +1357,7 @@ class OnchainController(BaseController):
|
||||
vs=ns_parser.vs,
|
||||
days=ns_parser.days,
|
||||
sortby=ns_parser.sortby,
|
||||
descend=ns_parser.descend,
|
||||
ascend=not ns_parser.descend,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
|
||||
@@ -1380,7 +1380,7 @@ class OnchainController(BaseController):
|
||||
vs=ns_parser.vs,
|
||||
days=ns_parser.days,
|
||||
sortby=ns_parser.sortby,
|
||||
descend=ns_parser.descend,
|
||||
ascend=not ns_parser.descend,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
else:
|
||||
|
||||
@@ -82,7 +82,12 @@ def make_request(params: Optional[dict] = None) -> Tuple[Optional[int], Any]:
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_whales_transactions(min_value: int = 800000, limit: int = 100) -> pd.DataFrame:
|
||||
def get_whales_transactions(
|
||||
min_value: int = 800000,
|
||||
limit: int = 100,
|
||||
sortby: str = "date",
|
||||
ascend: bool = False,
|
||||
) -> pd.DataFrame:
|
||||
"""Whale Alert's API allows you to retrieve live and historical transaction data from major blockchains.
|
||||
Supported blockchain: Bitcoin, Ethereum, Ripple, NEO, EOS, Stellar and Tron. [Source: https://docs.whale-alert.io/]
|
||||
|
||||
@@ -92,6 +97,10 @@ def get_whales_transactions(min_value: int = 800000, limit: int = 100) -> pd.Dat
|
||||
Minimum value of trade to track.
|
||||
limit: int
|
||||
Limit of transactions. Max 100
|
||||
sortby: str
|
||||
Key to sort by.
|
||||
ascend: str
|
||||
Sort in ascending order.
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -150,7 +159,7 @@ def get_whales_transactions(min_value: int = 800000, limit: int = 100) -> pd.Dat
|
||||
inplace=True,
|
||||
)
|
||||
|
||||
return data[
|
||||
df = data[
|
||||
[
|
||||
"date",
|
||||
"symbol",
|
||||
@@ -163,3 +172,5 @@ def get_whales_transactions(min_value: int = 800000, limit: int = 100) -> pd.Dat
|
||||
"to_address",
|
||||
]
|
||||
]
|
||||
df = df.sort_values(by=sortby, ascending=ascend)
|
||||
return df
|
||||
|
||||
@@ -23,7 +23,7 @@ def display_whales_transactions(
|
||||
min_value: int = 800000,
|
||||
top: int = 100,
|
||||
sortby: str = "date",
|
||||
descend: bool = False,
|
||||
ascend: bool = False,
|
||||
show_address: bool = False,
|
||||
export: str = "",
|
||||
) -> None:
|
||||
@@ -37,15 +37,15 @@ def display_whales_transactions(
|
||||
Limit of transactions. Maximum 100
|
||||
sortby: str
|
||||
Key to sort by.
|
||||
descend: str
|
||||
Sort in descending order.
|
||||
ascend: str
|
||||
Sort in ascending order.
|
||||
show_address: bool
|
||||
Flag to show addresses of transactions.
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
|
||||
df = whale_alert_model.get_whales_transactions(min_value)
|
||||
df = whale_alert_model.get_whales_transactions(min_value, sortby, ascend)
|
||||
|
||||
if df.empty:
|
||||
console.print("Failed to retrieve data.")
|
||||
@@ -53,8 +53,6 @@ def display_whales_transactions(
|
||||
|
||||
df_data = df.copy()
|
||||
|
||||
df = df.sort_values(by=sortby, ascending=descend)
|
||||
|
||||
if not show_address:
|
||||
df = df.drop(["from_address", "to_address"], axis=1)
|
||||
else:
|
||||
|
||||
@@ -16,15 +16,19 @@ DAYS = [30, 90, 365]
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_altcoin_index(period: int, since: int, until: int) -> pd.DataFrame:
|
||||
def get_altcoin_index(
|
||||
period: int = 30,
|
||||
since: int = int(datetime(2010, 1, 1).timestamp()),
|
||||
until: int = int(datetime.now().timestamp()),
|
||||
) -> pd.DataFrame:
|
||||
"""Get altcoin index overtime
|
||||
[Source: https://blockchaincenter.net]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
period: int
|
||||
Number of days {30,90,365} to check the performance of coins and calculate the altcoin index.
|
||||
E.g., 365 will check yearly performance (365 days), 90 will check seasonal performance (90 days),
|
||||
Number of days {30,90,365} to check performance of coins and calculate the altcoin index.
|
||||
E.g., 365 checks yearly performance, 90 will check seasonal performance (90 days),
|
||||
30 will check monthly performance (30 days).
|
||||
since : int
|
||||
Initial date timestamp (e.g., 1_609_459_200)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import logging
|
||||
import os
|
||||
from typing import List, Optional
|
||||
from datetime import datetime
|
||||
|
||||
from matplotlib import pyplot as plt
|
||||
|
||||
@@ -24,9 +25,9 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_altcoin_index(
|
||||
period: int,
|
||||
since: int,
|
||||
until: int,
|
||||
period: int = 365,
|
||||
since: int = int(datetime(2010, 1, 1).timestamp()),
|
||||
until: int = int(datetime.now().timestamp()),
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
) -> None:
|
||||
@@ -41,7 +42,7 @@ def display_altcoin_index(
|
||||
End date timestamp (e.g., 1_641_588_030)
|
||||
period: int
|
||||
Number of days to check the performance of coins and calculate the altcoin index.
|
||||
E.g., 365 will check yearly performance (365 days), 90 will check seasonal performance (90 days),
|
||||
E.g., 365 will check yearly performance , 90 will check seasonal performance (90 days),
|
||||
30 will check monthly performance (30 days).
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
|
||||
@@ -21,7 +21,9 @@ PAIRS_FILTERS = [
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_trading_pairs() -> pd.DataFrame:
|
||||
def get_trading_pairs(
|
||||
top: int = 50, sortby: str = "quote_increment", ascend: bool = True
|
||||
) -> pd.DataFrame:
|
||||
"""Get a list of available currency pairs for trading. [Source: Coinbase]
|
||||
|
||||
base_min_size - min order size
|
||||
@@ -29,6 +31,15 @@ def get_trading_pairs() -> pd.DataFrame:
|
||||
min_market_funds - min funds allowed in a market order.
|
||||
max_market_funds - max funds allowed in a market order.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
top: int
|
||||
Top n of pairs
|
||||
sortby: str
|
||||
Key to sortby data
|
||||
ascend: bool
|
||||
Sort descending flag
|
||||
|
||||
Returns
|
||||
-------
|
||||
pd.DataFrame
|
||||
@@ -45,4 +56,6 @@ def get_trading_pairs() -> pd.DataFrame:
|
||||
"min_market_funds",
|
||||
]
|
||||
pairs = make_coinbase_request("/products")
|
||||
return pd.DataFrame(pairs)[columns]
|
||||
df = pd.DataFrame(pairs)[columns]
|
||||
df = df.sort_values(by=sortby, ascending=ascend).head(top)
|
||||
return df
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user