Improves load and candle relation + 3 bonus READMEs (#908)

* stocks/ba

* stocks/disc

* stocks/dps

* Improve load and candle relation

* refactor trendline file

* change --plotly to --it
This commit is contained in:
DidierRLopes
2021-11-04 13:50:40 +00:00
committed by GitHub
parent f6d6b7382f
commit c0f4032b33
8 changed files with 213 additions and 167 deletions

View File

@@ -68,14 +68,6 @@ gamestonk\_terminal.common.technical\_analysis.trend\_indicators\_view module
:undoc-members:
:show-inheritance:
gamestonk\_terminal.common.technical\_analysis.trendline\_api module
--------------------------------------------------------------------
.. automodule:: gamestonk_terminal.common.technical_analysis.trendline_api
:members:
:undoc-members:
:show-inheritance:
gamestonk\_terminal.common.technical\_analysis.volatility\_model module
-----------------------------------------------------------------------

View File

@@ -1,94 +0,0 @@
"""Technical Analysis Trendline Module"""
__docformat__ = "numpy"
from typing import Union
from datetime import datetime
import yfinance as yf
from pandas.core.frame import DataFrame
from scipy.stats import linregress
def load_ticker(ticker: str, start_date: Union[str, datetime]) -> DataFrame:
"""Loads a ticker data from Yahoo Finance, adds a data index column data_id and Open-Close High/Low columns.
Parameters
----------
ticker : str
The stock ticker.
start_date : Union[str,datetime]
Start date to load stock ticker data formatted YYYY-MM-DD.
Returns
-------
DataFrame
A Panda's data frame with columns Open, High, Low, Close, Adj Close, Volume, date_id, OC-High, OC-Low.
"""
# print(f"Start date: {start_date}")
df_data = yf.download(ticker, start=start_date, progress=False)
df_data["date_id"] = (df_data.index.date - df_data.index.date.min()).astype(
"timedelta64[D]"
)
df_data["date_id"] = df_data["date_id"].dt.days + 1
df_data["OC_High"] = df_data[["Open", "Close"]].max(axis=1)
df_data["OC_Low"] = df_data[["Open", "Close"]].min(axis=1)
return df_data
def find_trendline(df_data: DataFrame, y_key: str, high_low: str = "high") -> DataFrame:
"""Attempts to find a trend line based on y_key column from a given stock ticker data frame.
Parameters
----------
df_data : DataFrame
The stock ticker data frame with at least date_id, y_key columns.
y_key : str
Column name to base the trend line on.
high_low: str, optional
Either "high" or "low". High is the default.
Returns
-------
DataFrame
If a trend is successfully found,
An updated Panda's data frame with a trend data {y_key}_trend column.
If no trend was found,
An original Panda's data frame
"""
for iteration in [3, 4, 5, 6, 7]:
df_temp = df_data.copy()
while len(df_temp) > iteration:
reg = linregress(
x=df_temp["date_id"],
y=df_temp[y_key],
)
if high_low == "high":
df_temp = df_temp.loc[
df_temp[y_key] > reg[0] * df_temp["date_id"] + reg[1]
]
else:
df_temp = df_temp.loc[
df_temp[y_key] < reg[0] * df_temp["date_id"] + reg[1]
]
if len(df_temp) > 1:
break
if len(df_temp) == 1:
return df_data
reg = linregress(
x=df_temp["date_id"],
y=df_temp[y_key],
)
df_data[f"{y_key}_trend"] = reg[0] * df_data["date_id"] + reg[1]
return df_data

View File

@@ -7,7 +7,7 @@ from datetime import datetime, timedelta
import pandas as pd
import mplfinance as mpf
from gamestonk_terminal.common.technical_analysis import trendline_api as trend
from gamestonk_terminal.stocks import stocks_helper
# pylint: disable=too-many-arguments
@@ -48,20 +48,20 @@ def draw_graph(
if os.path.isfile(df_stock_cache):
df_stock = pd.read_pickle(df_stock_cache)
else:
df_stock = trend.load_ticker(
df_stock = stocks_helper.load_ticker(
ticker,
(datetime.now() - timedelta(days=time_delta)).strftime("%Y-%m-%d"),
)
df_stock = trend.find_trendline(df_stock, "OC_High", "high")
df_stock = trend.find_trendline(df_stock, "OC_Low", "how")
df_stock = stocks_helper.find_trendline(df_stock, "OC_High", "high")
df_stock = stocks_helper.find_trendline(df_stock, "OC_Low", "how")
df_stock.to_pickle(df_stock_cache)
else:
df_stock = trend.load_ticker(
df_stock = stocks_helper.load_ticker(
ticker, (datetime.now() - timedelta(days=time_delta)).strftime("%Y-%m-%d")
)
df_stock = trend.find_trendline(df_stock, "OC_High", "high")
df_stock = trend.find_trendline(df_stock, "OC_Low", "how")
df_stock = stocks_helper.find_trendline(df_stock, "OC_High", "high")
df_stock = stocks_helper.find_trendline(df_stock, "OC_Low", "how")
mc = mpf.make_marketcolors(
up="green", down="red", edge="black", wick="black", volume="in", ohlc="i"

View File

@@ -1,6 +1,4 @@
# BEHAVIOURAL ANALYSIS
Check all features [HERE](https://gamestonkterminal.github.io/GamestonkTerminal/common/behavioural_analysis/).
# Behavioural Analysis [>>](https://gamestonkterminal.github.io/GamestonkTerminal/common/behavioural_analysis/)
Command|Description|Source
----|----|----
@@ -11,6 +9,7 @@ Command|Description|Source
`popular` |show popular tickers|[Reddit](https://reddit.com)
`spac_c` |show other users spacs announcements from subreddit SPACs community|[Reddit](https://reddit.com)
`spac` |show other users spacs announcements from other subs|[Reddit](https://reddit.com)
`getdd` |gets due diligence from another user's post|[Reddit](https://reddit.com)
`bullbear` |estimate quick sentiment from last 30 messages on board|[Stocktwits](https://stocktwits.com/)
`messages` |output up to the 30 last messages on the board|[Stocktwits](https://stocktwits.com/)
`trending` |trending stocks|[Stocktwits](https://stocktwits.com/)
@@ -21,6 +20,8 @@ Command|Description|Source
`regions` |regions that show highest interest in stock|[Google](https://google.com/)
`queries` |top related queries with this stock|[Google](https://google.com/)
`rise` |top rising related queries with stock|[Google](https://google.com/)
`popularsi` |show most popular stocks on social media right now|[Sentiment Investor](https://sentimentinvestor.com)
`emerging` |show stocks that are being talked about more than usual|[Sentiment Investor](https://sentimentinvestor.com)
`metrics` |core social sentiment metrics for this stock|[Sentiment Investor](https://sentimentinvestor.com)
`social` |social media figures for stock popularity|[Sentiment Investor](https://sentimentinvestor.com)
`historical` |plot the past week of data for a selected metric|[Sentiment Investor](https://sentimentinvestor.com)

View File

@@ -1,5 +1,13 @@
# DARK POOL SHORTS
# Dark Pool and Short Data [>>](https://gamestonkterminal.github.io/GamestonkTerminal/stocks/dark_pool_shorts)
Check all features [HERE](https://gamestonkterminal.github.io/GamestonkTerminal/stocks/dark_pool_shorts).
**TODO**
Command|Description|Source
---|---|---
`shorted` |show most shorted stocks |[Yahoo Finance](https://finance.yahoo.com/)
`hsi` |show top high short interest stocks of over 20% ratio |[High Short Interest](https://www.highshortinterest.com/)
`prom` |promising tickers based on dark pool shares regression |[FINRA](https://www.finra.org)
`pos` |dark pool short position|[Stockgrid](https://stockgrid.io)
`sidtc` |short interest and days to cover |[Stockgrid](https://stockgrid.io)
`dpotc` |dark pools (ATS) vs OTC data |[FINRA](https://www.finra.org)
`ftd` |fails-to-deliver data|[SEC](https://sec.report)
`spos` |net short vs position |[Stockgrid](https://stockgrid.io)
`psi` |price vs short interest volume |[Stockgrid](https://stockgrid.io) or [Quandl](https://data.nasdaq.com)

View File

@@ -1,29 +1,22 @@
# DISCOVER STOCKS
Check all features [HERE](https://gamestonkterminal.github.io/GamestonkTerminal/stocks/discovery/).
# Discovery [>>](https://gamestonkterminal.github.io/GamestonkTerminal/stocks/discovery/)
Command|Description|Source
---|---|---
`ipo` |past and future IPOs |[Finnhub](https://finnhub.io)
`map` |S&P500 index stocks map |[Finviz](https://finviz.com)
`rtp_sectors` |real-time performance sectors |[Alpha Vantage](www.alphavantage.co)
`rtearn` | realtime earnings from and expected moves | [Geek of Wall St](https://thegeekofwallstreet.com)
`pipo` |past IPOs dates |[Finnhub](https://finnhub.io)
`fipo` |future IPOs dates |[Finnhub](https://finnhub.io)
`gainers` |show latest top gainers |[Yahoo Finance](https://finance.yahoo.com/)
`losers` |show latest top losers |[Yahoo Finance](https://finance.yahoo.com/)
`orders` |orders by Fidelity Customers |[Fidelity](https://www.fidelity.com/)
`ark_orders` |orders by ARK Investment Management LLC | [Cathiesark](https://www.cathiesark.com)
`up_earnings` |upcoming earnings release dates |[Seeking Alpha](https://seekingalpha.com/)
`high_short` |show top high short interest stocks of over 20% ratio |[High Short Interest](https://www.highshortinterest.com/)
`low_float` |show low float stocks under 10M shares float |[Low Float](https://www.lowfloat.com/)
`simply_wallst` |Simply Wall St. research data |[Simply Wall St.](https://simplywall.st/about)
`spachero` |great website for SPACs research |[SpacHero](https://www.spachero.com/)
`uwhales` |good website for SPACs research |[UnusualWhales](https://unusualwhales.com/)
`valuation` |valuation of sectors, industry, country |[Finviz](https://finviz.com)
`performance` |performance of sectors, industry, country |[Finviz](https://finviz.com)
`spectrum` |spectrum of sectors, industry, country |[Finviz](https://finviz.com)
`ugs` |undervalued stocks with revenue and earnings growth in excess of 25% |[Yahoo Finance](https://finance.yahoo.com/)
`gtech` |tech stocks with revenue and earnings growth more than 25% |[Yahoo Finance](https://finance.yahoo.com/)
`active` |most active stocks by intraday trade volume |[Yahoo Finance](https://finance.yahoo.com/)
`ulc` |potentially undervalued large cap stocks |[Yahoo Finance](https://finance.yahoo.com/)
`asc` |small cap stocks with earnings growth rates better than 25% |[Yahoo Finance](https://finance.yahoo.com/)
`ford` |orders by Fidelity Customers |[Fidelity](https://www.fidelity.com/)
`arkord` |orders by ARK Investment Management LLC | [Cathiesark](https://www.cathiesark.com)
`upcoming` |upcoming earnings release dates |[Seeking Alpha](https://seekingalpha.com/)
`latest` |latest news |[Seeking Alpha](https://seekingalpha.com/)
`trending` |trending news |[Seeking Alpha](https://seekingalpha.com/)
`darkpool` |dark pool tickers with growing activity |[FINRA](https://www.finra.org)
`darkshort` |dark pool short position|[Stockgrid](https://stockgrid.io)
`shortvol` |short interest and days to cover |[Stockgrid](https://stockgrid.io)
`popular` |show most popular stocks on social media right now|[Sentiment Investor](https://sentimentinvestor.com)
`emerging` |show stocks that are being talked about more than usual|[Sentiment Investor](https://sentimentinvestor.com)
`low_float` |show low float stocks under 10M shares float |[Low Float](https://www.lowfloat.com/)
`hotpenny` |today's hot penny stocks |[hotpenny](https://pennystockflow.com)
`fds` |advanced Equities search based on country, sector, industry, name and/or description |[FinanceDatabase](https://github.com/JerBouma/FinanceDatabase)

View File

@@ -16,7 +16,12 @@ from gamestonk_terminal.helper_funcs import (
parse_known_args_and_warn,
)
from gamestonk_terminal.menu import session
from gamestonk_terminal.stocks.stocks_helper import display_candle, load, quote
from gamestonk_terminal.stocks.stocks_helper import (
display_candle,
load,
quote,
process_candle,
)
from gamestonk_terminal.helper_funcs import (
valid_date,
@@ -214,14 +219,22 @@ Market {('CLOSED', 'OPEN')[b_is_stock_market_open()]}
)
parser.add_argument(
"-s",
"--start_date",
"--start",
dest="s_start",
type=valid_date,
default=(datetime.now() - timedelta(days=366)).strftime("%Y-%m-%d"),
default=self.stock.index[0],
help="Start date for candle data",
)
parser.add_argument(
"--plotly",
"-e",
"--end",
dest="s_end",
type=valid_date,
default=self.stock.index[-1],
help="End date for candle data",
)
parser.add_argument(
"--it",
dest="plotly",
action="store_true",
default=False,
@@ -280,7 +293,7 @@ Market {('CLOSED', 'OPEN')[b_is_stock_market_open()]}
if not ns_parser:
return
if not self.ticker:
print("No ticker loaded. First use `load {ticker}`\n")
print("No ticker loaded. First use `load {ticker}`\n")
return
if ns_parser.raw:
@@ -293,11 +306,11 @@ Market {('CLOSED', 'OPEN')[b_is_stock_market_open()]}
)
else:
df_stock = process_candle(self.stock)
display_candle(
s_ticker=self.ticker + "." + self.suffix
if self.suffix
else self.ticker,
s_start=ns_parser.s_start,
s_ticker=self.ticker,
df_stock=df_stock,
plotly=ns_parser.plotly,
)

View File

@@ -2,8 +2,9 @@
__docformat__ = "numpy"
import argparse
from datetime import datetime, timedelta
from typing import List
from typing import List, Union
import warnings
from scipy import stats
import matplotlib.pyplot as plt
import mplfinance as mpf
import pandas as pd
@@ -19,13 +20,13 @@ from tabulate import tabulate
from gamestonk_terminal import config_plot as cfgPlot
from gamestonk_terminal import config_terminal as cfg
from gamestonk_terminal import feature_flags as gtff
from gamestonk_terminal.common.technical_analysis import trendline_api as trend
from gamestonk_terminal.helper_funcs import (
parse_known_args_and_warn,
plot_autoscale,
valid_date,
)
warnings.simplefilter("ignore")
# pylint: disable=no-member,too-many-branches,C0302
@@ -139,6 +140,14 @@ def load(
dest="s_start_date",
help="The starting date (format YYYY-MM-DD) of the stock",
)
parser.add_argument(
"-e",
"--end",
type=valid_date,
default=datetime.now().strftime("%Y-%m-%d"),
dest="s_end_date",
help="The ending date (format YYYY-MM-DD) of the stock",
)
parser.add_argument(
"-i",
"--interval",
@@ -209,12 +218,17 @@ def load(
df_stock_candidate.sort_index(ascending=True, inplace=True)
# Slice dataframe from the starting date YYYY-MM-DD selected
df_stock_candidate = df_stock_candidate[ns_parser.s_start_date :]
df_stock_candidate = df_stock_candidate[
ns_parser.s_start_date : ns_parser.s_end_date
]
# Yahoo Finance Source
elif ns_parser.source == "yf":
df_stock_candidate = yf.download(
ns_parser.s_ticker, start=ns_parser.s_start_date, progress=False
ns_parser.s_ticker,
start=ns_parser.s_start_date,
end=ns_parser.s_end_date,
progress=False,
)
# Check that loading a stock was not successful
@@ -252,7 +266,9 @@ def load(
df_stock_candidate.sort_index(ascending=True, inplace=True)
# Slice dataframe from the starting date YYYY-MM-DD selected
df_stock_candidate = df_stock_candidate[ns_parser.s_start_date :]
df_stock_candidate = df_stock_candidate[
ns_parser.s_start_date : ns_parser.s_end_date
]
# Check if start time from dataframe is more recent than specified
if df_stock_candidate.index[0] > pd.to_datetime(ns_parser.s_start_date):
@@ -290,7 +306,9 @@ def load(
df_stock_candidate.sort_index(ascending=True, inplace=True)
# Slice dataframe from the starting date YYYY-MM-DD selected
df_stock_candidate = df_stock_candidate[ns_parser.s_start_date :]
df_stock_candidate = df_stock_candidate[
ns_parser.s_start_date : ns_parser.s_end_date
]
# Check if start time from dataframe is more recent than specified
if df_stock_candidate.index[0] > pd.to_datetime(ns_parser.s_start_date):
@@ -376,7 +394,9 @@ def load(
df_stock_candidate.index.name = "date"
# Slice dataframe from the starting date YYYY-MM-DD selected
df_stock_candidate = df_stock_candidate[ns_parser.s_start_date :]
df_stock_candidate = df_stock_candidate[
ns_parser.s_start_date : ns_parser.s_end_date
]
# Check if start time from dataframe is more recent than specified
if df_stock_candidate.index[0] > pd.to_datetime(ns_parser.s_start_date):
@@ -407,27 +427,23 @@ def load(
return [s_ticker, s_start, s_interval, df_stock]
def display_candle(s_ticker: str, s_start: datetime, plotly: bool):
"""Shows candle plot of loaded ticker
def display_candle(s_ticker: str, df_stock: pd.DataFrame, plotly: bool):
"""Shows candle plot of loaded ticker. [Source: Yahoo Finance, IEX Cloud or Alpha Vantage]
Parameters
----------
df_stock: pd.DataFrame
Stock dataframe
s_ticker: str
Ticker to display
s_start: datetime
Starting date for candle
Ticker name
plotly: bool
Flag to show interactive plotly chart
"""
# TODO: Add option to customize plot even further
print(type(s_start))
df_stock = trend.load_ticker(s_ticker, s_start)
df_stock["ma20"] = df_stock["Close"].rolling(20).mean().fillna(method="bfill")
df_stock["ma50"] = df_stock["Close"].rolling(50).mean().fillna(method="bfill")
df_stock = trend.find_trendline(df_stock, "OC_High", "high")
df_stock = trend.find_trendline(df_stock, "OC_Low", "low")
df_stock = find_trendline(df_stock, "OC_High", "high")
df_stock = find_trendline(df_stock, "OC_Low", "low")
if not plotly:
mc = mpf.make_marketcolors(
up="green",
@@ -460,7 +476,7 @@ def display_candle(s_ticker: str, s_start: datetime, plotly: bool):
type="candle",
mav=(20, 50),
volume=True,
title=f"\n{s_ticker} - Starting {s_start.strftime('%Y-%m-%d')}",
title=f"\nStock {s_ticker}",
addplot=ap0,
xrotation=10,
style=s,
@@ -812,3 +828,120 @@ def plot_view_stock(df: pd.DataFrame, symbol: str, interval: str):
plt.show()
print("")
def load_ticker(
ticker: str, start_date: Union[str, datetime], end_date: Union[str, datetime] = ""
) -> pd.DataFrame:
"""Loads a ticker data from Yahoo Finance, adds a data index column data_id and Open-Close High/Low columns.
Parameters
----------
ticker : str
The stock ticker.
start_date : Union[str,datetime]
Start date to load stock ticker data formatted YYYY-MM-DD.
end_date : Union[str,datetime]
End date to load stock ticker data formatted YYYY-MM-DD.
Returns
-------
DataFrame
A Panda's data frame with columns Open, High, Low, Close, Adj Close, Volume, date_id, OC-High, OC-Low.
"""
if end_date:
df_data = yf.download(ticker, start=start_date, end=end_date, progress=False)
else:
df_data = yf.download(ticker, start=start_date, progress=False)
df_data["date_id"] = (df_data.index.date - df_data.index.date.min()).astype(
"timedelta64[D]"
)
df_data["date_id"] = df_data["date_id"].dt.days + 1
df_data["OC_High"] = df_data[["Open", "Close"]].max(axis=1)
df_data["OC_Low"] = df_data[["Open", "Close"]].min(axis=1)
return df_data
def process_candle(df_data: pd.DataFrame) -> pd.DataFrame:
"""Process DataFrame into candle style plot
Parameters
----------
df_data : DataFrame
Stock dataframe.
Returns
-------
DataFrame
A Panda's data frame with columns Open, High, Low, Close, Adj Close, Volume, date_id, OC-High, OC-Low.
"""
df_data["date_id"] = (df_data.index.date - df_data.index.date.min()).astype(
"timedelta64[D]"
)
df_data["date_id"] = df_data["date_id"].dt.days + 1
df_data["OC_High"] = df_data[["Open", "Close"]].max(axis=1)
df_data["OC_Low"] = df_data[["Open", "Close"]].min(axis=1)
return df_data
def find_trendline(
df_data: pd.DataFrame, y_key: str, high_low: str = "high"
) -> pd.DataFrame:
"""Attempts to find a trend line based on y_key column from a given stock ticker data frame.
Parameters
----------
df_data : DataFrame
The stock ticker data frame with at least date_id, y_key columns.
y_key : str
Column name to base the trend line on.
high_low: str, optional
Either "high" or "low". High is the default.
Returns
-------
DataFrame
If a trend is successfully found,
An updated Panda's data frame with a trend data {y_key}_trend column.
If no trend was found,
An original Panda's data frame
"""
for iteration in [3, 4, 5, 6, 7]:
df_temp = df_data.copy()
while len(df_temp) > iteration:
reg = stats.linregress(
x=df_temp["date_id"],
y=df_temp[y_key],
)
if high_low == "high":
df_temp = df_temp.loc[
df_temp[y_key] > reg[0] * df_temp["date_id"] + reg[1]
]
else:
df_temp = df_temp.loc[
df_temp[y_key] < reg[0] * df_temp["date_id"] + reg[1]
]
if len(df_temp) > 1:
break
if len(df_temp) == 1:
return df_data
reg = stats.linregress(
x=df_temp["date_id"],
y=df_temp[y_key],
)
df_data[f"{y_key}_trend"] = reg[0] * df_data["date_id"] + reg[1]
return df_data