diff --git a/openbb_terminal/cryptocurrency/crypto_controller.py b/openbb_terminal/cryptocurrency/crypto_controller.py index dec017ab4e8..010a03d5dde 100644 --- a/openbb_terminal/cryptocurrency/crypto_controller.py +++ b/openbb_terminal/cryptocurrency/crypto_controller.py @@ -436,7 +436,7 @@ class CryptoController(CryptoBaseController): self.queue = self.load_class( TechnicalAnalysisController, stock=self.current_df, - coin=self.coin, + coin=self.symbol, start=self.current_df.index[0], interval="", queue=self.queue, diff --git a/openbb_terminal/cryptocurrency/technical_analysis/ta_controller.py b/openbb_terminal/cryptocurrency/technical_analysis/ta_controller.py index d198fb075ed..d3307d2a694 100644 --- a/openbb_terminal/cryptocurrency/technical_analysis/ta_controller.py +++ b/openbb_terminal/cryptocurrency/technical_analysis/ta_controller.py @@ -4,6 +4,7 @@ __docformat__ = "numpy" import argparse import logging +import webbrowser from datetime import datetime from typing import List @@ -14,6 +15,7 @@ from openbb_terminal import feature_flags as obbff from openbb_terminal.common.technical_analysis import ( custom_indicators_view, momentum_view, + overlap_model, overlap_view, trend_indicators_view, volatility_model, @@ -42,6 +44,8 @@ class TechnicalAnalysisController(CryptoBaseController): "load", "ema", "sma", + "wma", + "hma", "vwap", "zlma", "cci", @@ -56,8 +60,10 @@ class TechnicalAnalysisController(CryptoBaseController): "donchian", "kc", "ad", + "adosc", "obv", "fib", + "tv", ] PATH = "/crypto/ta/" @@ -92,10 +98,13 @@ class TechnicalAnalysisController(CryptoBaseController): help_text = f"""[cmds] [param]Coin Loaded: [/param]{crypto_str} + tv open interactive chart on [src][TradingView][/src] + [info]Overlap:[/info] ema exponential moving average sma simple moving average wma weighted moving average + hma hull moving average zlma zero lag moving average vwap volume weighted average price [info]Momentum:[/info] @@ -127,6 +136,24 @@ class TechnicalAnalysisController(CryptoBaseController): return ["crypto", f"load {self.coin}", "ta"] return [] + @log_start_end(log=logger) + def call_tv(self, other_args): + """Process tv command""" + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="tv", + description="""View TradingView for technical analysis. [Source: TradingView]""", + ) + ns_parser = parse_known_args_and_warn(parser, other_args) + if ns_parser: + # temp USDT before we make changes to crypto ta_controller + webbrowser.open( + f"https://www.tradingview.com/chart/?symbol={self.coin}usdt" + ) + console.print("") + + # COMMON # TODO: Go through all models and make sure all needed columns are in dfs @log_start_end(log=logger) @@ -147,17 +174,15 @@ class TechnicalAnalysisController(CryptoBaseController): in the data. """, ) - parser.add_argument( "-l", "--length", action="store", dest="n_length", type=check_positive_list, - default=[20, 50], + default=overlap_model.WINDOW_LENGTHS, help="Window lengths. Multiple values indicated as comma separated values.", ) - parser.add_argument( "-o", "--offset", @@ -178,7 +203,7 @@ class TechnicalAnalysisController(CryptoBaseController): overlap_view.view_ma( ma_type="EMA", s_ticker=self.coin, - series=self.stock["Close"], + series=self.stock["Adj Close"], length=ns_parser.n_length, offset=ns_parser.n_offset, export=ns_parser.export, @@ -201,17 +226,15 @@ class TechnicalAnalysisController(CryptoBaseController): filtering out those changes. """, ) - parser.add_argument( "-l", "--length", action="store", dest="n_length", type=check_positive_list, - default=[20, 50], + default=overlap_model.WINDOW_LENGTHS, help="Window lengths. Multiple values indicated as comma separated values. ", ) - parser.add_argument( "-o", "--offset", @@ -224,6 +247,7 @@ class TechnicalAnalysisController(CryptoBaseController): if other_args and "-" not in other_args[0][0]: other_args.insert(0, "-l") + ns_parser = parse_known_args_and_warn( parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES ) @@ -231,7 +255,105 @@ class TechnicalAnalysisController(CryptoBaseController): overlap_view.view_ma( ma_type="SMA", s_ticker=self.coin, - series=self.stock["Close"], + series=self.stock["Adj Close"], + length=ns_parser.n_length, + offset=ns_parser.n_offset, + export=ns_parser.export, + ) + + @log_start_end(log=logger) + def call_wma(self, other_args: List[str]): + """Process wma command""" + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="wma", + description=""" + A Weighted Moving Average puts more weight on recent data and less on past data. + This is done by multiplying each bar’s price by a weighting factor. Because of its + unique calculation, WMA will follow prices more closely than a corresponding Simple + Moving Average. + """, + ) + parser.add_argument( + "-l", + "--length", + action="store", + dest="n_length", + type=check_positive_list, + default=overlap_model.WINDOW_LENGTHS, + help="Window lengths. Multiple values indicated as comma separated values. ", + ) + parser.add_argument( + "-o", + "--offset", + action="store", + dest="n_offset", + type=int, + default=0, + help="offset", + ) + + if other_args and "-" not in other_args[0][0]: + other_args.insert(0, "-l") + + ns_parser = parse_known_args_and_warn( + parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES + ) + if ns_parser: + overlap_view.view_ma( + ma_type="WMA", + s_ticker=self.coin, + series=self.stock["Adj Close"], + length=ns_parser.n_length, + offset=ns_parser.n_offset, + export=ns_parser.export, + ) + + @log_start_end(log=logger) + def call_hma(self, other_args: List[str]): + """Process hma command""" + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="hma", + description=""" + The Hull Moving Average solves the age old dilemma of making a moving average + more responsive to current price activity whilst maintaining curve smoothness. + In fact the HMA almost eliminates lag altogether and manages to improve smoothing + at the same time. + """, + ) + parser.add_argument( + "-l", + "--length", + action="store", + dest="n_length", + type=check_positive_list, + default=overlap_model.WINDOW_LENGTHS2, + help="Window lengths. Multiple values indicated as comma separated values. ", + ) + parser.add_argument( + "-o", + "--offset", + action="store", + dest="n_offset", + type=int, + default=0, + help="offset", + ) + + if other_args and "-" not in other_args[0][0]: + other_args.insert(0, "-l") + + ns_parser = parse_known_args_and_warn( + parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES + ) + if ns_parser: + overlap_view.view_ma( + ma_type="HMA", + s_ticker=self.coin, + series=self.stock["Adj Close"], length=ns_parser.n_length, offset=ns_parser.n_offset, export=ns_parser.export, @@ -254,7 +376,6 @@ class TechnicalAnalysisController(CryptoBaseController): the moving average. """, ) - parser.add_argument( "-l", "--length", @@ -264,7 +385,6 @@ class TechnicalAnalysisController(CryptoBaseController): default=[20], help="Window lengths. Multiple values indicated as comma separated values.", ) - parser.add_argument( "-o", "--offset", @@ -285,7 +405,7 @@ class TechnicalAnalysisController(CryptoBaseController): overlap_view.view_ma( ma_type="ZLMA", s_ticker=self.coin, - series=self.stock["Close"], + series=self.stock["Adj Close"], length=ns_parser.n_length, offset=ns_parser.n_offset, export=ns_parser.export, @@ -303,7 +423,6 @@ class TechnicalAnalysisController(CryptoBaseController): by volume. It is typically used with intraday charts to identify general direction. """, ) - parser.add_argument( "-o", "--offset", @@ -313,7 +432,6 @@ class TechnicalAnalysisController(CryptoBaseController): default=0, help="offset", ) - parser.add_argument( "--start", dest="start", @@ -668,7 +786,6 @@ class TechnicalAnalysisController(CryptoBaseController): a high number to be a strong trend, and a low number, a weak trend. """, ) - parser.add_argument( "-l", "--length", @@ -678,7 +795,6 @@ class TechnicalAnalysisController(CryptoBaseController): default=14, help="length", ) - parser.add_argument( "-s", "--scalar", @@ -688,7 +804,6 @@ class TechnicalAnalysisController(CryptoBaseController): default=100, help="scalar", ) - parser.add_argument( "-d", "--drift", @@ -699,6 +814,9 @@ class TechnicalAnalysisController(CryptoBaseController): help="drift", ) + if other_args and "-" not in other_args[0][0]: + other_args.insert(0, "-l") + ns_parser = parse_known_args_and_warn( parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES ) @@ -742,7 +860,6 @@ class TechnicalAnalysisController(CryptoBaseController): default=25, help="length", ) - parser.add_argument( "-s", "--scalar", @@ -753,15 +870,8 @@ class TechnicalAnalysisController(CryptoBaseController): help="scalar", ) - parser.add_argument( - "-o", - "--offset", - action="store", - dest="n_offset", - type=check_positive, - default=0, - help="offset", - ) + if other_args and "-" not in other_args[0][0]: + other_args.insert(0, "-l") ns_parser = parse_known_args_and_warn( parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES @@ -802,10 +912,9 @@ class TechnicalAnalysisController(CryptoBaseController): action="store", dest="n_length", type=check_positive, - default=5, + default=15, help="length", ) - parser.add_argument( "-s", "--std", @@ -815,7 +924,6 @@ class TechnicalAnalysisController(CryptoBaseController): default=2, help="std", ) - parser.add_argument( "-m", "--mamode", @@ -825,6 +933,9 @@ class TechnicalAnalysisController(CryptoBaseController): help="mamode", ) + if other_args and "-" not in other_args[0][0]: + other_args.insert(0, "-l") + ns_parser = parse_known_args_and_warn( parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES ) @@ -854,7 +965,6 @@ class TechnicalAnalysisController(CryptoBaseController): between the upper and lower bands represents the Donchian Channel. """, ) - parser.add_argument( "-u", "--length_upper", @@ -864,7 +974,6 @@ class TechnicalAnalysisController(CryptoBaseController): default=20, help="length", ) - parser.add_argument( "-l", "--length_lower", @@ -976,7 +1085,6 @@ class TechnicalAnalysisController(CryptoBaseController): then it signals an impending flattening of the price. """, ) - parser.add_argument( "--open", action="store_true", @@ -996,6 +1104,62 @@ class TechnicalAnalysisController(CryptoBaseController): export=ns_parser.export, ) + @log_start_end(log=logger) + def call_adosc(self, other_args: List[str]): + """Process adosc command""" + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="adosc", + description=""" + Accumulation/Distribution Oscillator, also known as the Chaikin Oscillator + is essentially a momentum indicator, but of the Accumulation-Distribution line + rather than merely price. It looks at both the strength of price moves and the + underlying buying and selling pressure during a given time period. The oscillator + reading above zero indicates net buying pressure, while one below zero registers + net selling pressure. Divergence between the indicator and pure price moves are + the most common signals from the indicator, and often flag market turning points. + """, + ) + parser.add_argument( + "--open", + action="store_true", + default=False, + dest="b_use_open", + help="uses open value of stock", + ) + parser.add_argument( + "-f", + "--fast_length", + action="store", + dest="n_length_fast", + type=check_positive, + default=3, + help="fast length", + ) + parser.add_argument( + "-s", + "--slow_length", + action="store", + dest="n_length_slow", + type=check_positive, + default=10, + help="slow length", + ) + + ns_parser = parse_known_args_and_warn( + parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES + ) + if ns_parser: + volume_view.display_adosc( + s_ticker=self.coin, + ohlc=self.stock, + use_open=ns_parser.b_use_open, + fast=ns_parser.n_length_fast, + slow=ns_parser.n_length_slow, + export=ns_parser.export, + ) + @log_start_end(log=logger) def call_obv(self, other_args: List[str]): """Process obv command""" @@ -1033,7 +1197,6 @@ class TechnicalAnalysisController(CryptoBaseController): prog="fib", description="Calculates the fibonacci retracement levels", ) - parser.add_argument( "-p", "--period", @@ -1042,7 +1205,6 @@ class TechnicalAnalysisController(CryptoBaseController): help="Days to lookback for retracement", default=120, ) - parser.add_argument( "--start", dest="start", @@ -1050,7 +1212,6 @@ class TechnicalAnalysisController(CryptoBaseController): help="Starting date to select", required="--end" in other_args, ) - parser.add_argument( "--end", dest="end", @@ -1059,6 +1220,9 @@ class TechnicalAnalysisController(CryptoBaseController): required="--start" in other_args, ) + if other_args and "-" not in other_args[0][0]: + other_args.insert(0, "-p") + ns_parser = parse_known_args_and_warn( parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES )