mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-10-27 20:42:26 +00:00
Add fibonacci level indicator. Improve TA menu in general. (#572)
* Customize `fib` to allow user entry of min/max dates * Add docs to overlap. Update VWAP plot to be just last day of intraday data * Volatility update. Default load to 2020-01-01 * Momentum update * Volume update (ad was incorrect) * Update READme * main readme * Edit ad plot * Update README.md * Update fib plot + menu spacings * Fix mypy error with start_date
This commit is contained in:
5
gamestonk_terminal/README.md
vendored
5
gamestonk_terminal/README.md
vendored
@@ -219,9 +219,10 @@ Command | Description | Sources
|
||||
[volatility](https://github.com/twopirllc/pandas-ta/tree/master/pandas_ta/volatility) |
|
||||
`bbands` |bollinger bands | [Wikipedia](https://en.wikipedia.org/wiki/Bollinger_Bands), [Investopedia](https://www.investopedia.com/terms/b/bollingerbands.asp)
|
||||
[volume](https://github.com/twopirllc/pandas-ta/tree/master/pandas_ta/volume) |
|
||||
`ad` |chaikin accumulation/distribution line values | [Wikipedia](https://en.wikipedia.org/wiki/Accumulation/distribution_index), [Investopedia](https://www.investopedia.com/terms/a/accumulationdistribution.asp)
|
||||
`ad` |accumulation/distribution line values | [Wikipedia](https://en.wikipedia.org/wiki/Accumulation/distribution_index), [Investopedia](https://www.investopedia.com/terms/a/accumulationdistribution.asp)
|
||||
`obv` |on balance volume | [Wikipedia](https://en.wikipedia.org/wiki/On-balance_volume), [Investopedia](https://www.investopedia.com/terms/o/onbalancevolume.asp)
|
||||
|
||||
custom|
|
||||
`fib` | Fibonocci levels | [Investopedia](https://www.investopedia.com/terms/f/fibonacciretracement.asp)
|
||||
|
||||
|
||||
## Due Diligence [»](due_diligence/README.md)
|
||||
|
||||
@@ -42,7 +42,13 @@ from gamestonk_terminal import thought_of_the_day as thought
|
||||
from gamestonk_terminal.technical_analysis import trendline_api as trend
|
||||
|
||||
|
||||
def clear(other_args: List[str], s_ticker, s_start, s_interval, df_stock):
|
||||
def clear(
|
||||
other_args: List[str],
|
||||
s_ticker: str,
|
||||
s_start,
|
||||
s_interval: str,
|
||||
df_stock: pd.DataFrame,
|
||||
):
|
||||
"""Clears loaded stock and returns empty variables
|
||||
|
||||
Parameters
|
||||
@@ -89,7 +95,13 @@ def clear(other_args: List[str], s_ticker, s_start, s_interval, df_stock):
|
||||
return s_ticker, s_start, s_interval, df_stock
|
||||
|
||||
|
||||
def load(other_args: List[str], s_ticker, s_start, s_interval, df_stock):
|
||||
def load(
|
||||
other_args: List[str],
|
||||
s_ticker: str,
|
||||
s_start,
|
||||
s_interval: str,
|
||||
df_stock: pd.DataFrame,
|
||||
):
|
||||
"""Load selected ticker
|
||||
|
||||
Parameters
|
||||
@@ -136,7 +148,7 @@ def load(other_args: List[str], s_ticker, s_start, s_interval, df_stock):
|
||||
"-s",
|
||||
"--start",
|
||||
type=valid_date,
|
||||
default="2019-01-01",
|
||||
default=(datetime.now() - timedelta(days=366)).strftime("%Y-%m-%d"),
|
||||
dest="s_start_date",
|
||||
help="The starting date (format YYYY-MM-DD) of the stock",
|
||||
)
|
||||
@@ -601,7 +613,7 @@ def quote(other_args: List[str], s_ticker: str):
|
||||
return
|
||||
|
||||
|
||||
def view(other_args: List[str], s_ticker: str, s_interval, df_stock):
|
||||
def view(other_args: List[str], s_ticker: str, s_interval: str, df_stock: pd.DataFrame):
|
||||
"""Plot loaded ticker
|
||||
|
||||
Parameters
|
||||
|
||||
32
gamestonk_terminal/technical_analysis/README.md
vendored
32
gamestonk_terminal/technical_analysis/README.md
vendored
@@ -41,10 +41,15 @@ This menu aims to perform a technical analysis on a pre-loaded ticker chart, and
|
||||
|
||||
[VOLUME](#VOLUME)
|
||||
* [ad](#ad)
|
||||
- chaikin accumulation/distribution line values
|
||||
- Accumulation/distribution line values
|
||||
* [obv](#obv)
|
||||
- on balance volume
|
||||
|
||||
[CUSTOM](#CUSTOM)
|
||||
* [fib](#fib)
|
||||
- Shows fibonocci levels
|
||||
|
||||
|
||||
**S/O to https://github.com/twopirllc/pandas-ta** _Owing to this library, it is fairly easy to add other technical indicators. So, let us know if there's any other that you would like._
|
||||
|
||||
## view <a name="view"></a>
|
||||
@@ -111,10 +116,11 @@ usage: sma [-l L_LENGTH] [-o N_OFFSET]
|
||||
|
||||
|
||||
## vwap <a name="vwap"></a>
|
||||
VWAP is available for intraday data. This plots the most recent day only.
|
||||
```
|
||||
usage: vwap [-o N_OFFSET]
|
||||
```
|
||||

|
||||

|
||||
|
||||
|
||||
# MOMENTUM <a name="MOMENTUM"></a>
|
||||
@@ -178,11 +184,29 @@ usage: bbands [-h] [-l N_LENGTH] [-s N_STD] [-m S_MAMODE] [-o N_OFFSET]
|
||||
```
|
||||
usage: ad [-o N_OFFSET] [--open]
|
||||
```
|
||||

|
||||

|
||||
|
||||
|
||||
## obv <a name="obv"></a>
|
||||
```
|
||||
usage: obv [-o N_OFFSET]
|
||||
```
|
||||

|
||||

|
||||
|
||||
# CUSTOM <a name="CUSTOM"></a>
|
||||
|
||||
## fib <a name="fib"></a>
|
||||
Shows fibonocci levels
|
||||
```python
|
||||
usage: fib [-p PERIOD] [--start] [--end]
|
||||
```
|
||||
* -p/--period: Number of days to lookback for retracement. Default = 120.
|
||||
* --start: Allows for custom selection of min point.
|
||||
* --end : Allows for custom selection of max point.
|
||||
|
||||
The fibonocci retracement works by looking at a minimum and maximum point. Between these values, there is typically support/resistance at
|
||||
23.5 %, 38.2%, 50% and 61.8%. Those values follow the golden ratio from the fibonocci sequence.
|
||||
|
||||
The `--start` and `--end` flags allow the user to select dates for the min and max points as your retracement levels. Both flags are required if using.
|
||||
|
||||

|
||||
|
||||
153
gamestonk_terminal/technical_analysis/custom_indicators_view.py
Normal file
153
gamestonk_terminal/technical_analysis/custom_indicators_view.py
Normal file
@@ -0,0 +1,153 @@
|
||||
"""Custom TA indicators"""
|
||||
__docformat__ = "numpy"
|
||||
|
||||
import argparse
|
||||
from typing import List
|
||||
import pandas as pd
|
||||
import matplotlib.pyplot as plt
|
||||
from tabulate import tabulate
|
||||
|
||||
from gamestonk_terminal.helper_funcs import (
|
||||
parse_known_args_and_warn,
|
||||
plot_autoscale,
|
||||
valid_date,
|
||||
)
|
||||
|
||||
from gamestonk_terminal import config_plot as cfp
|
||||
from gamestonk_terminal import feature_flags as gtff
|
||||
|
||||
|
||||
def fibinocci_retracement(other_args: List[str], data: pd.DataFrame, ticker: str):
|
||||
"""Calculate fibinocci retracement levels
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args:List[str]
|
||||
Argparse arguments
|
||||
data: pd.DataFrame
|
||||
Stock data
|
||||
ticker:str
|
||||
Stock ticker
|
||||
"""
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
prog="fib",
|
||||
description="Calculates the fibinocci retracement levels",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-p",
|
||||
"--period",
|
||||
dest="period",
|
||||
type=int,
|
||||
help="Days to lookback for retracement",
|
||||
default=120,
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--start",
|
||||
dest="start",
|
||||
type=valid_date,
|
||||
help="Starting date to select",
|
||||
required="--end" in other_args,
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--end",
|
||||
dest="end",
|
||||
type=valid_date,
|
||||
help="Ending date to select",
|
||||
required="--start" in other_args,
|
||||
)
|
||||
|
||||
try:
|
||||
ns_parser = parse_known_args_and_warn(parser, other_args)
|
||||
if not ns_parser:
|
||||
return
|
||||
|
||||
if ns_parser.start and ns_parser.end:
|
||||
|
||||
if ns_parser.start not in data.index:
|
||||
date0 = data.index[
|
||||
data.index.get_loc(ns_parser.start, method="nearest")
|
||||
]
|
||||
print(f"Start date not in data. Using nearest: {date0}")
|
||||
else:
|
||||
date0 = ns_parser.start
|
||||
if ns_parser.end not in data.index:
|
||||
date1 = data.index[data.index.get_loc(ns_parser.end, method="nearest")]
|
||||
print(f"End date not in data. Using nearest: {date1}")
|
||||
else:
|
||||
date1 = ns_parser.end
|
||||
|
||||
data0 = data.loc[date0, "Adj Close"]
|
||||
data1 = data.loc[date1, "Adj Close"]
|
||||
|
||||
min_pr = min(data0, data1)
|
||||
max_pr = max(data0, data1)
|
||||
|
||||
if min_pr == data0:
|
||||
min_date = date0
|
||||
max_date = date1
|
||||
else:
|
||||
min_date = date1
|
||||
max_date = date0
|
||||
|
||||
else:
|
||||
data_to_use = data.iloc[-ns_parser.period :]["Adj Close"]
|
||||
|
||||
min_pr = data_to_use.min()
|
||||
min_date = data_to_use.idxmin()
|
||||
max_pr = data_to_use.max()
|
||||
max_date = data_to_use.idxmax()
|
||||
|
||||
fib_levels = [0, 0.235, 0.382, 0.5, 0.618, 1]
|
||||
price_dif = max_pr - min_pr
|
||||
|
||||
levels = [round(max_pr - price_dif * f_lev, 2) for f_lev in fib_levels]
|
||||
|
||||
df = pd.DataFrame()
|
||||
df["Level"] = fib_levels
|
||||
df["Level"] = df["Level"].apply(lambda x: str(x * 100) + "%")
|
||||
df["Price"] = levels
|
||||
|
||||
fig, ax = plt.subplots(figsize=(plot_autoscale()), dpi=cfp.PLOT_DPI)
|
||||
|
||||
ax.plot(data["Adj Close"], "b")
|
||||
ax.plot([min_date, max_date], [min_pr, max_pr], c="k")
|
||||
|
||||
for i in levels:
|
||||
ax.axhline(y=i, c="g", alpha=0.5)
|
||||
|
||||
for i in range(5):
|
||||
ax.fill_between(data.index, levels[i], levels[i + 1], alpha=0.6)
|
||||
|
||||
ax.set_ylabel("Price")
|
||||
ax.set_title(f"Fibonacci Support for {ticker.upper()}")
|
||||
ax.set_xlim(data.index[0], data.index[-1])
|
||||
|
||||
ax1 = ax.twinx()
|
||||
ax1.set_ylim(ax.get_ylim())
|
||||
ax1.set_yticks(levels)
|
||||
ax1.set_yticklabels(fib_levels)
|
||||
|
||||
plt.gcf().autofmt_xdate()
|
||||
fig.tight_layout(pad=1)
|
||||
|
||||
if gtff.USE_ION:
|
||||
plt.ion()
|
||||
plt.show()
|
||||
|
||||
print(
|
||||
tabulate(
|
||||
df,
|
||||
headers=["Fib Level", "Price"],
|
||||
showindex=False,
|
||||
tablefmt="fancy_grid",
|
||||
)
|
||||
)
|
||||
print("")
|
||||
|
||||
except Exception as e:
|
||||
print(e, "\n")
|
||||
@@ -1,7 +1,14 @@
|
||||
"""Momentum Technical Analysis"""
|
||||
__docformat__ = "numpy"
|
||||
|
||||
import argparse
|
||||
from typing import List
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import pandas_ta as ta
|
||||
import pandas as pd
|
||||
from pandas.plotting import register_matplotlib_converters
|
||||
|
||||
from gamestonk_terminal.helper_funcs import (
|
||||
check_positive,
|
||||
parse_known_args_and_warn,
|
||||
@@ -13,7 +20,21 @@ from gamestonk_terminal import feature_flags as gtff
|
||||
register_matplotlib_converters()
|
||||
|
||||
|
||||
def cci(l_args, s_ticker, s_interval, df_stock):
|
||||
def cci(other_args: List[str], s_ticker: str, s_interval: str, df_stock: pd.DataFrame):
|
||||
"""Commodity channel index
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args:List[str]
|
||||
Argparse arguments
|
||||
s_ticker: str
|
||||
Ticker
|
||||
s_interval: str
|
||||
Stock time interval
|
||||
df_stock: pd.DataFrame
|
||||
Dataframe of prices
|
||||
"""
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
@@ -56,7 +77,7 @@ def cci(l_args, s_ticker, s_interval, df_stock):
|
||||
)
|
||||
|
||||
try:
|
||||
ns_parser = parse_known_args_and_warn(parser, l_args)
|
||||
ns_parser = parse_known_args_and_warn(parser, other_args)
|
||||
if not ns_parser:
|
||||
return
|
||||
|
||||
@@ -82,46 +103,63 @@ def cci(l_args, s_ticker, s_interval, df_stock):
|
||||
offset=ns_parser.n_offset,
|
||||
).dropna()
|
||||
|
||||
plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI)
|
||||
plt.subplot(211)
|
||||
plt.title(f"Commodity Channel Index (CCI) on {s_ticker}")
|
||||
fig, axes = plt.subplots(2, 1, figsize=plot_autoscale(), dpi=PLOT_DPI)
|
||||
ax = axes[0]
|
||||
ax.set_title(f"{s_ticker} CCI")
|
||||
if s_interval == "1440min":
|
||||
plt.plot(df_stock.index, df_stock["Adj Close"].values, "k", lw=2)
|
||||
ax.plot(df_stock.index, df_stock["Adj Close"].values, "k", lw=2)
|
||||
else:
|
||||
plt.plot(df_stock.index, df_stock["Close"].values, "k", lw=2)
|
||||
plt.xlim(df_stock.index[0], df_stock.index[-1])
|
||||
plt.ylabel("Share Price ($)")
|
||||
plt.grid(b=True, which="major", color="#666666", linestyle="-")
|
||||
plt.minorticks_on()
|
||||
plt.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
|
||||
plt.subplot(212)
|
||||
plt.plot(df_ta.index, df_ta.values, "b", lw=2)
|
||||
plt.xlim(df_stock.index[0], df_stock.index[-1])
|
||||
plt.axhspan(100, plt.gca().get_ylim()[1], facecolor="r", alpha=0.2)
|
||||
plt.axhspan(plt.gca().get_ylim()[0], -100, facecolor="g", alpha=0.2)
|
||||
plt.axhline(100, linewidth=3, color="r", ls="--")
|
||||
plt.axhline(-100, linewidth=3, color="g", ls="--")
|
||||
plt.xlabel("Time")
|
||||
plt.grid(b=True, which="major", color="#666666", linestyle="-")
|
||||
plt.minorticks_on()
|
||||
plt.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
|
||||
plt.gca().twinx()
|
||||
plt.ylim(plt.gca().get_ylim())
|
||||
plt.yticks([0.2, 0.8], ("OVERSOLD", "OVERBOUGHT"))
|
||||
ax.plot(df_stock.index, df_stock["Close"].values, "k", lw=2)
|
||||
ax.set_xlim(df_stock.index[0], df_stock.index[-1])
|
||||
ax.set_ylabel("Share Price ($)")
|
||||
ax.grid(b=True, which="major", color="#666666", linestyle="-")
|
||||
ax.minorticks_on()
|
||||
ax.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
|
||||
ax2 = axes[1]
|
||||
ax2.plot(df_ta.index, df_ta.values, "b", lw=2)
|
||||
ax2.set_xlim(df_stock.index[0], df_stock.index[-1])
|
||||
ax2.axhspan(100, plt.gca().get_ylim()[1], facecolor="r", alpha=0.2)
|
||||
ax2.axhspan(plt.gca().get_ylim()[0], -100, facecolor="g", alpha=0.2)
|
||||
ax2.axhline(100, linewidth=3, color="r", ls="--")
|
||||
ax2.axhline(-100, linewidth=3, color="g", ls="--")
|
||||
ax2.grid(b=True, which="major", color="#666666", linestyle="-")
|
||||
ax2.minorticks_on()
|
||||
ax2.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
|
||||
|
||||
ax3 = ax2.twinx()
|
||||
ax3.set_ylim(ax2.get_ylim())
|
||||
ax3.set_yticks([-100, 100])
|
||||
ax3.set_yticklabels(["OVERSOLD", "OVERBOUGHT"])
|
||||
|
||||
if gtff.USE_ION:
|
||||
plt.ion()
|
||||
|
||||
plt.gcf().autofmt_xdate()
|
||||
fig.tight_layout(pad=1)
|
||||
|
||||
plt.show()
|
||||
|
||||
print("")
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
print("")
|
||||
print(e, "\n")
|
||||
|
||||
|
||||
def macd(l_args, s_ticker, s_interval, df_stock):
|
||||
def macd(other_args: List[str], s_ticker: str, s_interval: str, df_stock: pd.DataFrame):
|
||||
"""Moving average convergence divergence
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args:List[str]
|
||||
Argparse arguments
|
||||
s_ticker: str
|
||||
Ticker
|
||||
s_interval: str
|
||||
Stock time interval
|
||||
df_stock: pd.DataFrame
|
||||
Dataframe of prices
|
||||
"""
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
@@ -176,7 +214,7 @@ def macd(l_args, s_ticker, s_interval, df_stock):
|
||||
)
|
||||
|
||||
try:
|
||||
ns_parser = parse_known_args_and_warn(parser, l_args)
|
||||
ns_parser = parse_known_args_and_warn(parser, other_args)
|
||||
if not ns_parser:
|
||||
return
|
||||
|
||||
@@ -200,47 +238,63 @@ def macd(l_args, s_ticker, s_interval, df_stock):
|
||||
offset=ns_parser.n_offset,
|
||||
).dropna()
|
||||
|
||||
plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI)
|
||||
plt.subplot(211)
|
||||
plt.title(f"Moving Average Convergence Divergence (MACD) on {s_ticker}")
|
||||
fig, axes = plt.subplots(2, 1, figsize=plot_autoscale(), dpi=PLOT_DPI)
|
||||
ax = axes[0]
|
||||
ax.set_title(f"{s_ticker} MACD")
|
||||
if s_interval == "1440min":
|
||||
plt.plot(df_stock.index, df_stock["Adj Close"].values, "k", lw=2)
|
||||
ax.plot(df_stock.index, df_stock["Adj Close"].values, "k", lw=2)
|
||||
else:
|
||||
plt.plot(df_stock.index, df_stock["Close"].values, "k", lw=2)
|
||||
plt.xlim(df_stock.index[0], df_stock.index[-1])
|
||||
plt.ylabel("Share Price ($)")
|
||||
plt.grid(b=True, which="major", color="#666666", linestyle="-")
|
||||
plt.minorticks_on()
|
||||
plt.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
|
||||
plt.subplot(212)
|
||||
plt.plot(df_ta.index, df_ta.iloc[:, 0].values, "b", lw=2)
|
||||
plt.plot(df_ta.index, df_ta.iloc[:, 2].values, "r", lw=2)
|
||||
plt.bar(df_ta.index, df_ta.iloc[:, 1].values, color="g")
|
||||
plt.legend(
|
||||
ax.plot(df_stock.index, df_stock["Close"].values, "k", lw=2)
|
||||
ax.set_xlim(df_stock.index[0], df_stock.index[-1])
|
||||
ax.set_ylabel("Share Price ($)")
|
||||
ax.grid(b=True, which="major", color="#666666", linestyle="-")
|
||||
ax.minorticks_on()
|
||||
ax.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
|
||||
ax2 = axes[1]
|
||||
ax2.plot(df_ta.index, df_ta.iloc[:, 0].values, "b", lw=2)
|
||||
ax2.plot(df_ta.index, df_ta.iloc[:, 2].values, "r", lw=2)
|
||||
ax2.bar(df_ta.index, df_ta.iloc[:, 1].values, color="g")
|
||||
ax2.legend(
|
||||
[
|
||||
f"MACD Line {df_ta.columns[0]}",
|
||||
f"Signal Line {df_ta.columns[2]}",
|
||||
f"Histogram {df_ta.columns[1]}",
|
||||
]
|
||||
],
|
||||
loc="upper left",
|
||||
)
|
||||
plt.xlim(df_stock.index[0], df_stock.index[-1])
|
||||
plt.grid(b=True, which="major", color="#666666", linestyle="-")
|
||||
plt.minorticks_on()
|
||||
plt.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
|
||||
plt.xlabel("Time")
|
||||
ax2.set_xlim(df_stock.index[0], df_stock.index[-1])
|
||||
ax2.grid(b=True, which="major", color="#666666", linestyle="-")
|
||||
ax2.minorticks_on()
|
||||
ax2.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
|
||||
|
||||
if gtff.USE_ION:
|
||||
plt.ion()
|
||||
|
||||
plt.gcf().autofmt_xdate()
|
||||
fig.tight_layout(pad=1)
|
||||
|
||||
plt.show()
|
||||
print("")
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
print("")
|
||||
print(e, "\n")
|
||||
|
||||
|
||||
def rsi(l_args, s_ticker, s_interval, df_stock):
|
||||
def rsi(other_args: List[str], s_ticker: str, s_interval: str, df_stock: pd.DataFrame):
|
||||
"""Relative strength index
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args:List[str]
|
||||
Argparse arguments
|
||||
s_ticker: str
|
||||
Ticker
|
||||
s_interval: str
|
||||
Stock time interval
|
||||
df_stock: pd.DataFrame
|
||||
Dataframe of prices
|
||||
"""
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
@@ -292,7 +346,7 @@ def rsi(l_args, s_ticker, s_interval, df_stock):
|
||||
)
|
||||
|
||||
try:
|
||||
ns_parser = parse_known_args_and_warn(parser, l_args)
|
||||
ns_parser = parse_known_args_and_warn(parser, other_args)
|
||||
if not ns_parser:
|
||||
return
|
||||
|
||||
@@ -316,47 +370,65 @@ def rsi(l_args, s_ticker, s_interval, df_stock):
|
||||
offset=ns_parser.n_offset,
|
||||
).dropna()
|
||||
|
||||
plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI)
|
||||
plt.subplot(211)
|
||||
fig, axes = plt.subplots(2, 1, figsize=plot_autoscale(), dpi=PLOT_DPI)
|
||||
ax = axes[0]
|
||||
if s_interval == "1440min":
|
||||
plt.plot(df_stock.index, df_stock["Adj Close"].values, "k", lw=2)
|
||||
ax.plot(df_stock.index, df_stock["Adj Close"].values, "k", lw=2)
|
||||
else:
|
||||
plt.plot(df_stock.index, df_stock["Close"].values, "k", lw=2)
|
||||
plt.title(f"Relative Strength Index (RSI) on {s_ticker}")
|
||||
plt.xlim(df_stock.index[0], df_stock.index[-1])
|
||||
plt.ylabel("Share Price ($)")
|
||||
plt.grid(b=True, which="major", color="#666666", linestyle="-")
|
||||
plt.minorticks_on()
|
||||
plt.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
|
||||
plt.subplot(212)
|
||||
plt.plot(df_ta.index, df_ta.values, "b", lw=2)
|
||||
plt.xlim(df_stock.index[0], df_stock.index[-1])
|
||||
plt.axhspan(70, 100, facecolor="r", alpha=0.2)
|
||||
plt.axhspan(0, 30, facecolor="g", alpha=0.2)
|
||||
plt.axhline(70, linewidth=3, color="r", ls="--")
|
||||
plt.axhline(30, linewidth=3, color="g", ls="--")
|
||||
plt.xlabel("Time")
|
||||
plt.grid(b=True, which="major", color="#666666", linestyle="-")
|
||||
plt.minorticks_on()
|
||||
plt.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
|
||||
plt.ylim([0, 100])
|
||||
plt.gca().twinx()
|
||||
plt.ylim(plt.gca().get_ylim())
|
||||
plt.yticks([0.15, 0.85], ("OVERSOLD", "OVERBOUGHT"))
|
||||
ax.plot(df_stock.index, df_stock["Close"].values, "k", lw=2)
|
||||
ax.set_title(f" {s_ticker} RSI{ns_parser.n_length} ")
|
||||
ax.set_xlim(df_stock.index[0], df_stock.index[-1])
|
||||
ax.set_ylabel("Share Price ($)")
|
||||
ax.grid(b=True, which="major", color="#666666", linestyle="-")
|
||||
ax.minorticks_on()
|
||||
ax.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
|
||||
ax2 = axes[1]
|
||||
ax2.plot(df_ta.index, df_ta.values, "b", lw=2)
|
||||
ax2.set_xlim(df_stock.index[0], df_stock.index[-1])
|
||||
ax2.axhspan(70, 100, facecolor="r", alpha=0.2)
|
||||
ax2.axhspan(0, 30, facecolor="g", alpha=0.2)
|
||||
ax2.axhline(70, linewidth=3, color="r", ls="--")
|
||||
ax2.axhline(30, linewidth=3, color="g", ls="--")
|
||||
ax2.grid(b=True, which="major", color="#666666", linestyle="-")
|
||||
ax2.minorticks_on()
|
||||
ax2.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
|
||||
ax2.set_ylim([0, 100])
|
||||
ax3 = ax2.twinx()
|
||||
ax3.set_ylim(ax2.get_ylim())
|
||||
ax3.set_yticks([30, 70])
|
||||
ax3.set_yticklabels(["OVERSOLD", "OVERBOUGHT"])
|
||||
|
||||
if gtff.USE_ION:
|
||||
plt.ion()
|
||||
|
||||
plt.gcf().autofmt_xdate()
|
||||
fig.tight_layout(pad=1)
|
||||
|
||||
plt.show()
|
||||
|
||||
print("")
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
print("")
|
||||
print(e, "\n")
|
||||
|
||||
|
||||
def stoch(l_args, s_ticker, s_interval, df_stock):
|
||||
def stoch(
|
||||
other_args: List[str], s_ticker: str, s_interval: str, df_stock: pd.DataFrame
|
||||
):
|
||||
"""Stochastic oscillator
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args:List[str]
|
||||
Argparse arguments
|
||||
s_ticker: str
|
||||
Ticker
|
||||
s_interval: str
|
||||
Stock time interval
|
||||
df_stock: pd.DataFrame
|
||||
Dataframe of prices
|
||||
"""
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
@@ -408,7 +480,7 @@ def stoch(l_args, s_ticker, s_interval, df_stock):
|
||||
)
|
||||
|
||||
try:
|
||||
ns_parser = parse_known_args_and_warn(parser, l_args)
|
||||
ns_parser = parse_known_args_and_warn(parser, other_args)
|
||||
if not ns_parser:
|
||||
return
|
||||
|
||||
@@ -436,43 +508,51 @@ def stoch(l_args, s_ticker, s_interval, df_stock):
|
||||
offset=ns_parser.n_offset,
|
||||
).dropna()
|
||||
|
||||
plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI)
|
||||
plt.subplot(211)
|
||||
fig, axes = plt.subplots(2, 1, figsize=plot_autoscale(), dpi=PLOT_DPI)
|
||||
ax = axes[0]
|
||||
if s_interval == "1440min":
|
||||
plt.plot(df_stock.index, df_stock["Adj Close"].values, "k", lw=2)
|
||||
ax.plot(df_stock.index, df_stock["Adj Close"].values, "k", lw=2)
|
||||
else:
|
||||
plt.plot(df_stock.index, df_stock["Close"].values, "k", lw=2)
|
||||
plt.title(f"Stochastic Relative Strength Index (STOCH RSI) on {s_ticker}")
|
||||
plt.xlim(df_stock.index[0], df_stock.index[-1])
|
||||
plt.ylabel("Share Price ($)")
|
||||
plt.grid(b=True, which="major", color="#666666", linestyle="-")
|
||||
plt.minorticks_on()
|
||||
plt.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
|
||||
plt.subplot(212)
|
||||
plt.plot(df_ta.index, df_ta.iloc[:, 0].values, "k", lw=2)
|
||||
plt.plot(df_ta.index, df_ta.iloc[:, 1].values, "b", lw=2, ls="--")
|
||||
plt.xlim(df_stock.index[0], df_stock.index[-1])
|
||||
plt.axhspan(80, 100, facecolor="r", alpha=0.2)
|
||||
plt.axhspan(0, 20, facecolor="g", alpha=0.2)
|
||||
plt.axhline(80, linewidth=3, color="r", ls="--")
|
||||
plt.axhline(20, linewidth=3, color="g", ls="--")
|
||||
plt.legend([f"%K {df_ta.columns[0]}", f"%D {df_ta.columns[1]}"])
|
||||
plt.xlabel("Time")
|
||||
plt.grid(b=True, which="major", color="#666666", linestyle="-")
|
||||
plt.minorticks_on()
|
||||
plt.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
|
||||
plt.ylim([0, 100])
|
||||
plt.gca().twinx()
|
||||
plt.ylim(plt.gca().get_ylim())
|
||||
plt.yticks([0.1, 0.9], ("OVERSOLD", "OVERBOUGHT"))
|
||||
ax.plot(df_stock.index, df_stock["Close"].values, "k", lw=2)
|
||||
ax.set_title(f"Stochastic Relative Strength Index (STOCH RSI) on {s_ticker}")
|
||||
ax.set_xlim(df_stock.index[0], df_stock.index[-1])
|
||||
ax.set_xticklabels([])
|
||||
ax.set_ylabel("Share Price ($)")
|
||||
ax.grid(b=True, which="major", color="#666666", linestyle="-")
|
||||
ax.minorticks_on()
|
||||
ax.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
|
||||
|
||||
ax2 = axes[1]
|
||||
ax2.plot(df_ta.index, df_ta.iloc[:, 0].values, "k", lw=2)
|
||||
ax2.plot(df_ta.index, df_ta.iloc[:, 1].values, "b", lw=2, ls="--")
|
||||
ax2.set_xlim(df_stock.index[0], df_stock.index[-1])
|
||||
|
||||
ax2.axhspan(80, 100, facecolor="r", alpha=0.2)
|
||||
ax2.axhspan(0, 20, facecolor="g", alpha=0.2)
|
||||
ax2.axhline(80, linewidth=3, color="r", ls="--")
|
||||
ax2.axhline(20, linewidth=3, color="g", ls="--")
|
||||
|
||||
ax2.grid(b=True, which="major", color="#666666", linestyle="-")
|
||||
ax2.minorticks_on()
|
||||
ax2.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
|
||||
ax2.set_ylim([0, 100])
|
||||
|
||||
ax3 = ax2.twinx()
|
||||
ax3.set_ylim(ax2.get_ylim())
|
||||
ax3.set_yticks([20, 80])
|
||||
ax3.set_yticklabels(["OVERSOLD", "OVERBOUGHT"])
|
||||
ax2.legend(
|
||||
[f"%K {df_ta.columns[0]}", f"%D {df_ta.columns[1]}"], loc="lower left"
|
||||
)
|
||||
|
||||
if gtff.USE_ION:
|
||||
plt.ion()
|
||||
|
||||
plt.gcf().autofmt_xdate()
|
||||
fig.tight_layout(pad=1)
|
||||
plt.show()
|
||||
|
||||
print("")
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
print("")
|
||||
print(e, "\n")
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
"""Overlap Technical Analysis"""
|
||||
___docformat__ = "numpy"
|
||||
|
||||
import argparse
|
||||
from typing import List
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import pandas as pd
|
||||
import pandas_ta as ta
|
||||
from pandas.plotting import register_matplotlib_converters
|
||||
import mplfinance as mpf
|
||||
|
||||
from gamestonk_terminal.helper_funcs import (
|
||||
check_positive,
|
||||
parse_known_args_and_warn,
|
||||
@@ -13,7 +21,21 @@ from gamestonk_terminal import feature_flags as gtff
|
||||
register_matplotlib_converters()
|
||||
|
||||
|
||||
def ema(l_args, s_ticker, s_interval, df_stock):
|
||||
def ema(other_args: List[str], s_ticker: str, s_interval: str, df_stock: pd.DataFrame):
|
||||
"""Plots exponential moving average (EMA) over stock
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args: List[str]
|
||||
Argparse arguments
|
||||
s_ticker: str
|
||||
Ticker
|
||||
s_interval: str
|
||||
Data interval
|
||||
df_stock: pd.DataFrame
|
||||
Dataframe of dates and prices
|
||||
"""
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
@@ -50,7 +72,7 @@ def ema(l_args, s_ticker, s_interval, df_stock):
|
||||
)
|
||||
|
||||
try:
|
||||
ns_parser = parse_known_args_and_warn(parser, l_args)
|
||||
ns_parser = parse_known_args_and_warn(parser, other_args)
|
||||
if not ns_parser:
|
||||
return
|
||||
|
||||
@@ -70,8 +92,9 @@ def ema(l_args, s_ticker, s_interval, df_stock):
|
||||
offset=ns_parser.n_offset,
|
||||
).dropna()
|
||||
|
||||
_, _ = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
|
||||
plt.title(f"{ns_parser.n_length} EMA on {s_ticker}")
|
||||
fig, _ = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
|
||||
plt.title(f"{ns_parser.n_length} Day EMA on {s_ticker}")
|
||||
|
||||
if s_interval == "1440min":
|
||||
plt.plot(
|
||||
df_stock["Adj Close"].index,
|
||||
@@ -86,17 +109,19 @@ def ema(l_args, s_ticker, s_interval, df_stock):
|
||||
else:
|
||||
plt.plot(df_stock["Close"].index, df_stock["Close"].values, "k", lw=3)
|
||||
plt.xlim(df_stock["Close"].index[0], df_stock["Close"].index[-1])
|
||||
|
||||
plt.xlabel("Time")
|
||||
plt.ylabel(f"Share Price of {s_ticker} ($)")
|
||||
plt.ylabel(f"{s_ticker} Price($)")
|
||||
plt.plot(df_ta.index, df_ta.values, c="tab:blue")
|
||||
l_legend = list()
|
||||
l_legend.append(s_ticker)
|
||||
# Pandas series
|
||||
if len(df_ta.shape) == 1:
|
||||
l_legend.append(f"{ns_parser.n_length} EMA")
|
||||
l_legend.append(f"EMA {ns_parser.n_length}")
|
||||
# Pandas dataframe
|
||||
else:
|
||||
l_legend.append(df_ta.columns.tolist())
|
||||
|
||||
plt.legend(l_legend)
|
||||
plt.grid(b=True, which="major", color="#666666", linestyle="-")
|
||||
plt.minorticks_on()
|
||||
@@ -105,15 +130,30 @@ def ema(l_args, s_ticker, s_interval, df_stock):
|
||||
if gtff.USE_ION:
|
||||
plt.ion()
|
||||
|
||||
plt.gcf().autofmt_xdate()
|
||||
fig.tight_layout(pad=1)
|
||||
|
||||
plt.show()
|
||||
print("")
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
print("")
|
||||
print(e, "\n")
|
||||
|
||||
|
||||
def sma(l_args, s_ticker, s_interval, df_stock):
|
||||
def sma(other_args: List[str], s_ticker: str, s_interval: str, df_stock: pd.DataFrame):
|
||||
"""Plots simple moving average (SMA) over stock
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args: List[str]
|
||||
Argparse arguments
|
||||
s_ticker: str
|
||||
Ticker
|
||||
s_interval: str
|
||||
Data interval
|
||||
df_stock: pd.DataFrame
|
||||
Dataframe of dates and prices
|
||||
"""
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
@@ -148,11 +188,11 @@ def sma(l_args, s_ticker, s_interval, df_stock):
|
||||
)
|
||||
|
||||
try:
|
||||
ns_parser = parse_known_args_and_warn(parser, l_args)
|
||||
ns_parser = parse_known_args_and_warn(parser, other_args)
|
||||
if not ns_parser:
|
||||
return
|
||||
|
||||
plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI)
|
||||
fig, _ = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
|
||||
if s_interval == "1440min":
|
||||
plt.plot(df_stock.index, df_stock["Adj Close"].values, color="k")
|
||||
else:
|
||||
@@ -171,11 +211,12 @@ def sma(l_args, s_ticker, s_interval, df_stock):
|
||||
df_stock["Close"], length=length, offset=ns_parser.n_offset
|
||||
).dropna()
|
||||
plt.plot(df_ta.index, df_ta.values)
|
||||
l_legend.append(f"{length} SMA")
|
||||
l_legend.append(f"SMA{length} ")
|
||||
|
||||
plt.title(f"SMA on {s_ticker}")
|
||||
plt.xlim(df_stock.index[0], df_stock.index[-1])
|
||||
plt.xlabel("Time")
|
||||
plt.ylabel("Share Price ($)")
|
||||
plt.ylabel(f"{s_ticker} Price ($)")
|
||||
plt.legend(l_legend)
|
||||
plt.grid(b=True, which="major", color="#666666", linestyle="-")
|
||||
plt.minorticks_on()
|
||||
@@ -184,15 +225,30 @@ def sma(l_args, s_ticker, s_interval, df_stock):
|
||||
if gtff.USE_ION:
|
||||
plt.ion()
|
||||
|
||||
plt.gcf().autofmt_xdate()
|
||||
fig.tight_layout(pad=1)
|
||||
|
||||
plt.show()
|
||||
print("")
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
print("")
|
||||
print(e, "\n")
|
||||
|
||||
|
||||
def vwap(l_args, s_ticker, s_interval, df_stock):
|
||||
def vwap(other_args: List[str], s_ticker: str, s_interval: str, df_stock: pd.DataFrame):
|
||||
"""Plots volume weighted average price (VWAP)
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args: List[str]
|
||||
Argparse arguments
|
||||
s_ticker: str
|
||||
Ticker
|
||||
s_interval: str
|
||||
Data interval
|
||||
df_stock: pd.DataFrame
|
||||
Dataframe of dates and prices
|
||||
"""
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
@@ -214,63 +270,41 @@ def vwap(l_args, s_ticker, s_interval, df_stock):
|
||||
)
|
||||
|
||||
try:
|
||||
ns_parser = parse_known_args_and_warn(parser, l_args)
|
||||
ns_parser = parse_known_args_and_warn(parser, other_args)
|
||||
if not ns_parser:
|
||||
return
|
||||
|
||||
# Daily
|
||||
if s_interval == "1440min":
|
||||
df_ta = ta.vwap(
|
||||
high=df_stock["High"],
|
||||
low=df_stock["Low"],
|
||||
close=df_stock["Adj Close"],
|
||||
volume=df_stock["Volume"],
|
||||
offset=ns_parser.n_offset,
|
||||
)
|
||||
print("VWAP should be used with intraday data. \n")
|
||||
return
|
||||
|
||||
# Intraday
|
||||
else:
|
||||
df_ta = ta.vwap(
|
||||
high=df_stock["High"],
|
||||
low=df_stock["Low"],
|
||||
close=df_stock["Close"],
|
||||
volume=df_stock["Volume"],
|
||||
offset=ns_parser.n_offset,
|
||||
)
|
||||
df_stock.index = df_stock.index.tz_localize(None)
|
||||
df_stock["Day"] = [idx.date() for idx in df_stock.index]
|
||||
|
||||
_, axPrice = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
|
||||
if s_interval == "1440min":
|
||||
plt.plot(df_stock.index, df_stock["Adj Close"].values, color="k")
|
||||
else:
|
||||
plt.plot(df_stock.index, df_stock["Close"].values, color="k")
|
||||
plt.plot(df_ta.index, df_ta.values)
|
||||
plt.title(f"VWAP on {s_ticker}")
|
||||
plt.xlim(df_stock.index[0], df_stock.index[-1])
|
||||
plt.xlabel("Time")
|
||||
plt.ylabel("Share Price ($)")
|
||||
plt.legend([s_ticker, "VWAP"])
|
||||
_ = axPrice.twinx()
|
||||
day_df = df_stock[df_stock.Day == df_stock.Day[-1]]
|
||||
|
||||
if s_interval == "1440min":
|
||||
plt.bar(
|
||||
df_stock.index,
|
||||
df_stock["Volume"].values,
|
||||
color="k",
|
||||
alpha=0.8,
|
||||
width=0.3,
|
||||
)
|
||||
else:
|
||||
plt.bar(
|
||||
df_stock.index,
|
||||
df_stock["Volume"].values,
|
||||
color="k",
|
||||
alpha=0.8,
|
||||
width=0.3,
|
||||
)
|
||||
plt.ylabel("Volume")
|
||||
plt.grid(b=True, which="major", color="#666666", linestyle="-")
|
||||
plt.minorticks_on()
|
||||
plt.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
|
||||
df_vwap = ta.vwap(
|
||||
high=day_df["High"],
|
||||
low=day_df["Low"],
|
||||
close=day_df["Close"],
|
||||
volume=day_df["Volume"],
|
||||
)
|
||||
|
||||
mc = mpf.make_marketcolors(
|
||||
up="green", down="red", edge="black", wick="black", volume="in", ohlc="i"
|
||||
)
|
||||
|
||||
s = mpf.make_mpf_style(marketcolors=mc, gridstyle=":", y_on_right=True)
|
||||
apdict = mpf.make_addplot(df_vwap, color="k")
|
||||
mpf.plot(
|
||||
day_df,
|
||||
style=s,
|
||||
type="candle",
|
||||
addplot=apdict,
|
||||
volume=True,
|
||||
title=f"\n{s_ticker} {s_interval} VWAP",
|
||||
)
|
||||
|
||||
if gtff.USE_ION:
|
||||
plt.ion()
|
||||
@@ -279,5 +313,4 @@ def vwap(l_args, s_ticker, s_interval, df_stock):
|
||||
print("")
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
print("")
|
||||
print(e, "\n")
|
||||
|
||||
@@ -21,6 +21,7 @@ from gamestonk_terminal.technical_analysis import finbrain_view
|
||||
from gamestonk_terminal.technical_analysis import tradingview_view
|
||||
from gamestonk_terminal.technical_analysis import finviz_view
|
||||
from gamestonk_terminal.technical_analysis import finnhub_view
|
||||
from gamestonk_terminal.technical_analysis import custom_indicators_view
|
||||
|
||||
|
||||
class TechnicalAnalysisController:
|
||||
@@ -49,6 +50,7 @@ class TechnicalAnalysisController:
|
||||
"bbands",
|
||||
"ad",
|
||||
"obv",
|
||||
"fib",
|
||||
]
|
||||
|
||||
def __init__(
|
||||
@@ -112,8 +114,10 @@ class TechnicalAnalysisController:
|
||||
print("volatility:")
|
||||
print(" bbands bollinger bands")
|
||||
print("volume:")
|
||||
print(" ad chaikin accumulation/distribution line values")
|
||||
print(" ad accumulation/distribution line values")
|
||||
print(" obv on balance volume")
|
||||
print("custom:")
|
||||
print(" fib fibonocci retracement")
|
||||
print("")
|
||||
|
||||
def switch(self, an_input: str):
|
||||
@@ -229,6 +233,12 @@ class TechnicalAnalysisController:
|
||||
"""Process obv command"""
|
||||
ta_volume.obv(other_args, self.ticker, self.interval, self.stock)
|
||||
|
||||
def call_fib(self, other_args: List[str]):
|
||||
"""Process fib command"""
|
||||
custom_indicators_view.fibinocci_retracement(
|
||||
other_args, self.stock, self.ticker
|
||||
)
|
||||
|
||||
|
||||
def menu(
|
||||
ticker: str, start: datetime, interval: str, stock: pd.DataFrame, context: str = ""
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
"""Volatility Technical Indicators"""
|
||||
__docformat__ = "numpy"
|
||||
|
||||
import argparse
|
||||
from typing import List
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import pandas_ta as ta
|
||||
from pandas.plotting import register_matplotlib_converters
|
||||
import pandas as pd
|
||||
|
||||
from gamestonk_terminal.helper_funcs import (
|
||||
check_positive,
|
||||
parse_known_args_and_warn,
|
||||
@@ -13,7 +20,23 @@ from gamestonk_terminal import feature_flags as gtff
|
||||
register_matplotlib_converters()
|
||||
|
||||
|
||||
def bbands(l_args, s_ticker, s_interval, df_stock):
|
||||
def bbands(
|
||||
other_args: List[str], s_ticker: str, s_interval: str, df_stock: pd.DataFrame
|
||||
):
|
||||
"""Plot Bollinger Bands
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args: List[str]
|
||||
Argparse arguments
|
||||
s_ticker: str
|
||||
Ticker
|
||||
s_interval: str
|
||||
Interval
|
||||
df_stock: pd.DataFrame
|
||||
Stock dataframe
|
||||
"""
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
@@ -64,7 +87,7 @@ def bbands(l_args, s_ticker, s_interval, df_stock):
|
||||
)
|
||||
|
||||
try:
|
||||
ns_parser = parse_known_args_and_warn(parser, l_args)
|
||||
ns_parser = parse_known_args_and_warn(parser, other_args)
|
||||
if not ns_parser:
|
||||
return
|
||||
|
||||
@@ -88,33 +111,37 @@ def bbands(l_args, s_ticker, s_interval, df_stock):
|
||||
offset=ns_parser.n_offset,
|
||||
).dropna()
|
||||
|
||||
plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI)
|
||||
fig, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
|
||||
if s_ticker == "1440min":
|
||||
plt.plot(df_stock.index, df_stock["Adj Close"].values, color="k", lw=3)
|
||||
ax.plot(df_stock.index, df_stock["Adj Close"].values, color="k", lw=3)
|
||||
else:
|
||||
plt.plot(df_stock.index, df_stock["Close"].values, color="k", lw=3)
|
||||
ax.plot(df_stock.index, df_stock["Close"].values, color="k", lw=3)
|
||||
plt.plot(df_ta.index, df_ta.iloc[:, 0].values, "r", lw=2)
|
||||
plt.plot(df_ta.index, df_ta.iloc[:, 1].values, "b", lw=1.5, ls="--")
|
||||
plt.plot(df_ta.index, df_ta.iloc[:, 2].values, "g", lw=2)
|
||||
plt.title(f"Bollinger Band (BBands) on {s_ticker}")
|
||||
plt.xlim(df_stock.index[0], df_stock.index[-1])
|
||||
plt.xlabel("Time")
|
||||
plt.ylabel("Share Price ($)")
|
||||
ax.plot(df_ta.index, df_ta.iloc[:, 1].values, "b", lw=1.5, ls="--")
|
||||
ax.plot(df_ta.index, df_ta.iloc[:, 2].values, "g", lw=2)
|
||||
ax.set_title(f"{s_ticker} Bollinger Bands")
|
||||
ax.set_xlim(df_stock.index[0], df_stock.index[-1])
|
||||
ax.set_xlabel("Time")
|
||||
ax.set_ylabel("Share Price ($)")
|
||||
|
||||
plt.legend([s_ticker, df_ta.columns[0], df_ta.columns[1], df_ta.columns[2]])
|
||||
plt.gca().fill_between(
|
||||
ax.fill_between(
|
||||
df_ta.index,
|
||||
df_ta.iloc[:, 0].values,
|
||||
df_ta.iloc[:, 2].values,
|
||||
alpha=0.1,
|
||||
color="b",
|
||||
)
|
||||
plt.grid(b=True, which="major", color="#666666", linestyle="-")
|
||||
ax.grid(b=True, which="major", color="#666666", linestyle="-")
|
||||
plt.minorticks_on()
|
||||
plt.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
|
||||
|
||||
if gtff.USE_ION:
|
||||
plt.ion()
|
||||
|
||||
plt.gcf().autofmt_xdate()
|
||||
fig.tight_layout(pad=1)
|
||||
|
||||
plt.show()
|
||||
print("")
|
||||
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
"""Volume Technical Analysis"""
|
||||
__docformat__ = "numpy"
|
||||
|
||||
import argparse
|
||||
from typing import List
|
||||
from datetime import timedelta
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import pandas_ta as ta
|
||||
import pandas as pd
|
||||
|
||||
from pandas.plotting import register_matplotlib_converters
|
||||
from gamestonk_terminal.helper_funcs import (
|
||||
check_positive,
|
||||
@@ -13,7 +21,21 @@ from gamestonk_terminal import feature_flags as gtff
|
||||
register_matplotlib_converters()
|
||||
|
||||
|
||||
def ad(l_args, s_ticker, s_interval, df_stock):
|
||||
def ad(other_args: List[str], s_ticker: str, s_interval: str, df_stock: pd.DataFrame):
|
||||
"""Accumulation Dictribution Line
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args: List[str]
|
||||
Argparse arguments
|
||||
s_ticker: str
|
||||
Ticker
|
||||
s_interval: str
|
||||
Stock data interval
|
||||
df_stock: pd.DataFrame
|
||||
Dataframe of stock prices
|
||||
"""
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
@@ -50,107 +72,115 @@ def ad(l_args, s_ticker, s_interval, df_stock):
|
||||
)
|
||||
|
||||
try:
|
||||
ns_parser = parse_known_args_and_warn(parser, l_args)
|
||||
ns_parser = parse_known_args_and_warn(parser, other_args)
|
||||
if not ns_parser:
|
||||
return
|
||||
|
||||
# Daily
|
||||
if s_interval == "1440min":
|
||||
# Use open stock values
|
||||
if ns_parser.b_use_open:
|
||||
df_ta = ta.ad(
|
||||
high=df_stock["High"],
|
||||
low=df_stock["Low"],
|
||||
close=df_stock["Adj Close"],
|
||||
volume=df_stock["Volume"],
|
||||
offset=ns_parser.n_offset,
|
||||
open_=df_stock["Open"],
|
||||
).dropna()
|
||||
# Do not use open stock values
|
||||
else:
|
||||
df_ta = ta.ad(
|
||||
high=df_stock["High"],
|
||||
low=df_stock["Low"],
|
||||
close=df_stock["Adj Close"],
|
||||
volume=df_stock["Volume"],
|
||||
offset=ns_parser.n_offset,
|
||||
).dropna()
|
||||
bar_colors = [
|
||||
"r" if x[1].Open < x[1].Close else "g" for x in df_stock.iterrows()
|
||||
]
|
||||
|
||||
# Intraday
|
||||
if s_interval == "1440min":
|
||||
bar_width = timedelta(days=1)
|
||||
else:
|
||||
# Use open stock values
|
||||
if ns_parser.b_use_open:
|
||||
df_ta = ta.ad(
|
||||
high=df_stock["High"],
|
||||
low=df_stock["Low"],
|
||||
close=df_stock["Close"],
|
||||
volume=df_stock["Volume"],
|
||||
offset=ns_parser.n_offset,
|
||||
open_=df_stock["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"],
|
||||
offset=ns_parser.n_offset,
|
||||
).dropna()
|
||||
bar_width = timedelta(minutes=int(s_interval.split("m")[0]))
|
||||
|
||||
plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI)
|
||||
axPrice = plt.subplot(211)
|
||||
if s_interval == "1440min":
|
||||
plt.plot(df_stock.index, df_stock["Adj Close"].values, "k", lw=2)
|
||||
if ns_parser.b_use_open:
|
||||
df_ta = ta.ad(
|
||||
high=df_stock["High"],
|
||||
low=df_stock["Low"],
|
||||
close=df_stock["Adj Close"],
|
||||
volume=df_stock["Volume"],
|
||||
offset=ns_parser.n_offset,
|
||||
open_=df_stock["Open"],
|
||||
).dropna()
|
||||
# Do not use open stock values
|
||||
else:
|
||||
plt.plot(df_stock.index, df_stock["Close"].values, "k", lw=2)
|
||||
plt.title(f"Accumulation/Distribution Line (AD) on {s_ticker}")
|
||||
plt.xlim(df_stock.index[0], df_stock.index[-1])
|
||||
plt.ylabel("Share Price ($)")
|
||||
plt.grid(b=True, which="major", color="#666666", linestyle="-")
|
||||
plt.minorticks_on()
|
||||
plt.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
|
||||
_ = axPrice.twinx()
|
||||
# Note this should always be Close not Adj Close
|
||||
df_ta = ta.ad(
|
||||
high=df_stock["High"],
|
||||
low=df_stock["Low"],
|
||||
close=df_stock["Close"],
|
||||
volume=df_stock["Volume"],
|
||||
offset=ns_parser.n_offset,
|
||||
).dropna()
|
||||
|
||||
fig, axes = plt.subplots(
|
||||
3,
|
||||
1,
|
||||
gridspec_kw={"height_ratios": [2, 1, 1]},
|
||||
figsize=plot_autoscale(),
|
||||
dpi=PLOT_DPI,
|
||||
)
|
||||
ax = axes[0]
|
||||
if s_interval == "1440min":
|
||||
plt.bar(
|
||||
ax.plot(df_stock.index, df_stock["Adj Close"].values, "k", lw=2)
|
||||
else:
|
||||
ax.plot(df_stock.index, df_stock["Close"].values, "k", lw=2)
|
||||
ax.set_title(f"{s_ticker} AD")
|
||||
ax.set_xlim(df_stock.index[0], df_stock.index[-1])
|
||||
ax.set_ylabel("Share Price ($)")
|
||||
ax.grid(b=True, which="major", color="#666666", linestyle="-")
|
||||
ax.minorticks_on()
|
||||
ax.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
|
||||
|
||||
ax2 = axes[1]
|
||||
ax2.set_ylabel("Volume")
|
||||
if s_interval == "1440min":
|
||||
ax2.bar(
|
||||
df_stock.index,
|
||||
df_stock["Volume"].values,
|
||||
color="k",
|
||||
color=bar_colors,
|
||||
alpha=0.8,
|
||||
width=0.3,
|
||||
)
|
||||
else:
|
||||
plt.bar(
|
||||
ax2.bar(
|
||||
df_stock.index,
|
||||
df_stock["Volume"].values,
|
||||
color="k",
|
||||
color=bar_colors,
|
||||
alpha=0.8,
|
||||
width=0.3,
|
||||
width=bar_width,
|
||||
)
|
||||
plt.subplot(212)
|
||||
plt.plot(df_ta.index, df_ta.values, "b", lw=1)
|
||||
plt.xlim(df_stock.index[0], df_stock.index[-1])
|
||||
plt.axhline(0, linewidth=2, color="k", ls="--")
|
||||
plt.legend(["Chaikin Oscillator"])
|
||||
plt.xlabel("Time")
|
||||
plt.grid(b=True, which="major", color="#666666", linestyle="-")
|
||||
plt.minorticks_on()
|
||||
plt.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
|
||||
ax2.set_xlim(df_stock.index[0], df_stock.index[-1])
|
||||
|
||||
ax3 = axes[2]
|
||||
ax3.plot(df_ta.index, df_ta.values, "b", lw=1)
|
||||
ax3.set_xlim(df_stock.index[0], df_stock.index[-1])
|
||||
ax3.axhline(0, linewidth=2, color="k", ls="--")
|
||||
ax3.set_ylabel("A/D")
|
||||
ax3.set_xlabel("Time")
|
||||
ax3.grid(b=True, which="major", color="#666666", linestyle="-")
|
||||
ax3.minorticks_on()
|
||||
ax3.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
|
||||
|
||||
if gtff.USE_ION:
|
||||
plt.ion()
|
||||
|
||||
plt.gcf().autofmt_xdate()
|
||||
fig.tight_layout(pad=1)
|
||||
|
||||
plt.show()
|
||||
print("")
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
print("")
|
||||
return
|
||||
print(e, "\n")
|
||||
|
||||
|
||||
def obv(l_args, s_ticker, s_interval, df_stock):
|
||||
"""Technical Analysis with On-Balance Volume indicator"""
|
||||
def obv(other_args: List[str], s_ticker: str, s_interval: str, df_stock: pd.DataFrame):
|
||||
"""On Balance Volume
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args: List[str]
|
||||
Argparse arguments
|
||||
s_ticker: str
|
||||
Ticker
|
||||
s_interval: str
|
||||
Stock data interval
|
||||
df_stock: pd.DataFrame
|
||||
Dataframe of stock prices
|
||||
"""
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
@@ -176,10 +206,19 @@ def obv(l_args, s_ticker, s_interval, df_stock):
|
||||
)
|
||||
|
||||
try:
|
||||
ns_parser = parse_known_args_and_warn(parser, l_args)
|
||||
ns_parser = parse_known_args_and_warn(parser, other_args)
|
||||
if not ns_parser:
|
||||
return
|
||||
|
||||
bar_colors = [
|
||||
"r" if x[1].Open < x[1].Close else "g" for x in df_stock.iterrows()
|
||||
]
|
||||
|
||||
if s_interval == "1440min":
|
||||
bar_width = timedelta(days=1)
|
||||
else:
|
||||
bar_width = timedelta(minutes=int(s_interval.split("m")[0]))
|
||||
|
||||
# Daily
|
||||
if s_interval == "1440min":
|
||||
df_ta = ta.obv(
|
||||
@@ -196,47 +235,58 @@ def obv(l_args, s_ticker, s_interval, df_stock):
|
||||
offset=ns_parser.n_offset,
|
||||
).dropna()
|
||||
|
||||
plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI)
|
||||
axPrice = plt.subplot(211)
|
||||
fig, axes = plt.subplots(
|
||||
3,
|
||||
1,
|
||||
gridspec_kw={"height_ratios": [2, 1, 1]},
|
||||
figsize=plot_autoscale(),
|
||||
dpi=PLOT_DPI,
|
||||
)
|
||||
ax = axes[0]
|
||||
if s_interval == "1440min":
|
||||
plt.plot(df_stock.index, df_stock["Adj Close"].values, "k", lw=2)
|
||||
ax.plot(df_stock.index, df_stock["Adj Close"].values, "k", lw=2)
|
||||
else:
|
||||
plt.plot(df_stock.index, df_stock["Close"].values, "k", lw=2)
|
||||
plt.title(f"On-Balance Volume (OBV) on {s_ticker}")
|
||||
plt.xlim(df_stock.index[0], df_stock.index[-1])
|
||||
plt.ylabel("Share Price ($)")
|
||||
plt.grid(b=True, which="major", color="#666666", linestyle="-")
|
||||
plt.minorticks_on()
|
||||
plt.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
|
||||
_ = axPrice.twinx()
|
||||
ax.plot(df_stock.index, df_stock["Close"].values, "k", lw=2)
|
||||
|
||||
ax.set_title(f"{s_ticker} OBV")
|
||||
ax.set_xlim(df_stock.index[0], df_stock.index[-1])
|
||||
ax.set_ylabel("Share Price ($)")
|
||||
ax.grid(b=True, which="major", color="#666666", linestyle="-")
|
||||
ax.minorticks_on()
|
||||
ax.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
|
||||
ax2 = axes[1]
|
||||
ax2.set_xlim(df_stock.index[0], df_stock.index[-1])
|
||||
|
||||
if s_interval == "1440min":
|
||||
plt.bar(
|
||||
ax2.bar(
|
||||
df_stock.index,
|
||||
df_stock["Volume"].values,
|
||||
color="k",
|
||||
color=bar_colors,
|
||||
alpha=0.8,
|
||||
width=0.3,
|
||||
width=bar_width,
|
||||
)
|
||||
else:
|
||||
plt.bar(
|
||||
ax2.bar(
|
||||
df_stock.index,
|
||||
df_stock["Volume"].values,
|
||||
color="k",
|
||||
color=bar_colors,
|
||||
alpha=0.8,
|
||||
width=0.3,
|
||||
width=bar_width,
|
||||
)
|
||||
plt.subplot(212)
|
||||
plt.plot(df_ta.index, df_ta.values, "b", lw=1)
|
||||
plt.xlim(df_stock.index[0], df_stock.index[-1])
|
||||
plt.legend(["OBV"])
|
||||
plt.xlabel("Time")
|
||||
plt.grid(b=True, which="major", color="#666666", linestyle="-")
|
||||
plt.minorticks_on()
|
||||
plt.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
|
||||
ax3 = axes[2]
|
||||
ax3.plot(df_ta.index, df_ta.values, "b", lw=1)
|
||||
ax3.set_xlim(df_stock.index[0], df_stock.index[-1])
|
||||
ax3.set_xlabel("Time")
|
||||
ax3.grid(b=True, which="major", color="#666666", linestyle="-")
|
||||
ax3.minorticks_on()
|
||||
ax3.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
|
||||
|
||||
if gtff.USE_ION:
|
||||
plt.ion()
|
||||
|
||||
plt.gcf().autofmt_xdate()
|
||||
fig.tight_layout(pad=1)
|
||||
|
||||
plt.show()
|
||||
print("")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user