mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-10-27 12:40:35 +00:00
Backlog updates: candle and api keys (#556)
* Edit `candle` to have argparse and add a terminal option to view defined api keys * Change the terminal `keys` functions print location and some documentation * Docstring formatting * Docstring formatting 2 * Add testing for non broker keys
This commit is contained in:
4
gamestonk_terminal/README.md
vendored
4
gamestonk_terminal/README.md
vendored
@@ -65,10 +65,10 @@ quote -t S_TICKER
|
||||
* Show the current price of a stock.
|
||||
|
||||
```
|
||||
candle
|
||||
candle -s START_DATE
|
||||
```
|
||||
|
||||
* Visualize candles historical data from the past 6 months, with support and resistance bars, and moving averages of 20 and 50
|
||||
* Visualize candles historical data, with support and resistance bars, and moving averages of 20 and 50.
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -48,8 +48,8 @@ DG_PASSWORD = os.getenv("GT_DG_PASSWORD") or "REPLACE_ME"
|
||||
DG_TOTP_SECRET = os.getenv("GT_DG_TOTP_SECRET") or None
|
||||
|
||||
# https://developer.oanda.com
|
||||
OANDA_ACCOUNT = os.getenv("GT_OANDA_ACCOUNT") or "REPLACE ME"
|
||||
OANDA_TOKEN = os.getenv("GT_OANDA_TOKEN") or "REPLACE ME"
|
||||
OANDA_ACCOUNT = os.getenv("GT_OANDA_ACCOUNT") or "REPLACE_ME"
|
||||
OANDA_TOKEN = os.getenv("GT_OANDA_TOKEN") or "REPLACE_ME"
|
||||
|
||||
# https://tradier.com/products/market-data-api
|
||||
TRADIER_TOKEN = os.getenv("GT_API_TRADIER_TOKEN") or "REPLACE_ME"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"""Helper functions"""
|
||||
__docformat__ = "numpy"
|
||||
import argparse
|
||||
from typing import List
|
||||
from datetime import datetime, timedelta, time as Time
|
||||
import os
|
||||
import random
|
||||
@@ -27,6 +28,23 @@ if cfgPlot.BACKEND is not None:
|
||||
|
||||
|
||||
def check_valid_path(path: str) -> str:
|
||||
"""Argparse type function to test is path is valid
|
||||
|
||||
Parameters
|
||||
----------
|
||||
path: str
|
||||
Path supplied
|
||||
|
||||
Returns
|
||||
-------
|
||||
path: str
|
||||
Valid path
|
||||
|
||||
Raises
|
||||
-------
|
||||
argparse.ArgumentTypeError
|
||||
Given path does not exist
|
||||
"""
|
||||
if not os.path.exists(
|
||||
os.path.abspath(
|
||||
os.path.join(
|
||||
@@ -38,14 +56,41 @@ def check_valid_path(path: str) -> str:
|
||||
return path
|
||||
|
||||
|
||||
def check_int_range(mini, maxi):
|
||||
"""
|
||||
Checks if argparse argument is an int between 2 values.
|
||||
https://stackoverflow.com/questions/55324449/how-to-specify-a-minimum-or-maximum-float-value-with-argparse
|
||||
def check_int_range(mini: int, maxi: int):
|
||||
"""Checks if argparse argument is an int between 2 values.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
mini: int
|
||||
Min value to compare
|
||||
maxi: int
|
||||
Max value to compare
|
||||
|
||||
Returns
|
||||
-------
|
||||
int_range_checker:
|
||||
Function that compares the three integers
|
||||
"""
|
||||
|
||||
# Define the function with default arguments
|
||||
def int_range_checker(num) -> int:
|
||||
def int_range_checker(num: int) -> int:
|
||||
"""Checks if int is between a high and low value
|
||||
|
||||
Parameters
|
||||
----------
|
||||
num: int
|
||||
Input integer
|
||||
|
||||
Returns
|
||||
-------
|
||||
num: int
|
||||
Input number if conditions are met
|
||||
|
||||
Raises
|
||||
-------
|
||||
argparse.ArgumentTypeError
|
||||
Input number not between min and max values
|
||||
"""
|
||||
num = int(num)
|
||||
if num < mini or num > maxi:
|
||||
raise argparse.ArgumentTypeError(f"must be in range [{mini},{maxi}]")
|
||||
@@ -437,7 +482,21 @@ def patch_pandas_text_adjustment():
|
||||
pandas.io.formats.format.TextAdjustment.adjoin = text_adjustment_adjoin
|
||||
|
||||
|
||||
def parse_known_args_and_warn(parser, l_args):
|
||||
def parse_known_args_and_warn(parser: argparse.ArgumentParser, other_args: List[str]):
|
||||
"""Parses list of arguments into the supplied parser
|
||||
|
||||
Parameters
|
||||
----------
|
||||
parser: argparse.ArgumentParser
|
||||
Parser with predefined arguments
|
||||
other_args: List[str]
|
||||
List of arguments to parse
|
||||
|
||||
Returns
|
||||
-------
|
||||
ns_parser:
|
||||
Namespace with parsed arguments
|
||||
"""
|
||||
parser.add_argument(
|
||||
"-h", "--help", action="store_true", help="show this help message"
|
||||
)
|
||||
@@ -445,7 +504,7 @@ def parse_known_args_and_warn(parser, l_args):
|
||||
if gtff.USE_CLEAR_AFTER_CMD:
|
||||
os.system("cls||clear")
|
||||
|
||||
(ns_parser, l_unknown_args) = parser.parse_known_args(l_args)
|
||||
(ns_parser, l_unknown_args) = parser.parse_known_args(other_args)
|
||||
|
||||
if ns_parser.help:
|
||||
parser.print_help()
|
||||
|
||||
@@ -8,15 +8,19 @@ import subprocess
|
||||
import random
|
||||
from datetime import datetime, timedelta
|
||||
import hashlib
|
||||
import requests
|
||||
from colorama import Fore, Style
|
||||
import matplotlib.pyplot as plt
|
||||
from numpy.core.fromnumeric import transpose
|
||||
import pandas as pd
|
||||
from alpha_vantage.timeseries import TimeSeries
|
||||
import quandl
|
||||
import mplfinance as mpf
|
||||
import yfinance as yf
|
||||
from coinmarketcapapi import CoinMarketCapAPI, CoinMarketCapAPIError
|
||||
import pytz
|
||||
import pyEX
|
||||
from pyEX.common.exception import PyEXception
|
||||
from tabulate import tabulate
|
||||
|
||||
# import git
|
||||
@@ -408,49 +412,85 @@ def load(other_args: List[str], s_ticker, s_start, s_interval, df_stock):
|
||||
return [s_ticker, s_start, s_interval, df_stock]
|
||||
|
||||
|
||||
def candle(s_ticker: str, s_start: str):
|
||||
df_stock = trend.load_ticker(s_ticker, s_start)
|
||||
df_stock = trend.find_trendline(df_stock, "OC_High", "high")
|
||||
df_stock = trend.find_trendline(df_stock, "OC_Low", "low")
|
||||
def candle(s_ticker: str, other_args: List[str]):
|
||||
"""Shows candle plot of loaded ticker
|
||||
|
||||
mc = mpf.make_marketcolors(
|
||||
up="green", down="red", edge="black", wick="black", volume="in", ohlc="i"
|
||||
Parameters
|
||||
----------
|
||||
s_ticker: str
|
||||
Ticker to display
|
||||
other_args: str
|
||||
Argparse arguments
|
||||
"""
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
prog="candle",
|
||||
description="Displays candle chart of loaded ticker",
|
||||
)
|
||||
|
||||
s = mpf.make_mpf_style(marketcolors=mc, gridstyle=":", y_on_right=True)
|
||||
|
||||
ap0 = []
|
||||
|
||||
if "OC_High_trend" in df_stock.columns:
|
||||
ap0.append(
|
||||
mpf.make_addplot(df_stock["OC_High_trend"], color="g"),
|
||||
)
|
||||
|
||||
if "OC_Low_trend" in df_stock.columns:
|
||||
ap0.append(
|
||||
mpf.make_addplot(df_stock["OC_Low_trend"], color="b"),
|
||||
)
|
||||
|
||||
if gtff.USE_ION:
|
||||
plt.ion()
|
||||
|
||||
mpf.plot(
|
||||
df_stock,
|
||||
type="candle",
|
||||
mav=(20, 50),
|
||||
volume=True,
|
||||
title=f"\n{s_ticker} - Last 6 months",
|
||||
addplot=ap0,
|
||||
xrotation=10,
|
||||
style=s,
|
||||
figratio=(10, 7),
|
||||
figscale=1.10,
|
||||
figsize=(plot_autoscale()),
|
||||
update_width_config=dict(
|
||||
candle_linewidth=1.0, candle_width=0.8, volume_linewidth=1.0
|
||||
),
|
||||
parser.add_argument(
|
||||
"-s",
|
||||
"--start_date",
|
||||
dest="s_start",
|
||||
type=valid_date,
|
||||
default=(datetime.now() - timedelta(days=180)).strftime("%Y-%m-%d"),
|
||||
help="Start date for candle data",
|
||||
)
|
||||
print("")
|
||||
|
||||
try:
|
||||
ns_parser = parse_known_args_and_warn(parser, other_args)
|
||||
if not ns_parser:
|
||||
return
|
||||
if not s_ticker:
|
||||
print("No ticker loaded. First use `load {ticker}`", "\n")
|
||||
return
|
||||
|
||||
df_stock = trend.load_ticker(s_ticker, ns_parser.s_start)
|
||||
df_stock = trend.find_trendline(df_stock, "OC_High", "high")
|
||||
df_stock = trend.find_trendline(df_stock, "OC_Low", "low")
|
||||
|
||||
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)
|
||||
|
||||
ap0 = []
|
||||
|
||||
if "OC_High_trend" in df_stock.columns:
|
||||
ap0.append(
|
||||
mpf.make_addplot(df_stock["OC_High_trend"], color="g"),
|
||||
)
|
||||
|
||||
if "OC_Low_trend" in df_stock.columns:
|
||||
ap0.append(
|
||||
mpf.make_addplot(df_stock["OC_Low_trend"], color="b"),
|
||||
)
|
||||
|
||||
if gtff.USE_ION:
|
||||
plt.ion()
|
||||
|
||||
mpf.plot(
|
||||
df_stock,
|
||||
type="candle",
|
||||
mav=(20, 50),
|
||||
volume=True,
|
||||
title=f"\n{s_ticker} - Starting {ns_parser.s_start.strftime('%Y-%m-%d')}",
|
||||
addplot=ap0,
|
||||
xrotation=10,
|
||||
style=s,
|
||||
figratio=(10, 7),
|
||||
figscale=1.10,
|
||||
figsize=(plot_autoscale()),
|
||||
update_width_config=dict(
|
||||
candle_linewidth=1.0, candle_width=0.8, volume_linewidth=1.0
|
||||
),
|
||||
)
|
||||
print("")
|
||||
|
||||
except Exception as e:
|
||||
print(e, "\n")
|
||||
|
||||
|
||||
def quote(other_args: List[str], s_ticker: str):
|
||||
@@ -601,7 +641,219 @@ def view(other_args: List[str], s_ticker: str, s_interval, df_stock):
|
||||
return
|
||||
|
||||
|
||||
# pylint: disable=too-many-statements
|
||||
|
||||
|
||||
def check_api_keys():
|
||||
"""Check api keys and if they are supplied"""
|
||||
|
||||
key_dict = {}
|
||||
if cfg.API_KEY_ALPHAVANTAGE == "REPLACE_ME": # pragma: allowlist secret
|
||||
key_dict["ALPHA_VANTAGE"] = "Not defined"
|
||||
else:
|
||||
df = TimeSeries(
|
||||
key=cfg.API_KEY.ALPHAVANTAGE, output_format="pandas"
|
||||
).get_intraday(symbol="AAPL")
|
||||
if df.empty:
|
||||
key_dict["ALPHA_VANTAGE"] = "defined, test failed"
|
||||
else:
|
||||
key_dict["ALPHA_VANTAGE"] = "defined, test passed"
|
||||
|
||||
if cfg.API_KEY_FINANCIALMODELINGPREP == "REPLACE_ME":
|
||||
key_dict["FINANCIAL_MODELING_PREP"] = "Not defined"
|
||||
else:
|
||||
r = requests.get(
|
||||
f"https://financialmodelingprep.com/api/v3/profile/AAPL?apikey={cfg.API_KEY_FINANCIALMODELINGPREP}"
|
||||
)
|
||||
if r.status_code in [403, 401]:
|
||||
key_dict["FINANCIAL_MODELING_PREP"] = "defined, test failed"
|
||||
elif r.status_code == 200:
|
||||
key_dict["FINANCIAL_MODELING_PREP"] = "defined, test passed"
|
||||
else:
|
||||
key_dict["FINANCIAL_MODELING_PREP"] = "defined, test inconclusive"
|
||||
|
||||
if cfg.API_KEY_QUANDL == "REPLACE_ME":
|
||||
key_dict["QUANDL"] = "Not defined"
|
||||
else:
|
||||
try:
|
||||
quandl.save_key(cfg.API_KEY_QUANDL)
|
||||
quandl.get_table(
|
||||
"ZACKS/FC",
|
||||
paginate=True,
|
||||
ticker=["AAPL", "MSFT"],
|
||||
per_end_date={"gte": "2015-01-01"},
|
||||
qopts={"columns": ["ticker", "per_end_date"]},
|
||||
)
|
||||
key_dict["QUANDL"] = "defined, test passed"
|
||||
except quandl.errors.quandl_error.ForbiddenError:
|
||||
key_dict["QUANDL"] = "defined, test failed"
|
||||
|
||||
if cfg.API_POLYGON_KEY == "REPLACE_ME":
|
||||
key_dict["POLYGON"] = "Not defined"
|
||||
else:
|
||||
r = requests.get(
|
||||
f"https://api.polygon.io/v2/aggs/ticker/AAPL/range/1/day/2020-06-01/2020-06-17?apiKey={cfg.API_POLYGON_KEY}"
|
||||
)
|
||||
if r.status_code in [403, 401]:
|
||||
key_dict["POLYGON"] = "defined, test failed"
|
||||
elif r.status_code == 200:
|
||||
key_dict["POLYGON"] = "defined, test passed"
|
||||
else:
|
||||
key_dict["POLYGON"] = "defined, test inconclusive"
|
||||
|
||||
if cfg.API_FRED_KEY == "REPLACE_ME":
|
||||
key_dict["FRED"] = "Not defined"
|
||||
else:
|
||||
r = requests.get(
|
||||
f"https://api.stlouisfed.org/fred/series?series_id=GNPCA&api_key={cfg.API_FRED_KEY}"
|
||||
)
|
||||
if r.status_code in [403, 401, 400]:
|
||||
key_dict["FRED"] = "defined, test failed"
|
||||
elif r.status_code == 200:
|
||||
key_dict["FRED"] = "defined, test passed"
|
||||
else:
|
||||
key_dict["FRED"] = "defined, test inconclusive"
|
||||
|
||||
if cfg.API_NEWS_TOKEN == "REPLACE_ME":
|
||||
key_dict["NEWSAPI"] = "Not defined"
|
||||
else:
|
||||
r = requests.get(
|
||||
f"https://newsapi.org/v2/everything?q=keyword&apiKey={cfg.API_NEWS_TOKEN}"
|
||||
)
|
||||
if r.status_code in [401, 403]:
|
||||
key_dict["NEWSAPI"] = "defined, test failed"
|
||||
elif r.status_code == 200:
|
||||
key_dict["NEWSAPI"] = "defined, test passed"
|
||||
else:
|
||||
key_dict["NEWSAPI"] = "defined, test inconclusive"
|
||||
|
||||
if cfg.TRADIER_TOKEN == "REPLACE_ME":
|
||||
key_dict["TRADIER"] = "Not defined"
|
||||
else:
|
||||
r = requests.get(
|
||||
"https://sandbox.tradier.com/v1/markets/quotes",
|
||||
params={"symbols": "AAPL"},
|
||||
headers={
|
||||
"Authorization": f"Bearer {cfg.TRADIER_TOKEN}",
|
||||
"Accept": "application/json",
|
||||
},
|
||||
)
|
||||
if r.status_code in [401, 403]:
|
||||
key_dict["TRADIER"] = "defined, test failed"
|
||||
elif r.status_code == 200:
|
||||
key_dict["TRADIER"] = "defined, test passed"
|
||||
else:
|
||||
key_dict["TRADIER"] = "defined, test inconclusive"
|
||||
|
||||
if cfg.API_CMC_KEY == "REPLACE_ME":
|
||||
key_dict["COINMARKETCAP"] = "Not defined"
|
||||
else:
|
||||
cmc = CoinMarketCapAPI(cfg.API_CMC_KEY)
|
||||
try:
|
||||
cmc.exchange_info()
|
||||
key_dict["COINMARKETCAP"] = "defined, test passed"
|
||||
except CoinMarketCapAPIError:
|
||||
key_dict["COINMARKETCAP"] = "defined, test failed"
|
||||
|
||||
if cfg.API_FINNHUB_KEY == "REPLACE_ME":
|
||||
key_dict["FINNHUB"] = "Not defined"
|
||||
else:
|
||||
r = r = requests.get(
|
||||
f"https://finnhub.io/api/v1/quote?symbol=AAPL&token={cfg.API_FINNHUB_KEY}"
|
||||
)
|
||||
if r.status_code in [403, 401, 400]:
|
||||
key_dict["FINNHUB"] = "defined, test failed"
|
||||
elif r.status_code == 200:
|
||||
key_dict["FINNHUB"] = "defined, test passed"
|
||||
else:
|
||||
key_dict["FINNHUB"] = "defined, test inconclusive"
|
||||
|
||||
if cfg.API_IEX_TOKEN == "REPLACE_ME":
|
||||
key_dict["IEXCLOUD"] = "Not defined"
|
||||
else:
|
||||
try:
|
||||
pyEX.Client(api_token=cfg.API_IEX_TOKEN, version="v1")
|
||||
key_dict["IEXCLOUD"] = "defined, test passed"
|
||||
except PyEXception:
|
||||
key_dict["IEXCLOUD"] = "defined, test failed"
|
||||
|
||||
# Reddit
|
||||
reddit_keys = [
|
||||
cfg.API_REDDIT_CLIENT_ID,
|
||||
cfg.API_REDDIT_CLIENT_SECRET,
|
||||
cfg.API_REDDIT_USERNAME,
|
||||
cfg.API_REDDIT_PASSWORD,
|
||||
cfg.API_REDDIT_USER_AGENT,
|
||||
]
|
||||
if "REPLACE_ME" in reddit_keys:
|
||||
key_dict["REDDIT"] = "Not defined"
|
||||
else:
|
||||
key_dict["REDDIT"] = "defined, not tested"
|
||||
|
||||
# Reddit keys
|
||||
twitter_keys = [
|
||||
cfg.API_TWITTER_KEY,
|
||||
cfg.API_TWITTER_SECRET_KEY,
|
||||
cfg.API_TWITTER_BEARER_TOKEN,
|
||||
]
|
||||
if "REPLACE_ME" in twitter_keys:
|
||||
key_dict["TWITTER"] = "Not defined"
|
||||
else:
|
||||
params = {
|
||||
"query": "(\\$AAPL) (lang:en)",
|
||||
"max_results": "10",
|
||||
"tweet.fields": "created_at,lang",
|
||||
}
|
||||
r = requests.get(
|
||||
"https://api.twitter.com/2/tweets/search/recent",
|
||||
params=params, # type: ignore
|
||||
headers={"authorization": "Bearer " + cfg.API_TWITTER_BEARER_TOKEN},
|
||||
)
|
||||
if r.status_code == 200:
|
||||
key_dict["TWITTER"] = "defined, test passed"
|
||||
elif r.status_code in [401, 403]:
|
||||
key_dict["TWITTER"] = "defined, test failed"
|
||||
else:
|
||||
key_dict["TWITTER"] = "defined, test inconclusive"
|
||||
|
||||
# Robinhood keys
|
||||
rh_keys = [cfg.RH_USERNAME, cfg.RH_PASSWORD]
|
||||
if "REPLACE_ME" in rh_keys:
|
||||
key_dict["ROBINHOOD"] = "Not defined"
|
||||
else:
|
||||
key_dict["ROBINHOOD"] = "defined, not tested"
|
||||
# Degiro keys
|
||||
dg_keys = [cfg.DG_USERNAME, cfg.DG_PASSWORD, cfg.DG_TOTP_SECRET]
|
||||
if "REPLACE_ME" in dg_keys:
|
||||
key_dict["DEGIRO"] = "Not defined"
|
||||
else:
|
||||
key_dict["DEGIRO"] = "defined, not tested"
|
||||
# OANDA keys
|
||||
oanda_keys = [cfg.OANDA_TOKEN, cfg.OANDA_ACCOUNT]
|
||||
if "REPLACE_ME" in oanda_keys:
|
||||
key_dict["OANDA"] = "Not defined"
|
||||
else:
|
||||
key_dict["OANDA"] = "defined, not tested"
|
||||
# Binance keys
|
||||
bn_keys = [cfg.API_BINANCE_KEY, cfg.API_BINANCE_SECRET]
|
||||
if "REPLACE_ME" in bn_keys:
|
||||
key_dict["BINANCE"] = "Not defined"
|
||||
else:
|
||||
key_dict["BINANCE"] = "defined, not tested"
|
||||
|
||||
print(
|
||||
tabulate(
|
||||
pd.DataFrame(key_dict.items()),
|
||||
showindex=False,
|
||||
headers=[],
|
||||
tablefmt="fancy_grid",
|
||||
),
|
||||
"\n",
|
||||
)
|
||||
|
||||
|
||||
def print_goodbye():
|
||||
"""Prints a goodbye message when quitting the terminal"""
|
||||
goodbye_msg = [
|
||||
"An informed ape, is a strong ape. ",
|
||||
"Remember that stonks only go up. ",
|
||||
@@ -641,6 +893,7 @@ def sha256sum(filename):
|
||||
|
||||
|
||||
def update_terminal():
|
||||
"""Updates the terminal by running git pull in the directory. Runs poetry install if needed"""
|
||||
poetry_hash = sha256sum("poetry.lock")
|
||||
|
||||
completed_process = subprocess.run("git pull", shell=True, check=False)
|
||||
@@ -664,6 +917,7 @@ def update_terminal():
|
||||
|
||||
|
||||
def about_us():
|
||||
"""Prints an about us section"""
|
||||
print(
|
||||
f"\n{Fore.GREEN}Thanks for using Gamestonk Terminal. This is our way!{Style.RESET_ALL}\n"
|
||||
"\n"
|
||||
@@ -728,6 +982,7 @@ def bootup():
|
||||
|
||||
|
||||
def reset():
|
||||
"""Resets the terminal. Allows for checking code or keys without quitting"""
|
||||
print("resetting...")
|
||||
plt.close("all")
|
||||
completed_process = subprocess.run("python terminal.py", shell=True, check=False)
|
||||
|
||||
19
terminal.py
19
terminal.py
@@ -5,14 +5,17 @@ __docformat__ = "numpy"
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime
|
||||
from typing import List
|
||||
import pandas as pd
|
||||
import yfinance as yf
|
||||
from alpha_vantage.timeseries import TimeSeries
|
||||
from prompt_toolkit.completion import NestedCompleter
|
||||
|
||||
from gamestonk_terminal.helper_funcs import b_is_stock_market_open, get_flair
|
||||
from gamestonk_terminal.helper_funcs import (
|
||||
b_is_stock_market_open,
|
||||
get_flair,
|
||||
)
|
||||
from gamestonk_terminal.main_helper import (
|
||||
clear,
|
||||
load,
|
||||
@@ -24,6 +27,7 @@ from gamestonk_terminal.main_helper import (
|
||||
about_us,
|
||||
bootup,
|
||||
reset,
|
||||
check_api_keys,
|
||||
)
|
||||
from gamestonk_terminal.menu import session
|
||||
from gamestonk_terminal import config_terminal as cfg
|
||||
@@ -103,6 +107,7 @@ class TerminalController:
|
||||
"about",
|
||||
"bro",
|
||||
"ins",
|
||||
"keys",
|
||||
]
|
||||
CHOICES += CHOICES_TICKER_DEPENDENT
|
||||
|
||||
@@ -136,6 +141,7 @@ What do you want to do?
|
||||
cls clear screen
|
||||
?/help show this menu again
|
||||
update update terminal from remote
|
||||
keys check for defined api keys
|
||||
reset reset terminal and reload configs
|
||||
about about us
|
||||
q(uit) to abandon the program
|
||||
@@ -189,6 +195,7 @@ Contexts:
|
||||
help_text += """\n> disc discover trending stocks, \t e.g. map, sectors, high short interest
|
||||
> scr screener stocks, \t\t e.g. overview/performance, using preset filters
|
||||
"""
|
||||
|
||||
print(help_text)
|
||||
|
||||
def switch(self, an_input: str):
|
||||
@@ -265,11 +272,11 @@ Contexts:
|
||||
other_args, self.ticker + "." + self.suffix if self.suffix else self.ticker
|
||||
)
|
||||
|
||||
def call_candle(self, _):
|
||||
def call_candle(self, other_args: List[str]):
|
||||
"""Process candle command"""
|
||||
candle(
|
||||
self.ticker + "." + self.suffix if self.suffix else self.ticker,
|
||||
(datetime.now() - timedelta(days=180)).strftime("%Y-%m-%d"),
|
||||
other_args,
|
||||
)
|
||||
|
||||
def call_view(self, other_args: List[str]):
|
||||
@@ -333,6 +340,10 @@ Contexts:
|
||||
self.update_succcess = not update_terminal()
|
||||
return True
|
||||
|
||||
def call_keys(self, _):
|
||||
"""Process keys command"""
|
||||
check_api_keys()
|
||||
|
||||
def call_about(self, _):
|
||||
"""Process about command"""
|
||||
about_us()
|
||||
|
||||
Reference in New Issue
Block a user