Merge branch 'main' into fix-tf-libs-issue, update alpaca api, add notes

# Conflicts:
#	poetry.lock
#	pyproject.toml
This commit is contained in:
Aaron Cutright
2021-03-19 22:12:37 -04:00
17 changed files with 688 additions and 12 deletions

View File

@@ -1,4 +1,7 @@
name: Mac OS X Full Clean Build with ML
env:
GTFF_USE_PROMPT_TOOLKIT: false
GTFF_USE_ION: false
on:
push:
branches:

View File

@@ -1,4 +1,7 @@
name: Tests
env:
GTFF_USE_PROMPT_TOOLKIT: false
GTFF_USE_ION: false
on: [pull_request, push]
jobs:
linting:

View File

@@ -1,4 +1,7 @@
name: Windows 10 Full Clean Build with ML
env:
GTFF_USE_PROMPT_TOOLKIT: false
GTFF_USE_ION: false
on:
push:
branches:

View File

@@ -13,7 +13,12 @@ dnsutils \
git \
gnupg \
unzip \
bzip2 && \
bzip2 \
libsm6 \
libxt6 \
libgl1-mesa-glx \
libpng16-16 \
python3-tk && \
apt-get -y autoremove && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

View File

@@ -131,9 +131,13 @@
## Portfolio Analysis
### Short term
* [ ] Add Brokers (td, alpaca, webull, etc)
* [ ] Merge data from different brokers
* [ ] Refactor
### Long term
* [ ] Summaries / tear sheets
* [ ] Portfolio Optimization
---
## Credit Analysis

View File

@@ -28,3 +28,7 @@ API_TWITTER_BEARER_TOKEN = os.getenv("GT_API_TWITTER_BEARER_TOKEN") or "REPLACE_
# https://fred.stlouisfed.org/docs/api/api_key.html
API_FRED_KEY = os.getenv("GT_FRED_API_KEY") or "REPLACE_ME"
# Robinhood
RH_USERNAME = os.getenv("GT_RH_USERNAME") or "REPLACE_ME"
RH_PASSWORD = os.getenv("GT_RH_PASSWORD") or "REPLACE_ME"

View File

@@ -1,12 +1,13 @@
from distutils.util import strtobool
import os
USE_COLOR = os.getenv("GTFF_USE_COLOR") or True
USE_COLOR = strtobool(os.getenv("GTFF_USE_COLOR", "True"))
USE_FLAIR = os.getenv("GTFF_USE_FLAIR") or "stars"
USE_ION = os.getenv("GTFF_USE_ION") or True
USE_PROMPT_TOOLKIT = os.getenv("GTFF_USE_PROMPT_TOOLKIT") or False
USE_ION = strtobool(os.getenv("GTFF_USE_ION", "True"))
USE_PROMPT_TOOLKIT = strtobool(os.getenv("GTFF_USE_PROMPT_TOOLKIT", "False"))
# Enable Prediction features
ENABLE_PREDICT = os.getenv("GTFF_ENABLE_PREDICT") or False
ENABLE_PREDICT = strtobool(os.getenv("GTFF_ENABLE_PREDICT", "False"))
# Enable plot autoscaling
USE_PLOT_AUTOSCALING = os.getenv("GTFF_USE_PLOT_AUTOSCALING") or False
USE_PLOT_AUTOSCALING = strtobool(os.getenv("GTFF_USE_PLOT_AUTOSCALING", "False"))

View File

@@ -53,6 +53,7 @@ def print_help(s_ticker, s_start, s_interval, b_is_market_open):
print(
" fred economic data, \t\t\t from: Federal Reserve Bank of St. Louis "
)
print(" port portfolio, \t\t\t Currently: Robinhood ")
if s_ticker:
print(

View File

@@ -1,11 +1,25 @@
import os
from matplotlib import pyplot
from prompt_toolkit import PromptSession
from prompt_toolkit.eventloop.inputhook import set_eventloop_with_inputhook
from prompt_toolkit.history import FileHistory
def inputhook(inputhook_context):
while not inputhook_context.input_is_ready():
pyplot.pause(0.1)
return False
history_file = os.path.join(os.path.expanduser("~"), ".gamestonk_terminal.his")
try:
session = PromptSession(history=FileHistory(history_file))
set_eventloop_with_inputhook(inputhook)
except Exception as e: # noqa: F841
print(
"WARNING: Prompt toolkit is turned on but did not initialize successfully. Falling back to input()..."
)
session = None

View File

@@ -0,0 +1,49 @@
# PORTFOLIO
This page shows the available brokers for loading in data. If yours is not listed, please submit a new issue and we will look at adding it.
Once this screen is accessed, the first command to be run is
````
login
````
Which will use your login information, which should be stored as environment variables in [config file](/gamestonk_terminal/config_terminal.py)
Robinhood has Two Factor Authentication, so you will likely be prompted to enter a code that is texted/emailed to you.
###NOTE THAT LOGGING IN WILL SAVE A TOKEN TO `os.path.expanduser("~")/.tokens` WHICH CAN BE USED TO LOGIN EVEN IF USER CREDENTIALS ARE INCORRECT.
[ROBINHOOD](#ROBINHOOD)
* [hold](#hold)
* Look at current (stock only) holdings
* [rhhist](#rhhist)
* Get and plot historical portfolio
## ROBINHOOD <a name="ROBINHOOD"></a>
### hold <a name="hold"></a>
Displays current holdings to the console:
````
usage: hold
````
There are no additional flags. This just prints all current stonks, their last price, previous close, your equity and
the % change from previous close.
Example:
![hold](https://user-images.githubusercontent.com/18151143/111685384-3c6ab080-87fe-11eb-80ce-9b256c396bf2.png)
### rhhist <a name="rhhist"></a>
Display your RH portfolio based on provided interval and span. Based on the API data availablility, plotted as a candlestick chart.
````
usage: rhhist [-s --span] [-i --interval]
````
* -s/--span : How long to look back. Defaults to the day. Options:
* [day, week, month, 3month, year, 5year, all]
* -i/--interval: Data resolution. Defaults to 10minute intervals. Options:
* [5minute, 10minute, hour, day, week]
Example Default Output:
![rhhist](https://user-images.githubusercontent.com/18151143/111718919-36da8e00-8831-11eb-99e1-957c8eccb583.png)

View File

View File

@@ -0,0 +1,100 @@
import argparse
from matplotlib import pyplot as plt
from prompt_toolkit.completion import NestedCompleter
from gamestonk_terminal import feature_flags as gtff
from gamestonk_terminal.helper_funcs import get_flair
from gamestonk_terminal.menu import session
from gamestonk_terminal.portfolio import rh_api
def print_port(show_login):
""" Print help """
print("\nPortfolio:")
print(" help show this menu again")
print(" q quit this menu, and shows back to main menu")
print(" quit quit to abandon program")
print(" ")
print("Robinhood:")
print("")
if show_login:
print(" login login")
print(" hold look at current holdings")
print(" rhhist look at historical portfolio")
print(" ")
def port_menu():
plt.close("all")
port_parser = argparse.ArgumentParser(prog="port", add_help=False)
choices = ["help", "q", "quit", "hold", "rhhist", "login"]
port_parser.add_argument("cmd", choices=choices)
completer = NestedCompleter.from_nested_dict({c: None for c in choices})
should_print_help = True
print_login = True
while True:
if should_print_help:
print_port(print_login)
should_print_help = False
# Get input command from user
if session and gtff.USE_PROMPT_TOOLKIT:
as_input = session.prompt(
f"{get_flair()} (port)> ",
completer=completer,
)
else:
as_input = input(f"{get_flair()} (port)> ")
try:
(ns_known_args, l_args) = port_parser.parse_known_args(as_input.split())
except SystemExit:
print("The command selected doesn't exist\n")
continue
if ns_known_args.cmd == "help":
should_print_help = True
elif ns_known_args.cmd == "q":
# Leave the port menu + logout of robinhood
# logoff raises error if not logged in
try:
rh_api.logoff()
except Exception:
pass
return False
elif ns_known_args.cmd == "quit":
# Will raise exception if not logged in
try:
rh_api.logoff()
except Exception:
pass
# Abandon the program
return True
elif ns_known_args.cmd == "hold":
try:
rh_api.show_holdings()
except Exception as e:
print(e)
print("")
elif ns_known_args.cmd == "rhhist":
rh_api.plot_historical(l_args)
elif ns_known_args.cmd == "login":
try:
rh_api.login()
should_print_help = True
print_login = False
except Exception as e:
print("")
print(e)
print("Make sure credentials are defined in config_terminal.py ")
print("")
should_print_help = False
print_login = True
else:
print("Command not recognized")
print("")

View File

@@ -0,0 +1,164 @@
import argparse
import datetime
from datetime import datetime as dt
import pandas as pd
from pandas.plotting import register_matplotlib_converters
import matplotlib.pyplot as plt
import mplfinance as mpf
import numpy as np
from robin_stocks import robinhood
from termcolor import colored
from gamestonk_terminal.helper_funcs import (
parse_known_args_and_warn,
plot_autoscale,
)
from gamestonk_terminal import feature_flags as gtff
from gamestonk_terminal.config_terminal import RH_USERNAME as user, RH_PASSWORD as pw
register_matplotlib_converters()
dt_format = "%Y-%m-%dT%H:%M:%SZ"
valid_span = ["day", "week", "month", "3month", "year", "5year", "all"]
valid_interval = ["5minute", "10minute", "hour", "day", "week"]
span_title_dict = {
"day": "Day",
"week": "Week",
"month": "Month",
"3month": "3 Months",
"year": "Year",
"5year": "5 Years",
"all": "All Time",
}
def login():
robinhood.login(user, pw)
def logoff():
robinhood.logout()
def show_holdings():
holds = robinhood.account.build_holdings()
stocks = []
equity = []
for stock, data in holds.items():
stocks.append(stock)
equity.append(round(float(data["equity"]), 2))
print("")
print("Stonk\t last price \t prev close \t equity \t % Change")
print("")
for stonk, eq in zip(stocks, equity):
stonk_data = robinhood.stocks.get_quotes(stonk)[0]
prev_close = round(float(stonk_data["adjusted_previous_close"]), 2)
last_price = round(float(stonk_data["last_trade_price"]), 2)
pct_change = round((last_price - prev_close) / prev_close, 3)
to_print = f"{stonk}\t {last_price}\t\t {prev_close}\t\t {eq}\t\t {pct_change}"
if last_price >= prev_close:
print(colored(to_print, "green"))
else:
print(colored(to_print, "red"))
print("")
def plot_historical(l_args):
parser = argparse.ArgumentParser(
add_help=False,
prog="Port",
description="""
Historical Portfolio Info
""",
)
parser.add_argument(
"-s",
"--span",
dest="span",
type=str,
default="day",
help="Span of historical data",
)
parser.add_argument(
"-i",
"--interval",
dest="interval",
default="10minute",
type=str,
help="Interval to look at portfolio",
)
try:
ns_parser = parse_known_args_and_warn(parser, l_args)
if not ns_parser:
return
if ns_parser.interval not in valid_interval:
raise ValueError(
"Invalid Interval: Must be one of: 5minute, 10minute, hour, day, week"
)
if ns_parser.span not in valid_span:
raise ValueError(
"Invalid Span: Must be one of : day, week, month, 3month, year, 5year, all"
)
rhhist = robinhood.account.get_historical_portfolio(
ns_parser.interval, span=ns_parser.span
)
rhhist_eq = rhhist["equity_historicals"]
open_eq = []
close_eq = []
time = []
for h in rhhist_eq:
time.append(
dt.strptime(h["begins_at"], dt_format) - datetime.timedelta(hours=4)
)
close_eq.append(float(h["adjusted_close_equity"]))
open_eq.append(float(h["adjusted_open_equity"]))
close_eq = np.asarray(close_eq)
open_eq = np.asarray(open_eq)
high = np.maximum(open_eq, close_eq)
low = np.minimum(open_eq, close_eq)
df = pd.DataFrame(index=time)
df["High"] = high
df["Low"] = low
df["Open"] = open_eq
df["Close"] = close_eq
mc = mpf.make_marketcolors(
up="green", down="red", edge="black", wick="black", ohlc="i"
)
s = mpf.make_mpf_style(marketcolors=mc, gridstyle=":", y_on_right=False)
mpf.plot(
df,
type="candle",
style=s,
title=f"Portfolio for {span_title_dict[ns_parser.span]}",
ylabel="Equity ($)",
figsize=(plot_autoscale()),
update_width_config=dict(
candle_linewidth=1.0,
candle_width=0.8,
),
)
if gtff.USE_ION:
plt.ion()
print("")
except Exception as e:
print(e)
print("")
return

View File

@@ -0,0 +1,130 @@
""" Fundamental Analysis Market Watch API """
__docformat__ = "numpy"
import re
import random
import requests
from bs4 import BeautifulSoup
from gamestonk_terminal.helper_funcs import get_user_agent
class ThoughtOfTheDay:
""" ThoughtOfTheDay class """
def __init__(self):
""" Constructor """
self.urls = {
"Marcus_Aurelius": "https://www.goodreads.com/author/quotes/17212.Marcus_Aurelius",
"Epictetus": "https://www.goodreads.com/author/quotes/13852.Epictetus",
"Seneca": "https://www.goodreads.com/author/quotes/4918776.Seneca",
"Marcus_Tullius_Cicero": "https://www.goodreads.com/author/quotes/13755.Marcus_Tullius_Cicero",
"Aristotle": "https://www.goodreads.com/author/quotes/2192.Aristotle",
"Plato": "https://www.goodreads.com/author/quotes/879.Plato",
"Pythagoras": "https://www.goodreads.com/author/quotes/203707.Pythagoras",
}
self.metadata = {}
def get_urls(self) -> dict:
""" Getter method for URLs """
return self.urls
def get_metadata(self, author: str) -> dict:
"""Loads metadata for a given author
Parameters
----------
author : str
Author key - Marcus_Aurelius, Epictetus, Seneca, Marcus_Tullius_Cicero, Aristotle, Plato, Pythagoras
Returns
-------
dict
Metadata dictionary that includes number of quotes, number of pages and first 30 quotes
"""
quotes_page = BeautifulSoup(
requests.get(
self.urls[author],
headers={"User-Agent": get_user_agent()},
).text,
"lxml",
)
find_navigation = quotes_page.find("em", {"class": "current"}).find_parent(
"div"
)
page_count = list()
for a_page_ref in find_navigation.find_all("a", href=True):
page_count.append(a_page_ref.text.strip("\n"))
ret = {}
ret["pages"] = page_count[-2]
find_count = quotes_page.find(string=re.compile("Showing 1-30 of"))
quote_count = re.search(r"Showing 1-30 of (?P<number>[\d,]+)", find_count)
if quote_count:
ret["quoutes"] = quote_count.group("number")
all_quotes = quotes_page.find_all("div", {"class": "quote"})
ret["quotes"] = []
for a_quote in all_quotes:
parsed_quote = {}
parsed_quote = a_quote.find("div", {"class": "quoteText"}).text
ret["quotes"].append(parsed_quote)
return ret
def quote_to_str(self, a_quote: str) -> str:
"""Format a quote parsed from Goodreads into a string
Parameters
----------
a_quote : str
A quote formatted by Goodreads
Returns
-------
str
A string version of the quote
"""
ready = []
prev = None
for a_line in a_quote:
if not prev:
ready.append(a_line)
prev = a_line
continue
if a_line != "\n":
ready.append(a_line)
prev = a_line
continue
if prev == " \n":
ready.pop()
prev = None
return "".join(map(str, ready))
def get_thought_of_the_day():
"""Pick a thought of the day"""
totd = ThoughtOfTheDay()
quotes = []
for an_author in totd.get_urls():
metadata = totd.get_metadata(an_author)
quotes = quotes + metadata["quotes"]
print("Thought of the day:")
print(totd.quote_to_str(quotes[random.randint(0, len(quotes) - 1)]))
print("")

172
poetry.lock generated
View File

@@ -29,6 +29,23 @@ yarl = ">=1.0,<2.0"
[package.extras]
speedups = ["aiodns", "brotlipy", "cchardet"]
[[package]]
name = "alpaca-trade-api"
version = "1.1.0"
description = "Alpaca API python client"
category = "main"
optional = false
python-versions = "*"
[package.dependencies]
msgpack = "1.0.2"
numpy = "*"
pandas = "*"
requests = ">2,<3"
urllib3 = ">1.24,<2"
websocket-client = ">=0.56.0,<1"
websockets = ">=8.0,<9"
[[package]]
name = "alpha-vantage"
version = "2.3.1"
@@ -323,6 +340,25 @@ pytz = ">=2014.10"
docs = ["sphinx", "sphinx-rtd-theme"]
test = ["coverage"]
[[package]]
name = "cryptography"
version = "3.4.6"
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
category = "main"
optional = false
python-versions = ">=3.6"
[package.dependencies]
cffi = ">=1.12"
[package.extras]
docs = ["sphinx (>=1.6.5,!=1.8.0,!=3.1.0,!=3.1.1)", "sphinx-rtd-theme"]
docstest = ["doc8", "pyenchant (>=1.6.11)", "twine (>=1.12.0)", "sphinxcontrib-spelling (>=4.0.1)"]
pep8test = ["black", "flake8", "flake8-import-order", "pep8-naming"]
sdist = ["setuptools-rust (>=0.11.4)"]
ssh = ["bcrypt (>=3.1.5)"]
test = ["pytest (>=6.0)", "pytest-cov", "pytest-subtests", "pytest-xdist", "pretend", "iso8601", "pytz", "hypothesis (>=1.11.4,!=3.79.2)"]
[[package]]
name = "cssselect"
version = "1.1.0"
@@ -1182,6 +1218,14 @@ python-versions = "*"
matplotlib = "*"
pandas = "*"
[[package]]
name = "msgpack"
version = "1.0.2"
description = "MessagePack (de)serializer."
category = "main"
optional = false
python-versions = "*"
[[package]]
name = "multidict"
version = "5.1.0"
@@ -1770,6 +1814,14 @@ python-versions = ">=3.6"
[package.dependencies]
pyobjc-core = ">=7.1"
[[package]]
name = "pyotp"
version = "2.6.0"
description = "Python One Time Password Library"
category = "main"
optional = false
python-versions = "*"
[[package]]
name = "pyparsing"
version = "2.4.7"
@@ -1842,6 +1894,17 @@ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
[package.dependencies]
six = ">=1.5"
[[package]]
name = "python-dotenv"
version = "0.15.0"
description = "Add .env support to your django/flask apps in development and deployments"
category = "main"
optional = false
python-versions = "*"
[package.extras]
cli = ["click (>=5.0)"]
[[package]]
name = "pytrends"
version = "4.7.3"
@@ -2007,6 +2070,20 @@ python-versions = "*"
[package.dependencies]
six = ">=1.7.0"
[[package]]
name = "robin-stocks"
version = "2.0.3"
description = "A Python wrapper around the Robinhood API"
category = "main"
optional = false
python-versions = ">=3"
[package.dependencies]
cryptography = "*"
pyotp = "*"
python-dotenv = "*"
requests = "*"
[[package]]
name = "rsa"
version = "4.7.2"
@@ -2280,7 +2357,7 @@ name = "termcolor"
version = "1.1.0"
description = "ANSII Color formatting for output in terminal."
category = "main"
optional = true
optional = false
python-versions = "*"
[[package]]
@@ -2532,6 +2609,14 @@ python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
[package.dependencies]
six = "*"
[[package]]
name = "websockets"
version = "8.1"
description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)"
category = "main"
optional = false
python-versions = ">=3.6.1"
[[package]]
name = "werkzeug"
version = "1.0.1"
@@ -2609,7 +2694,7 @@ prediction = ["fbprophet", "tensorflow", "pmdarima", "transformers", "flair", "t
[metadata]
lock-version = "1.1"
python-versions = "^3.6.8"
content-hash = "8b892e0dc807e52b9f8ece6c5bb60b1e5881e66c72426fe1ffe2faee2930cf87"
content-hash = "6050ce94f3ec0988ef02b85642d7c33af3eb4622130bb303c3d44dbb471be5cb"
[metadata.files]
absl-py = [
@@ -2655,6 +2740,10 @@ aiohttp = [
{file = "aiohttp-3.7.4.post0-cp39-cp39-win_amd64.whl", hash = "sha256:02f46fc0e3c5ac58b80d4d56eb0a7c7d97fcef69ace9326289fb9f1955e65cfe"},
{file = "aiohttp-3.7.4.post0.tar.gz", hash = "sha256:493d3299ebe5f5a7c66b9819eacdcfbbaaf1a8e84911ddffcdc48888497afecf"},
]
alpaca-trade-api = [
{file = "alpaca-trade-api-1.1.0.tar.gz", hash = "sha256:751e06db061cf69aeaf6e21e7cce1baee652cc222a4c00c9f3c2074f7711f757"},
{file = "alpaca_trade_api-1.1.0-py3-none-any.whl", hash = "sha256:098cde3d3ce70a000c643131e6750f372184db79998e91bf9c5ed787a0da3b13"},
]
alpha-vantage = [
{file = "alpha_vantage-2.3.1-py3-none-any.whl", hash = "sha256:5d05355febe6f0fafc4bd11dc6ce3504a02d9d3c105d60202539855c0f608661"},
{file = "alpha_vantage-2.3.1.tar.gz", hash = "sha256:0ce76908c3e2a22f9bbdacead90195ec3a4fa41ef8ae7c69a4a2fc99459bfbec"},
@@ -2809,6 +2898,20 @@ convertdate = [
{file = "convertdate-2.3.2-py3-none-any.whl", hash = "sha256:8f5e9efc2b71410d33217012c0a215f83463f765c94d5883bf656ce7a962b888"},
{file = "convertdate-2.3.2.tar.gz", hash = "sha256:57df962a6047534f1452c390ad48e3dc5c83052ad83ad6dd78d60ae22f99214c"},
]
cryptography = [
{file = "cryptography-3.4.6-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:57ad77d32917bc55299b16d3b996ffa42a1c73c6cfa829b14043c561288d2799"},
{file = "cryptography-3.4.6-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:4169a27b818de4a1860720108b55a2801f32b6ae79e7f99c00d79f2a2822eeb7"},
{file = "cryptography-3.4.6-cp36-abi3-manylinux2010_x86_64.whl", hash = "sha256:93cfe5b7ff006de13e1e89830810ecbd014791b042cbe5eec253be11ac2b28f3"},
{file = "cryptography-3.4.6-cp36-abi3-manylinux2014_aarch64.whl", hash = "sha256:5ecf2bcb34d17415e89b546dbb44e73080f747e504273e4d4987630493cded1b"},
{file = "cryptography-3.4.6-cp36-abi3-manylinux2014_x86_64.whl", hash = "sha256:fec7fb46b10da10d9e1d078d1ff8ed9e05ae14f431fdbd11145edd0550b9a964"},
{file = "cryptography-3.4.6-cp36-abi3-win32.whl", hash = "sha256:df186fcbf86dc1ce56305becb8434e4b6b7504bc724b71ad7a3239e0c9d14ef2"},
{file = "cryptography-3.4.6-cp36-abi3-win_amd64.whl", hash = "sha256:66b57a9ca4b3221d51b237094b0303843b914b7d5afd4349970bb26518e350b0"},
{file = "cryptography-3.4.6-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:066bc53f052dfeda2f2d7c195cf16fb3e5ff13e1b6b7415b468514b40b381a5b"},
{file = "cryptography-3.4.6-pp36-pypy36_pp73-manylinux2014_x86_64.whl", hash = "sha256:600cf9bfe75e96d965509a4c0b2b183f74a4fa6f5331dcb40fb7b77b7c2484df"},
{file = "cryptography-3.4.6-pp37-pypy37_pp73-manylinux2010_x86_64.whl", hash = "sha256:0923ba600d00718d63a3976f23cab19aef10c1765038945628cd9be047ad0336"},
{file = "cryptography-3.4.6-pp37-pypy37_pp73-manylinux2014_x86_64.whl", hash = "sha256:9e98b452132963678e3ac6c73f7010fe53adf72209a32854d55690acac3f6724"},
{file = "cryptography-3.4.6.tar.gz", hash = "sha256:2d32223e5b0ee02943f32b19245b61a62db83a882f0e76cc564e1cec60d48f87"},
]
cssselect = [
{file = "cssselect-1.1.0-py2.py3-none-any.whl", hash = "sha256:f612ee47b749c877ebae5bb77035d8f4202c6ad0f0fc1271b3c18ad6c4468ecf"},
{file = "cssselect-1.1.0.tar.gz", hash = "sha256:f95f8dedd925fd8f54edb3d2dfb44c190d9d18512377d3c1e2388d16126879bc"},
@@ -3376,6 +3479,36 @@ mplfinance = [
{file = "mplfinance-0.12.7a10-py3-none-any.whl", hash = "sha256:aa4d9759a1befadfed190f9fc72ac8389d80fb61bc6f8ce6693d9c2627e88021"},
{file = "mplfinance-0.12.7a10.tar.gz", hash = "sha256:f3745ad29ec834cd5505aa510f401f2c44b44328f92c781d093b3bb597641545"},
]
msgpack = [
{file = "msgpack-1.0.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:b6d9e2dae081aa35c44af9c4298de4ee72991305503442a5c74656d82b581fe9"},
{file = "msgpack-1.0.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:a99b144475230982aee16b3d249170f1cccebf27fb0a08e9f603b69637a62192"},
{file = "msgpack-1.0.2-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:1026dcc10537d27dd2d26c327e552f05ce148977e9d7b9f1718748281b38c841"},
{file = "msgpack-1.0.2-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:fe07bc6735d08e492a327f496b7850e98cb4d112c56df69b0c844dbebcbb47f6"},
{file = "msgpack-1.0.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:9ea52fff0473f9f3000987f313310208c879493491ef3ccf66268eff8d5a0326"},
{file = "msgpack-1.0.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:26a1759f1a88df5f1d0b393eb582ec022326994e311ba9c5818adc5374736439"},
{file = "msgpack-1.0.2-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:497d2c12426adcd27ab83144057a705efb6acc7e85957a51d43cdcf7f258900f"},
{file = "msgpack-1.0.2-cp36-cp36m-win32.whl", hash = "sha256:e89ec55871ed5473a041c0495b7b4e6099f6263438e0bd04ccd8418f92d5d7f2"},
{file = "msgpack-1.0.2-cp36-cp36m-win_amd64.whl", hash = "sha256:a4355d2193106c7aa77c98fc955252a737d8550320ecdb2e9ac701e15e2943bc"},
{file = "msgpack-1.0.2-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:d6c64601af8f3893d17ec233237030e3110f11b8a962cb66720bf70c0141aa54"},
{file = "msgpack-1.0.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:f484cd2dca68502de3704f056fa9b318c94b1539ed17a4c784266df5d6978c87"},
{file = "msgpack-1.0.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:f3e6aaf217ac1c7ce1563cf52a2f4f5d5b1f64e8729d794165db71da57257f0c"},
{file = "msgpack-1.0.2-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:8521e5be9e3b93d4d5e07cb80b7e32353264d143c1f072309e1863174c6aadb1"},
{file = "msgpack-1.0.2-cp37-cp37m-win32.whl", hash = "sha256:31c17bbf2ae5e29e48d794c693b7ca7a0c73bd4280976d408c53df421e838d2a"},
{file = "msgpack-1.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:8ffb24a3b7518e843cd83538cf859e026d24ec41ac5721c18ed0c55101f9775b"},
{file = "msgpack-1.0.2-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:b28c0876cce1466d7c2195d7658cf50e4730667196e2f1355c4209444717ee06"},
{file = "msgpack-1.0.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:87869ba567fe371c4555d2e11e4948778ab6b59d6cc9d8460d543e4cfbbddd1c"},
{file = "msgpack-1.0.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:b55f7db883530b74c857e50e149126b91bb75d35c08b28db12dcb0346f15e46e"},
{file = "msgpack-1.0.2-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:ac25f3e0513f6673e8b405c3a80500eb7be1cf8f57584be524c4fa78fe8e0c83"},
{file = "msgpack-1.0.2-cp38-cp38-win32.whl", hash = "sha256:0cb94ee48675a45d3b86e61d13c1e6f1696f0183f0715544976356ff86f741d9"},
{file = "msgpack-1.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:e36a812ef4705a291cdb4a2fd352f013134f26c6ff63477f20235138d1d21009"},
{file = "msgpack-1.0.2-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:2a5866bdc88d77f6e1370f82f2371c9bc6fc92fe898fa2dec0c5d4f5435a2694"},
{file = "msgpack-1.0.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:92be4b12de4806d3c36810b0fe2aeedd8d493db39e2eb90742b9c09299eb5759"},
{file = "msgpack-1.0.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:de6bd7990a2c2dabe926b7e62a92886ccbf809425c347ae7de277067f97c2887"},
{file = "msgpack-1.0.2-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:5a9ee2540c78659a1dd0b110f73773533ee3108d4e1219b5a15a8d635b7aca0e"},
{file = "msgpack-1.0.2-cp39-cp39-win32.whl", hash = "sha256:c747c0cc08bd6d72a586310bda6ea72eeb28e7505990f342552315b229a19b33"},
{file = "msgpack-1.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:d8167b84af26654c1124857d71650404336f4eb5cc06900667a493fc619ddd9f"},
{file = "msgpack-1.0.2.tar.gz", hash = "sha256:fae04496f5bc150eefad4e9571d1a76c55d021325dcd484ce45065ebbdd00984"},
]
multidict = [
{file = "multidict-5.1.0-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:b7993704f1a4b204e71debe6095150d43b2ee6150fa4f44d6d966ec356a8d61f"},
{file = "multidict-5.1.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:9dd6e9b1a913d096ac95d0399bd737e00f2af1e1594a787e00f7975778c8b2bf"},
@@ -3733,6 +3866,10 @@ pyobjc-framework-cocoa = [
{file = "pyobjc_framework_Cocoa-7.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3f68f022f1f6d5985c418e10c6608c562fcf4bfe3714ec64fd10ce3dc6221bd4"},
{file = "pyobjc_framework_Cocoa-7.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ecfefd4c48dae42275c18679c69f6f2fff970e711097515a0a8732fc10194018"},
]
pyotp = [
{file = "pyotp-2.6.0-py2.py3-none-any.whl", hash = "sha256:9d144de0f8a601d6869abe1409f4a3f75f097c37b50a36a3bf165810a6e23f28"},
{file = "pyotp-2.6.0.tar.gz", hash = "sha256:d28ddfd40e0c1b6a6b9da961c7d47a10261fb58f378cb00f05ce88b26df9c432"},
]
pyparsing = [
{file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"},
{file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"},
@@ -3775,6 +3912,10 @@ python-dateutil = [
{file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"},
{file = "python_dateutil-2.8.1-py2.py3-none-any.whl", hash = "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"},
]
python-dotenv = [
{file = "python-dotenv-0.15.0.tar.gz", hash = "sha256:587825ed60b1711daea4832cf37524dfd404325b7db5e25ebe88c495c9f807a0"},
{file = "python_dotenv-0.15.0-py2.py3-none-any.whl", hash = "sha256:0c8d1b80d1a1e91717ea7d526178e3882732420b03f08afea0406db6402e220e"},
]
pytrends = [
{file = "pytrends-4.7.3-py3-none-any.whl", hash = "sha256:88d92e398b9408c79fd92946ddc2b03fa622301233bc49f16804042eb2897328"},
{file = "pytrends-4.7.3.tar.gz", hash = "sha256:8ccb06c57c31fa157b978a0d810de7718ee46583d28cf818250d45f36abd2faa"},
@@ -4002,6 +4143,9 @@ requests-oauthlib = [
retrying = [
{file = "retrying-1.3.3.tar.gz", hash = "sha256:08c039560a6da2fe4f2c426d0766e284d3b736e355f8dd24b37367b0bb41973b"},
]
robin-stocks = [
{file = "robin_stocks-2.0.3.tar.gz", hash = "sha256:c7300a7721748a1776bc9160c6dc6aea1801b8397e3900609378dc40d884e943"},
]
rsa = [
{file = "rsa-4.7.2-py3-none-any.whl", hash = "sha256:78f9a9bf4e7be0c5ded4583326e7461e3a3c5aae24073648b4bdfa797d78c9d2"},
{file = "rsa-4.7.2.tar.gz", hash = "sha256:9d689e6ca1b3038bc82bf8d23e944b6b6037bc02301a574935b2dd946e0353b9"},
@@ -4348,6 +4492,30 @@ websocket-client = [
{file = "websocket_client-0.58.0-py2.py3-none-any.whl", hash = "sha256:44b5df8f08c74c3d82d28100fdc81f4536809ce98a17f0757557813275fbb663"},
{file = "websocket_client-0.58.0.tar.gz", hash = "sha256:63509b41d158ae5b7f67eb4ad20fecbb4eee99434e73e140354dc3ff8e09716f"},
]
websockets = [
{file = "websockets-8.1-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:3762791ab8b38948f0c4d281c8b2ddfa99b7e510e46bd8dfa942a5fff621068c"},
{file = "websockets-8.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:3db87421956f1b0779a7564915875ba774295cc86e81bc671631379371af1170"},
{file = "websockets-8.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4f9f7d28ce1d8f1295717c2c25b732c2bc0645db3215cf757551c392177d7cb8"},
{file = "websockets-8.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:295359a2cc78736737dd88c343cd0747546b2174b5e1adc223824bcaf3e164cb"},
{file = "websockets-8.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:1d3f1bf059d04a4e0eb4985a887d49195e15ebabc42364f4eb564b1d065793f5"},
{file = "websockets-8.1-cp36-cp36m-win32.whl", hash = "sha256:2db62a9142e88535038a6bcfea70ef9447696ea77891aebb730a333a51ed559a"},
{file = "websockets-8.1-cp36-cp36m-win_amd64.whl", hash = "sha256:0e4fb4de42701340bd2353bb2eee45314651caa6ccee80dbd5f5d5978888fed5"},
{file = "websockets-8.1-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:9b248ba3dd8a03b1a10b19efe7d4f7fa41d158fdaa95e2cf65af5a7b95a4f989"},
{file = "websockets-8.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:ce85b06a10fc65e6143518b96d3dca27b081a740bae261c2fb20375801a9d56d"},
{file = "websockets-8.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:965889d9f0e2a75edd81a07592d0ced54daa5b0785f57dc429c378edbcffe779"},
{file = "websockets-8.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:751a556205d8245ff94aeef23546a1113b1dd4f6e4d102ded66c39b99c2ce6c8"},
{file = "websockets-8.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:3ef56fcc7b1ff90de46ccd5a687bbd13a3180132268c4254fc0fa44ecf4fc422"},
{file = "websockets-8.1-cp37-cp37m-win32.whl", hash = "sha256:7ff46d441db78241f4c6c27b3868c9ae71473fe03341340d2dfdbe8d79310acc"},
{file = "websockets-8.1-cp37-cp37m-win_amd64.whl", hash = "sha256:20891f0dddade307ffddf593c733a3fdb6b83e6f9eef85908113e628fa5a8308"},
{file = "websockets-8.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c1ec8db4fac31850286b7cd3b9c0e1b944204668b8eb721674916d4e28744092"},
{file = "websockets-8.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:5c01fd846263a75bc8a2b9542606927cfad57e7282965d96b93c387622487485"},
{file = "websockets-8.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:9bef37ee224e104a413f0780e29adb3e514a5b698aabe0d969a6ba426b8435d1"},
{file = "websockets-8.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:d705f8aeecdf3262379644e4b55107a3b55860eb812b673b28d0fbc347a60c55"},
{file = "websockets-8.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:c8a116feafdb1f84607cb3b14aa1418424ae71fee131642fc568d21423b51824"},
{file = "websockets-8.1-cp38-cp38-win32.whl", hash = "sha256:e898a0863421650f0bebac8ba40840fc02258ef4714cb7e1fd76b6a6354bda36"},
{file = "websockets-8.1-cp38-cp38-win_amd64.whl", hash = "sha256:f8a7bff6e8664afc4e6c28b983845c5bc14965030e3fb98789734d416af77c4b"},
{file = "websockets-8.1.tar.gz", hash = "sha256:5c65d2da8c6bce0fca2528f69f44b2f977e06954c8512a952222cea50dad430f"},
]
werkzeug = [
{file = "Werkzeug-1.0.1-py2.py3-none-any.whl", hash = "sha256:2de2a5db0baeae7b2d2664949077c2ac63fbd16d98da0ff71837f7d1dea3fd43"},
{file = "Werkzeug-1.0.1.tar.gz", hash = "sha256:6c80b1e5ad3665290ea39320b91e1be1e0d5f60652b964a3070216de83d2e47c"},

View File

@@ -1,3 +1,4 @@
# https://python-poetry.org/docs/dependency-specification/
[tool.poetry]
name = "GamestonkTerminal"
version = "0.1.0"
@@ -6,7 +7,7 @@ authors = ["Didier Rodrigues Lopes"]
[tool.poetry.dependencies]
python = "^3.6.8"
pandas = "^1.1.5"
pandas = "^1.1.5,<1.2"
iso8601 = "^0.1.14"
FundamentalAnalysis = "^0.2.6"
requests = "^2.25.1"
@@ -37,13 +38,16 @@ prompt-toolkit = "^3.0.16"
jupyter = "^1.0.0"
mplfinance = "^0.12.7-alpha.7"
seaborn = "^0.11.0"
scipy = "1.5.4"
scipy = "~1.5.4"
fredapi = "^0.4.3"
screeninfo = "^0.6.7"
numpy = "~1.19.5"
numpy = "~1.19.5,<1.20"
pyrsistent = "~0.14.11"
regex = "~2020.11.13"
h5py = "~2.10.0"
robin-stocks = "^2.0.3"
termcolor = "^1.1.0"
alpaca-trade-api = "^1.0.1"
[tool.poetry.dev-dependencies]
pytest = "^6.2.2"
@@ -57,3 +61,13 @@ prediction = ["fbprophet", "tensorflow", "pmdarima", "transformers", "flair", "t
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
# Notes for developers:
# 1. numpy >= 1.20.0 sometimes has issues with tensorflow=2.4.1
# 2. The following packages dropped support for python<3.7:
# pandas >= 1.2.0
# numpy >= 1.20.0
# scipy >= 1.6.0
# 3. The following often cause poetry to misbehave:
# pyrsistent >= 0.17
# regex >= 2021

View File

@@ -11,6 +11,7 @@ from prompt_toolkit.completion import NestedCompleter
from gamestonk_terminal import config_terminal as cfg
from gamestonk_terminal import feature_flags as gtff
from gamestonk_terminal import thought_of_the_day as thought
from gamestonk_terminal import res_menu as rm
from gamestonk_terminal.discovery import disc_menu as dm
from gamestonk_terminal.due_diligence import dd_menu as ddm
@@ -24,6 +25,7 @@ from gamestonk_terminal.technical_analysis import ta_menu as tam
from gamestonk_terminal.comparison_analysis import ca_menu as cam
from gamestonk_terminal.options import op_menu as opm
from gamestonk_terminal.fred import fred_menu as fm
from gamestonk_terminal.portfolio import port_menu
# import warnings
# warnings.simplefilter("always")
@@ -75,6 +77,7 @@ def main():
"ca",
"op",
"fred",
"port",
]
menu_parser.add_argument("opt", choices=choices)
completer = NestedCompleter.from_nested_dict({c: None for c in choices})
@@ -84,6 +87,13 @@ def main():
should_print_help = True
parsed_stdin = False
print("-------------------")
try:
thought.get_thought_of_the_day()
except Exception as e:
print(e)
print("")
# Loop forever and ever
while True:
main_cmd = False
@@ -193,6 +203,9 @@ def main():
elif ns_known_args.opt == "fred":
b_quit = fm.fred_menu()
elif ns_known_args.opt == "port":
b_quit = port_menu.port_menu()
elif ns_known_args.opt == "pred":
if not gtff.ENABLE_PREDICT: