Merge pull request #360 from alokan/main

Forex support through Oanda
This commit is contained in:
DidierRLopes
2021-04-21 23:36:10 +01:00
committed by GitHub
12 changed files with 1147 additions and 78 deletions

View File

@@ -258,13 +258,11 @@ These are the ones where a key is necessary:
* FRED: https://fred.stlouisfed.org/docs/api/api_key.html
* News API: https://newsapi.org
* Tradier: https://developer.tradier.com/getting_started
* Oanda API: https://developer.oanda.com
When these are obtained, don't forget to update [config_terminal.py](/gamestonk_terminal/config_terminal.py).
Alternatively, you can also set them to the following environment variables: GT_API_KEY_ALPHAVANTAGE,
GT_API_KEY_FINANCIALMODELINGPREP, GT_API_KEY_QUANDL, GT_API_REDDIT_CLIENT_ID, GT_API_REDDIT_CLIENT_SECRET, GT_API_REDDIT_USERNAME,
GT_API_REDDIT_USER_AGENT, GT_API_REDDIT_PASSWORD, GT_API_TWITTER_KEY, GT_API_TWITTER_SECRET_KEY,
GT_API_TWITTER_BEARER_TOKEN, GT_API_POLYGON_KEY, GT_FRED_API_KEY, GT_API_NEWS_TOKEN, GT_TRADIER_TOKEN .
Alternatively, you can also set them to the following environment variables: GT_API_KEY_ALPHAVANTAGE, GT_API_KEY_FINANCIALMODELINGPREP, GT_API_KEY_QUANDL, GT_API_REDDIT_CLIENT_ID, GT_API_REDDIT_CLIENT_SECRET, GT_API_REDDIT_USERNAME, GT_API_REDDIT_USER_AGENT, GT_API_REDDIT_PASSWORD, GT_API_TWITTER_KEY, GT_API_TWITTER_SECRET_KEY, GT_API_TWITTER_BEARER_TOKEN, GT_API_POLYGON_KEY, GT_FRED_API_KEY, GT_API_NEWS_TOKEN, GT_OANDA_TOKEN, GT_OANDA_ACCOUNT, GT_TRADIER_TOKEN.
Example:
```

View File

@@ -39,6 +39,10 @@ API_NEWS_TOKEN = os.getenv("GT_API_NEWS_TOKEN") or "REPLACE_ME"
RH_USERNAME = os.getenv("GT_RH_USERNAME") or "REPLACE_ME"
RH_PASSWORD = os.getenv("GT_RH_PASSWORD") or "REPLACE_ME"
# https://developer.oanda.com
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_TRADIER_TOKEN") or "REPLACE_ME"

View File

@@ -0,0 +1,146 @@
# Forex
This menu utilizes oanda to enable support for trading forex.
* [summary](#summary)
* Display a summary of your account
* [calendar](#calendar)
* Get information about past or upcoming events which may impact the price
* [list](#list)
* List your order history
* [pending](#pending)
* Get information about pending orders
* [cancel](#cancel)
* Cancel a pending order by ID
* [positions](#positions)
* Get information about your positions
* [trades](#trades)
* See a list of open trades
* [closetrade](#closetrade)
* Close a trade by ID
* [load](#load)
* Specify an instrument to use
* [candles](#candles)
* Get a candlestick chart for the forex instrument
* [price](#price)
* Show the current price for the forex instrument
* [order](#order)
* Place a limit order
* [orderbook](#orderbook)
* Display the orderbook if Oanda provides one for the forex instrument
* [positionbook](#positionbook)
* Display the positionbook if Oanda provides one for the forex instrument
## summary <a name ="summary"></a>
```text
usage: summary
```
Displays current balance, net asset value, unrealized P/L, total P/L, count of open trades, how much margin is available, how much margin you've used, the margin call value, the percent of margin until closeout, and the total position value.
## calendar <a name="calendar"></a>
```text
usage: calendar [-d DAYS]
```
Display information about past or upcoming events up to 30 days before or from todays date. The information includes the Title of the event, the time the event is scheduled, the rated impact, Oanda's forecast, the market forecast, the currency involved, the region from which the event originates, the actual value (for events that have finished), and the previous value.
* -d : The number of days to search (7 is the default, 30 is the maximum that information is provided for). Use a positive value to search for upcoming events and a negative value to search for past events.
## list <a name="list"></a>
```text
usage: list [-s STATE] [-c COUNT]
```
Retrieves a list of orders you've made. It includes the ID, the instrument, the number of units, the price, the state of the order, and the type of order.
* -s : The state of the orders to filter. You can specify: pending, filled, triggered, canceled or all. (default=all)
* -c : The number of orders to retrieve. (default = 20)
## pending <a name="pending"></a>
```text
usage: pending
```
A shortcut to list the pending orders for your account. It includes the ID, the instrument, the price, the number of units, the time the order was created and the time in force.
## cancel <a name="cancel"></a>
```text
usage: cancel [-i ORDERID]
```
Cancel a pending order by its order ID.
* -i : Specify the order ID. You don't need to include this, simply include the order number.
## positions <a name="positions"></a>
```text
usage: positions
```
Lists your open positions. The information includes the instrument, the current number of long units, the total profit/loss from long positions for the account, the unrealized profit/loss from long positions, the current number of short units, the total profit/loss from short positions for the account, and the unrealized profit/loss from short positions.
## trades <a name="trades"></a>
```text
usage: trades
```
Lists the current open trades for your account. The information includes the ID, the instrument, the initial units opened for the trade, the current number of units open for the trade, it's entry price, and the unrealized profit/loss for the trade.
## closetrade <a name="closetrade"></a>
```text
usage: closetrade [-i ORDERID] [-u UNITS]
```
Closes a trade by ID. Displays the order ID closed, the instrument, the number of units that were closed, the price, and the profit/loss
* -i : Specify the order ID. You don't need to include this, simply include the order number.
* -u : Specify the number of units to close for that trade. (default=all)
## load <a name="load"></a>
```text
usage: load [-i INSTRUMENT]
```
Specify the instrument to use in the format EUR_USD
* -i : Specify the instrument. You don't need to include this, simply include the instrument.
## candles <a name="candles"></a>
```text
usage: candles [-g GRANULARITY] [-c CANDLECOUNT]
```
Retrieve a candlestick chart for the currently loaded instrument. Not a live chart.
* -g : Specify the granularity, which is the timeframe each candle represents. The available granularities are Seconds: S5, S10, S15, S30 Minutes: M1, M2, M4, M5, M10, M15, M30 Hours: H1, H2, H3, H4, H6, H8, H12 Day: D, Week: W Month: M. (default=D)
* -c : Specify the number of candles to retrieve. (default=180)
## price <a name="price"></a>
```text
usage: price
```
Gets the current price for the currently loaded instrument
## order <a name="order"></a>
```text
usage: order -u UNITS -p PRICE
```
Places a limit order for the specified number of units at the specified price. Both arguments are required.
* -u : Specify the number of units for the order.
* -p : Specify the price for the limit order.
## orderbook <a name="orderbook"></a>
```text
usage: orderbook
```
Plots the current orderbook for loaded instrument if one is provided by Oanda. Not a live chart.
## positionbook <a name="positionbook"></a>
```text
usage: positionbook
```
Plots the current positionbook for the loaded instrument if one is provided by Oanda. Not a live chart.

View File

View File

@@ -0,0 +1,181 @@
import argparse
from typing import List
from prompt_toolkit.completion import NestedCompleter
from gamestonk_terminal.helper_funcs import get_flair
from gamestonk_terminal import feature_flags as gtff
from gamestonk_terminal.menu import session
from gamestonk_terminal.forex import fx_view
from gamestonk_terminal import config_terminal as cfg
account = cfg.OANDA_ACCOUNT
class ForexController:
"""Oanda Controller class"""
CHOICES = [
"help",
"q",
"quit",
"price",
"summary",
"list",
"orderbook",
"positionbook",
"order",
"load",
"cancel",
"positions",
"closetrade",
"trades",
"candles",
"pending",
"calendar",
]
def __init__(self):
"""Construct Data"""
self.fx_parser = argparse.ArgumentParser(add_help=False, prog="fx")
self.fx_parser.add_argument(
"cmd",
choices=self.CHOICES,
)
self.instrument = None
@staticmethod
def print_help(self):
"""Print help"""
print("\nForex Mode:")
print(" help show this menu again")
print(" q quit this menu and goes back to main menu")
print(" quit quit to abandon program")
print("")
print(" summary shows account summary")
print(" calendar show calendar")
print(" list list order history")
print(" pending get information on pending orders")
print(" cancel cancel a pending order by ID -i order ID")
print(" positions get open positions")
print(" trades list open trades")
print(" closetrade close a trade by id")
print("")
print(f"Loaded instrument: {self.instrument if self.instrument else ''}")
print("")
print(" load load an instrument to use")
if self.instrument:
print(" candles show candles")
print(" price shows price for selected instrument")
print(" order place limit order -u # of units -p price")
print(" orderbook print orderbook")
print(" positionbook print positionbook")
print("")
def switch(self, an_input: str):
"""Process and dispatch input
Returns
______
True, False, or None
False - quit the menu
True - quit the program
None - continue in the menu
"""
(known_args, other_args) = self.fx_parser.parse_known_args(an_input.split())
return getattr(
self, "call_" + known_args.cmd, lambda: "command not recognized!"
)(other_args)
def call_help(self, _):
"""Process Help Command"""
self.print_help(self)
def call_q(self, _):
"""Process Q command - quit the menu"""
return False
def call_quit(self, _):
"""Process Quit command - exit the program"""
return True
def call_price(self, other_args):
"""Process Price Command"""
fx_view.get_fx_price(account, self.instrument, other_args)
def call_load(self, other_args):
self.instrument = fx_view.load(other_args)
def call_summary(self, other_args):
"""Process account summary command"""
fx_view.get_account_summary(account, other_args)
def call_orderbook(self, other_args):
"""Process Oanda Order Book"""
fx_view.get_order_book(self.instrument, other_args)
def call_positionbook(self, other_args):
"""Process Oanda Position Book"""
fx_view.get_position_book(self.instrument, other_args)
def call_list(self, other_args: List[str]):
"""Process list orders command"""
fx_view.list_orders(account, other_args)
def call_order(self, other_args: List[str]):
"""Place limit order"""
fx_view.create_order(account, self.instrument, other_args)
def call_cancel(self, other_args: List[str]):
"""Cancel pending order by ID"""
fx_view.cancel_pending_order(account, other_args)
def call_positions(self, other_args):
"""Get Open Positions"""
fx_view.get_open_positions(account, other_args)
def call_pending(self, other_args):
"""See up to 25 pending orders"""
fx_view.get_pending_orders(account, other_args)
def call_closetrade(self, other_args: List[str]):
"""Close a trade by id"""
fx_view.close_trade(account, other_args)
def call_candles(self, other_args: List[str]):
fx_view.show_candles(account, self.instrument, other_args)
def call_trades(self, other_args):
"""List open trades"""
fx_view.get_open_trades(account, other_args)
def call_calendar(self, other_args: List[str]):
"""Call calendar"""
fx_view.calendar(self.instrument, other_args)
def menu():
"""Oanda Menu"""
fx_controller = ForexController()
fx_controller.call_help(None)
while True:
if session and gtff.USE_PROMPT_TOOLKIT:
completer = NestedCompleter.from_nested_dict(
{c: None for c in fx_controller.CHOICES}
)
an_input = session.prompt(
f"{get_flair()} (fx)> ",
completer=completer,
)
else:
an_input = input(f"{get_flair()} (fx)> ")
try:
process_input = fx_controller.switch(an_input)
if process_input is not None:
return process_input
except SystemExit:
print("The command selected doesn't exit\n")
continue

View File

@@ -0,0 +1,748 @@
import argparse
from oandapyV20 import API
from typing import List
import oandapyV20.endpoints.pricing as pricing
import oandapyV20.endpoints.accounts as accounts
import oandapyV20.endpoints.orders as orders
import oandapyV20.endpoints.instruments as instruments
import oandapyV20.endpoints.positions as positions
import oandapyV20.endpoints.trades as trades
import oandapyV20.endpoints.forexlabs as labs
from oandapyV20.exceptions import V20Error
from gamestonk_terminal import config_terminal as cfg
from gamestonk_terminal import config_plot as cfgPlot
from gamestonk_terminal import feature_flags as gtff
from gamestonk_terminal.helper_funcs import parse_known_args_and_warn, plot_autoscale
import pandas as pd
import mplfinance as mpf
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
import seaborn as sns
from datetime import datetime
client = API(access_token=cfg.OANDA_TOKEN, environment="live")
account = cfg.OANDA_ACCOUNT
def get_fx_price(accountID, instrument, other_args: List[str]):
parser = argparse.ArgumentParser(
add_help=False,
prog="price",
description="Get price for selected instrument.",
)
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
try:
parameters = {"instruments": instrument}
request = pricing.PricingInfo(accountID=accountID, params=parameters)
response = client.request(request)
bid = response["prices"][0]["bids"][0]["price"]
ask = response["prices"][0]["asks"][0]["price"]
print(instrument + " Bid: " + bid)
print(instrument + " Ask: " + ask)
print("")
except V20Error as e:
d_error = eval(e.msg)
print(d_error["errorMessage"], "\n")
def get_account_summary(accountID, other_args: List[str]):
parser = argparse.ArgumentParser(
add_help=False,
prog="summary",
description="Print some information about your account.",
)
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
try:
request = accounts.AccountSummary(accountID=accountID)
response = client.request(request)
df_summary = pd.DataFrame(
[
{"Type": "Balance", "Value": response["account"]["balance"]},
{"Type": "NAV", "Value": response["account"]["NAV"]},
{
"Type": "Unrealized P/L",
"Value": response["account"]["unrealizedPL"],
},
{"Type": "Total P/L", "Value": response["account"]["pl"]},
{
"Type": "Open Trade Count",
"Value": response["account"]["openTradeCount"],
},
{
"Type": "Margin Available",
"Value": response["account"]["marginAvailable"],
},
{"Type": "Margin Used", "Value": response["account"]["marginUsed"]},
{
"Type": "Margin Closeout",
"Value": response["account"]["marginCloseoutNAV"],
},
{
"Type": "Margin Closeout Percent",
"Value": response["account"]["marginCloseoutPercent"],
},
{
"Type": "Margin Closeout Position Value",
"Value": response["account"]["marginCloseoutPositionValue"],
},
]
)
print(df_summary.to_string(index=False, header=False))
print("")
except V20Error as e:
d_error = eval(e.msg)
print(d_error["errorMessage"], "\n")
def list_orders(accountID, other_args: List[str]):
parser = argparse.ArgumentParser(
add_help=False,
prog="list",
description="List order history",
)
parser.add_argument(
"-s",
"--state",
dest="state",
action="store",
default="ALL",
required=False,
help="Select state for order list. ",
)
parser.add_argument(
"-c",
"--count",
dest="count",
action="store",
default=20,
required=False,
help="the number of orders to retrieve ",
)
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
parameters = {}
parameters["state"] = ns_parser.state.upper()
parameters["count"] = ns_parser.count
try:
request = orders.OrderList(accountID, parameters)
response = client.request(request)
df = pd.DataFrame.from_dict(response["orders"])
df = df[["id", "instrument", "units", "price", "state", "type"]]
print(df)
print("")
except KeyError:
print("No orders were found\n")
except V20Error as e:
d_error = eval(e.msg)
print(d_error["errorMessage"], "\n")
def get_order_book(instrument, other_args):
parser = argparse.ArgumentParser(
add_help=False,
prog="orderbook",
description="Plot the orderbook for the instrument if Oanda provides one.",
)
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
parameters = {"bucketWidth": "1"}
try:
instrument = format_instrument(instrument, "_")
request = instruments.InstrumentsOrderBook(
instrument=instrument, params=parameters
)
response = client.request(request)
df = pd.DataFrame.from_dict(response["orderBook"]["buckets"])
pd.set_option("display.max_rows", None)
df = df.take(range(527, 727, 1))
book_plot(df, instrument, "Order Book")
print("")
except V20Error as e:
d_error = eval(e.msg)
print(d_error["errorMessage"], "\n")
def get_position_book(instrument, other_args):
parser = argparse.ArgumentParser(
add_help=False,
prog="positionbook",
description="Plot the positionbook for the instrument if Oanda provides one.",
)
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
try:
instrument = format_instrument(instrument, "_")
request = instruments.InstrumentsPositionBook(instrument=instrument)
response = client.request(request)
df = pd.DataFrame.from_dict(response["positionBook"]["buckets"])
pd.set_option("display.max_rows", None)
df = df.take(range(219, 415, 1))
book_plot(df, instrument, "Position Book")
print("")
except V20Error as e:
d_error = eval(e.msg)
print(d_error["errorMessage"], "\n")
def create_order(accountID, instrument, other_args: List[str]):
parser = argparse.ArgumentParser(
add_help=False,
prog="order",
description="Create order",
)
parser.add_argument(
"-u",
"--unit",
dest="units",
action="store",
type=int,
default=0,
required=True,
help="The number of units to place in the order request. Positive for "
+ "a long position and negative for a short position ",
)
parser.add_argument(
"-p",
"--price",
dest="price",
action="store",
type=float,
required=True,
help="The price to set for the limit order. ",
)
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
data = {
"order": {
"price": ns_parser.price,
"instrument": instrument,
"units": ns_parser.units,
"type": "LIMIT",
"timeInForce": "GTC",
"positionFill": "DEFAULT",
}
}
try:
request = orders.OrderCreate(accountID, data)
response = client.request(request)
if "orderFillTransaction" in response["orderCreateTransaction"]:
order_id = response["orderCreateTransaction"]["orderFillTransaction"]["id"]
order_instrument = response["orderCreateTransaction"][
"orderFillTransaction"
]["instrument"]
units = response["orderCreateTransaction"]["orderFillTransaction"]["units"]
price = response["orderCreateTransaction"]["orderFillTransaction"]["price"]
print("Order Filled:")
print(f"ID: {order_id}")
print(f"Instrument: {order_instrument}")
print(f"Units: {units}")
print(f"Price: {price}")
print("")
else:
order_creation_id = response["orderCreateTransaction"]["id"]
order_instrument = response["orderCreateTransaction"]["instrument"]
units = response["orderCreateTransaction"]["units"]
price = response["orderCreateTransaction"]["price"]
print("Order created:")
print(f"ID: {order_creation_id}")
print(f"Instrument: {order_instrument}")
print(f"Units: {units}")
print(f"Price: {price}")
print("")
except Exception as e:
print(e)
except V20Error as e:
d_error = eval(e.msg)
print(d_error["message"], "\n")
def cancel_pending_order(accountID, other_args: List[str]):
parser = argparse.ArgumentParser(
add_help=False,
prog="cancel",
description="Cancel Pending Order ",
)
parser.add_argument(
"-i",
"--id",
dest="orderID",
action="store",
type=str,
help="The pending order ID to cancel ",
)
if other_args:
if "-" not in other_args[0]:
other_args.insert(0, "-i")
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
try:
request = orders.OrderCancel(accountID, ns_parser.orderID)
response = client.request(request)
order_id = response["orderCancelTransaction"]["orderID"]
print(f"Order {order_id} canceled.")
print("")
except V20Error as e:
d_error = eval(e.msg)
print(d_error["errorMessage"], "\n")
def get_pending_orders(accountID, other_args):
parser = argparse.ArgumentParser(
add_help=False,
prog="pending",
description="Gets information about pending orders.",
)
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
try:
request = orders.OrdersPending(accountID)
response = client.request(request)
for i in range(len(response["orders"])):
order_id = response["orders"][i]["id"]
instrument = response["orders"][i]["instrument"]
price = response["orders"][i]["price"]
units = response["orders"][i]["units"]
create_time = response["orders"][i]["createTime"]
time_in_force = response["orders"][i]["timeInForce"]
print(f"Order ID: {order_id}")
print(f"Instrument: {instrument}")
print(f"Price: {price}")
print(f"Units: {units}")
print(f"Time created: {create_time}")
print(f"Time in force: {time_in_force}")
print("-" * 30)
print("")
except V20Error as e:
d_error = eval(e.msg)
print(d_error["errorMessage"], "\n")
def get_open_positions(accountID, other_args):
parser = argparse.ArgumentParser(
add_help=False,
prog="positions",
description="Gets information about open positions.",
)
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
try:
request = positions.OpenPositions(accountID)
response = client.request(request)
for i in range(len(response["positions"])):
instrument = response["positions"][i]["instrument"]
long_units = response["positions"][i]["long"]["units"]
long_pl = response["positions"][i]["long"]["pl"]
long_upl = response["positions"][i]["long"]["unrealizedPL"]
short_units = response["positions"][i]["short"]["units"]
short_pl = response["positions"][i]["short"]["pl"]
short_upl = response["positions"][i]["short"]["unrealizedPL"]
print(f"Instrument: {instrument}\n")
print(f"Long Units: {long_units}")
print(f"Total Long P/L: {long_pl}")
print(f"Long Unrealized P/L: {long_upl}\n")
print(f"Short Units: {short_units}")
print(f"Total Short P/L: {short_pl}")
print(f"Short Unrealized P/L: {short_upl}")
print("-" * 30 + "\n")
print("")
except V20Error as e:
d_error = eval(e.msg)
print(d_error["errorMessage"], "\n")
def get_open_trades(accountID, other_args):
parser = argparse.ArgumentParser(
add_help=False,
prog="trades",
description="Gets information about open trades.",
)
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
try:
request = trades.OpenTrades(accountID)
response = client.request(request)
try:
df = pd.DataFrame.from_dict(response["trades"])
df = df[
[
"id",
"instrument",
"initialUnits",
"currentUnits",
"price",
"unrealizedPL",
]
]
df = df.rename(
columns={
"id": "ID",
"instrument": "Instrument",
"initialUnits": "Initial Units",
"currentUnits": "Current Units",
"price": "Entry Price",
"unrealizedPL": "Unrealized P/L",
}
)
print(df)
print("")
except KeyError:
print("No trades were found")
print("")
except V20Error as e:
msg_length = len(e.msg)
msg = e.msg[17 : msg_length - 2]
print(msg)
print("")
def close_trade(accountID, other_args: List[str]):
parser = argparse.ArgumentParser(
add_help=False,
prog="closetrade",
description="Close a trade by id.",
)
parser.add_argument(
"-i",
"--id",
dest="orderID",
action="store",
type=str,
required=False,
help="The Trade ID to close. ",
)
parser.add_argument(
"-u",
"--units",
dest="units",
action="store",
required=False,
help="The number of units on the trade to close. If not set it "
+ "defaults to all units. ",
)
if other_args:
if "-i" not in other_args[0]:
other_args.insert(0, "-i")
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
data = {}
if ns_parser.units is not None:
data["units"] = ns_parser.units
try:
request = trades.TradeClose(accountID, ns_parser.orderID, data)
response = client.request(request)
order_id = response["orderCreateTransaction"]["tradeClose"]["tradeID"]
order_instrument = response["orderFillTransaction"]["instrument"]
units = response["orderCreateTransaction"]["units"]
price = response["orderFillTransaction"]["price"]
pl = response["orderFillTransaction"]["pl"]
print("Order closed:")
print(f"ID: {order_id}")
print(f"Instrument: {order_instrument}")
print(f"Units: {units}")
print(f"Price: {price}")
print(f"P/L: {pl}")
print("")
except Exception as e:
print(e, "\n")
except V20Error as e:
d_error = eval(e.msg)
print(d_error["errorMessage"], "\n")
def show_candles(accountID, instrument, other_args: List[str]):
parser = argparse.ArgumentParser(
add_help=False,
prog="candles",
description="Display Candle Data",
)
parser.add_argument(
"-g",
"--granularity",
dest="granularity",
action="store",
type=str,
default="D",
required=False,
help="The timeframe to get for the candle chart (Seconds: S5, S10, S15, S30 "
+ "Minutes: M1, M2, M4, M5, M10, M15, M30 Hours: H1, H2, H3, H4, H6, H8, H12 "
+ "Day (default): D, Week: W Month: M",
)
parser.add_argument(
"-c",
"--count",
dest="candlecount",
action="store",
default=180,
type=int,
required=False,
help="The number of candles to retrieve. Default:180 ",
)
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
parameters = {}
parameters["granularity"] = ns_parser.granularity
parameters["count"] = ns_parser.candlecount
try:
instrument = format_instrument(instrument, "_")
request = instruments.InstrumentsCandles(instrument, params=parameters)
response = client.request(request)
process_candle_response(response)
oanda_fix_date(".temp_candles.csv")
df = pd.read_csv(".candles.csv", index_col=0)
df.index = pd.to_datetime(df.index)
df.columns = ["Open", "High", "Low", "Close", "Volume"]
if gtff.USE_ION:
plt.ion()
mpf.plot(
df,
type="candle",
style="charles",
volume=True,
title=f"{instrument} {ns_parser.granularity}",
)
print("")
except V20Error as e:
d_error = eval(e.msg)
print(d_error["errorMessage"], "\n")
def process_candle_response(response):
with open(".temp_candles.csv", "w") as out:
for i in range(len(response["candles"])):
time = response["candles"][i]["time"]
volume = response["candles"][i]["volume"]
o = response["candles"][i]["mid"]["o"]
h = response["candles"][i]["mid"]["h"]
low = response["candles"][i]["mid"]["l"]
c = response["candles"][i]["mid"]["c"]
out.write(
str(time)
+ ","
+ str(o)
+ ","
+ str(h)
+ ","
+ str(low)
+ ","
+ str(c)
+ ","
+ str(volume)
+ "\n"
)
def oanda_fix_date(file):
with open(file) as candle_file:
lines = candle_file.readlines()
with open(".candles.csv", "w") as out:
out.write("Datetime, Open, High, Low, Close, Volume\n")
for line in lines:
with open(".candles.csv", "a") as output:
output.write(line[:10] + " " + line[11:19] + line[30:])
def calendar(instrument, other_args: List[str]):
parser = argparse.ArgumentParser(
add_help=False,
prog="calendar",
description="Show Calendar Data",
)
parser.add_argument(
"-d",
"--days",
dest="days",
action="store",
type=int,
default=7,
required=False,
help="The number of days to search for, up to 30 forward or backward "
+ "use negative numbers to search back. ",
)
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
parameters = {"instrument": instrument, "period": str(ns_parser.days * 86400 * -1)}
try:
request = labs.Calendar(params=parameters)
response = client.request(request)
l_data = []
for i in range(len(response)):
if "forecast" in response[i]:
forecast = response[i]["forecast"]
if response[i]["unit"] != "Index":
forecast += response[i]["unit"]
else:
forecast = ""
if "market" in response[i]:
market = response[i]["market"]
if response[i]["unit"] != "Index":
market += response[i]["unit"]
else:
market = ""
if "actual" in response[i]:
actual = response[i]["actual"]
if response[i]["unit"] != "Index":
actual += response[i]["unit"]
else:
actual = ""
if "previous" in response[i]:
previous = response[i]["previous"]
if response[i]["unit"] != "Index":
previous += response[i]["unit"]
else:
previous = ""
if "impact" in response[i]:
impact = response[i]["impact"]
else:
impact = ""
l_data.append(
{
"Title": response[i]["title"],
"Time": datetime.fromtimestamp(response[i]["timestamp"]),
"Impact": impact,
"Forecast": forecast,
"Market Forecast": market,
"Currency": response[i]["currency"],
"Region": response[i]["region"],
"Actual": actual,
"Previous": previous,
}
)
print(pd.DataFrame(l_data).to_string(index=False))
print("")
except V20Error as e:
d_error = eval(e.msg)
print(d_error["message"], "\n")
def load(other_args: List[str]):
"""Load a forex instrument to use"""
parser = argparse.ArgumentParser(
add_help=False,
prog="load",
description="Forex using oanda",
)
parser.add_argument(
"-i",
"--instrument",
required=True,
type=str,
dest="instrument",
help="Forex pair to use. ",
)
try:
if other_args:
if "-" not in other_args[0]:
other_args.insert(0, "-i")
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
print("")
return ns_parser.instrument.upper()
except Exception as e:
print(e, "\n")
return None
def book_plot(df, instrument, book_type):
_, ax = plt.subplots(figsize=plot_autoscale(), dpi=cfgPlot.PLOT_DPI)
df = df.apply(pd.to_numeric)
df["shortCountPercent"] = df["shortCountPercent"] * -1
axis_origin = max(
abs(max(df["longCountPercent"])), abs(max(df["shortCountPercent"]))
)
ax.set_xlim(-axis_origin, +axis_origin)
sns.set_style(style="darkgrid")
sns.barplot(
x="longCountPercent",
y="price",
data=df,
label="Count Percent",
color="green",
orient="h",
)
sns.barplot(
x="shortCountPercent",
y="price",
data=df,
label="Prices",
color="red",
orient="h",
)
ax.invert_yaxis()
plt.title(f"{instrument} {book_type}")
plt.xlabel("Count Percent")
plt.ylabel("Price")
sns.despine(left=True, bottom=True)
ax.yaxis.set_major_locator(mticker.MultipleLocator(5))
if gtff.USE_ION:
plt.ion()
plt.show()
def format_instrument(instrument, char):
if char not in instrument:
instrument_list = list(instrument)
instrument_list.pop(3)
instrument_list.insert(3, char)
instrument = "".join(map(str, instrument_list))
return instrument

View File

@@ -63,6 +63,7 @@ def print_help(s_ticker, s_start, s_interval, b_is_market_open):
print(
" po portfolio optimization, \t\t optimal portfolio weights from pyportfolioopt"
)
print(" fx forex menu, \t\t\t forex support through Oanda")
if s_ticker:
print(

50
poetry.lock generated
View File

@@ -837,7 +837,7 @@ idna = ">=2.0"
[[package]]
name = "importlib-metadata"
version = "4.0.0"
version = "4.0.1"
description = "Read metadata from Python packages"
category = "main"
optional = false
@@ -1496,6 +1496,14 @@ category = "main"
optional = false
python-versions = ">=3.6"
[[package]]
name = "oandapyv20"
version = "0.6.3"
description = "Python wrapper for the OANDA REST-V20 API"
category = "main"
optional = false
python-versions = "*"
[[package]]
name = "oauthlib"
version = "3.1.0"
@@ -2099,7 +2107,7 @@ python-versions = "*"
[[package]]
name = "pyupgrade"
version = "2.12.0"
version = "2.13.0"
description = "A tool to automatically upgrade syntax for newer versions."
category = "dev"
optional = false
@@ -2954,7 +2962,7 @@ prediction = ["fbprophet", "tensorflow", "pmdarima", "transformers", "flair", "t
[metadata]
lock-version = "1.1"
python-versions = "^3.6.8"
content-hash = "fa7c02ebec2d14a1c42f76f8e1328134975893c5f98afa879f2bc672675d6a7f"
content-hash = "2b31cd4c709b83d1a6f1d516036c84dc611cc487ae5d499905658454fa8dba40"
[metadata.files]
absl-py = [
@@ -3287,30 +3295,51 @@ entrypoints = [
]
ephem = [
{file = "ephem-3.7.7.1-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:0a6d6ed003383f702695094399728052981c567d423b25aa7163b3fd40de3d5a"},
{file = "ephem-3.7.7.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3cbc4f643329c4f64de63584e636625fa9f11b50209386ed99cbf508abe19488"},
{file = "ephem-3.7.7.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:e73b9997d7b844fabff988d7f66c3bad4e76ec8975ec9c60ec988037bb5c04b1"},
{file = "ephem-3.7.7.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:7619297a1103f6b3dac0c609bfa7c31e17678fb1a02653347ec030487e412031"},
{file = "ephem-3.7.7.1-cp27-cp27m-win32.whl", hash = "sha256:7756218a8b72ca50ee4f290b80828073412e7d7023389df5ead5d14839175bda"},
{file = "ephem-3.7.7.1-cp27-cp27m-win_amd64.whl", hash = "sha256:b8f9fb5b4184523b98f6629c6c927aeeba80d61df21f07af2844cdae45e1a294"},
{file = "ephem-3.7.7.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:37fd1abbebb821381d2865064a6fa9484ffdcd2161cf92193da8d42da79aa7db"},
{file = "ephem-3.7.7.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:ff4e1584cc232d8bc4aea405346eeb8a24b0fbe84c6331d4edb5d4456d19f1c3"},
{file = "ephem-3.7.7.1-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:c6081a9791e9de6511cddbeb9529bd5550fdb6f9e2a8dc9c2ec85911d67c6d11"},
{file = "ephem-3.7.7.1-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:d1d1ac8dc9be47dc6c7ec62800ca6557d03e8be3716c2a10ea0c8f1198c0a701"},
{file = "ephem-3.7.7.1-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:7f781d73e49caf7989c503a948471f1c8c1f738a450d557413999fb732f4dba3"},
{file = "ephem-3.7.7.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:f0959882bf73c8fe1cb801f42b0989e0ecb9d84b99eb8b8f70d61d16767a1e8a"},
{file = "ephem-3.7.7.1-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:06029db6b26f1764ed009360de8530f6cd759411232b3001df1b69ba6afa871d"},
{file = "ephem-3.7.7.1-cp35-cp35m-manylinux2014_s390x.whl", hash = "sha256:562baaeb3a46cf2248f97d2ad80092d747024e5dea62ebe50386a04b8e506c10"},
{file = "ephem-3.7.7.1-cp35-cp35m-win32.whl", hash = "sha256:2bcd953cced045e4232bcb71d60f6ba237f7944c880e83e74cc959449b192dee"},
{file = "ephem-3.7.7.1-cp35-cp35m-win_amd64.whl", hash = "sha256:fd0b922387df1ad8721f2fafd5dca51ce7105238f968e1532a177b781b8cae0e"},
{file = "ephem-3.7.7.1-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:e10c2c8afbb9e927d46d9bf3562441da2173ff196790a75ad0e5c5ee920d5922"},
{file = "ephem-3.7.7.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:592264e512b5658402e93903343eb26502c6f327df8a71847f3dcaea73908f32"},
{file = "ephem-3.7.7.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:8d586d970c42d62b1fc757a1c7c10679416a43e9e4a77391a05907159ce346f8"},
{file = "ephem-3.7.7.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:1a8ea6a045ff669011f8ecdeffadfc5eaa519fb56ab8dd40508910e9db5ec7b0"},
{file = "ephem-3.7.7.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:c25993d6554820ff11fdd8f2ddb75bf99e70db01327f09700bf8811201e9daef"},
{file = "ephem-3.7.7.1-cp36-cp36m-manylinux2014_s390x.whl", hash = "sha256:9180d953ff4cbe89fc9ccc78aea73f290c0166b8ddb01e9c837b4639a7492ec8"},
{file = "ephem-3.7.7.1-cp36-cp36m-win32.whl", hash = "sha256:72fdb72c813fc9780726aa732eb2193bbe1663549265ca5a746899215ecfbffd"},
{file = "ephem-3.7.7.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f5af029f8814aa8617e73b2ddcad2bd1c682ca13c31ee3b6f5825dd5cb43e777"},
{file = "ephem-3.7.7.1-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:e61c68f1c7d304a130bb6b88c1fca6600bbc1a1df6ca9a109b6eba4c6cbd3376"},
{file = "ephem-3.7.7.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fdf5f3ed8bd46ce2bf1145b26aec65a2c08ea7c97cf42b6b439af6e7bc6dc94d"},
{file = "ephem-3.7.7.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:31e2a17ca6f8d6bd44832574fea5461938ba034e52bf551e15e1a4c8f8c6c4fb"},
{file = "ephem-3.7.7.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:1ff5abefa230d5ab40846f1cb27d4f5583d46044fecf10e17bfb559bdc766a47"},
{file = "ephem-3.7.7.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:5ef34e3cfea0683998e867d7b8de642081e8821fafbd5e1d2dcab503c119c4a2"},
{file = "ephem-3.7.7.1-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:e2aca9edb59ee2bb3c8c36f17177966bc762da04af994450c8ad61a20fb6acdd"},
{file = "ephem-3.7.7.1-cp37-cp37m-win32.whl", hash = "sha256:71ea3935c658ee184575fd4cc2aa3e7fd6d6bac4a1ccff9ee5549cee67ff0385"},
{file = "ephem-3.7.7.1-cp37-cp37m-win_amd64.whl", hash = "sha256:34fd228105b89fefd20608420861a75a184db1edeaf0056cf2f85d2a2f768aee"},
{file = "ephem-3.7.7.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:189fcaeacb44dc5a1684ad489542f126d99d4a85e87d2fe73864c902f0bc2c71"},
{file = "ephem-3.7.7.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:a5ddf46ced515e4b81dfd22e6408fd06a329c31c6abb10af48d392641c490b0e"},
{file = "ephem-3.7.7.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:3530bee3eb7458d86d4c399f51f5b73ad7ea0441f0b2fb03de41d623789935af"},
{file = "ephem-3.7.7.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:77193de077e5fff453756144dee978e5fd6978c5c03ce3f67a09bb237e78f9d4"},
{file = "ephem-3.7.7.1-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:095ad42e8df6a5c91e0aeb5a68d76c0800b0283f72fc5f76e6df370ae1fb5537"},
{file = "ephem-3.7.7.1-cp38-cp38-win32.whl", hash = "sha256:33ad1a71b204aff123250b04e0ff2d5c3b8e9c6c814bf2c675d7752ce5896c02"},
{file = "ephem-3.7.7.1-cp38-cp38-win_amd64.whl", hash = "sha256:4bc5140cc7218a53ee6d949110f6ed413b8e3165294100515cd0fb29aa8e3637"},
{file = "ephem-3.7.7.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7aa88d2a6d216c2044be2a3b3cb184e9c8a5022f12464220694017ea9d75209d"},
{file = "ephem-3.7.7.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:1a9822bde93205c67fd3399b26868204b67d9e4442af21a764307e51ea6dc672"},
{file = "ephem-3.7.7.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:15dd3dbb3864fb853388e39ac3c915c72873507f54ee6b3ede0033b03465d8ba"},
{file = "ephem-3.7.7.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:5763919cdf38cd0488172711da504c3be003b7c104ccd2516cc496ff05f146ae"},
{file = "ephem-3.7.7.1-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:cdea23a7caa1178b322e6e76484d40bd021672446ff51b512f35581e0f1b32b7"},
{file = "ephem-3.7.7.1-cp39-cp39-win32.whl", hash = "sha256:c3cbc973b334892972445cec3deb99aafd0c57cb4e50679d5f12fc8c51b4e65f"},
{file = "ephem-3.7.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:1af920c382980fe3566a31f36bd712973e1ca6049cbe07b4624214d5e1f144bc"},
{file = "ephem-3.7.7.1.tar.gz", hash = "sha256:36b51a8dc7cfdeb456dd6b8ab811accab8341b2d562ee3c6f4c86f6d3dbb984e"},
]
fbprophet = [
@@ -3491,8 +3520,8 @@ idna-ssl = [
{file = "idna-ssl-1.1.0.tar.gz", hash = "sha256:a933e3bb13da54383f9e8f35dc4f9cb9eb9b3b78c6b36f311254d6d0d92c6c7c"},
]
importlib-metadata = [
{file = "importlib_metadata-4.0.0-py3-none-any.whl", hash = "sha256:19192b88d959336bfa6bdaaaef99aeafec179eca19c47c804e555703ee5f07ef"},
{file = "importlib_metadata-4.0.0.tar.gz", hash = "sha256:2e881981c9748d7282b374b68e759c87745c25427b67ecf0cc67fb6637a1bff9"},
{file = "importlib_metadata-4.0.1-py3-none-any.whl", hash = "sha256:d7eb1dea6d6a6086f8be21784cc9e3bcfa55872b52309bc5fad53a8ea444465d"},
{file = "importlib_metadata-4.0.1.tar.gz", hash = "sha256:8c501196e49fb9df5df43833bdb1e4328f64847763ec8a50703148b73784d581"},
]
inflection = [
{file = "inflection-0.5.1-py2.py3-none-any.whl", hash = "sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2"},
@@ -3955,6 +3984,9 @@ numpy = [
{file = "numpy-1.19.5-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:a0d53e51a6cb6f0d9082decb7a4cb6dfb33055308c4c44f53103c073f649af73"},
{file = "numpy-1.19.5.zip", hash = "sha256:a76f502430dd98d7546e1ea2250a7360c065a5fdea52b2dffe8ae7180909b6f4"},
]
oandapyv20 = [
{file = "oandapyV20-0.6.3.tar.gz", hash = "sha256:173a56b41ab3a19315c2fbea6f9aa3f0c17f64ba84acff014d072c64c1844b28"},
]
oauthlib = [
{file = "oauthlib-3.1.0-py2.py3-none-any.whl", hash = "sha256:df884cd6cbe20e32633f1db1072e9356f53638e4361bef4e8b03c9127c9328ea"},
{file = "oauthlib-3.1.0.tar.gz", hash = "sha256:bee41cc35fcca6e988463cacc3bcb8a96224f470ca547e697b604cc697b2f889"},
@@ -4305,8 +4337,8 @@ pytz = [
{file = "pytz-2021.1.tar.gz", hash = "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da"},
]
pyupgrade = [
{file = "pyupgrade-2.12.0-py2.py3-none-any.whl", hash = "sha256:024fc6be99c2ccdbc1c9354ac0ab8d5b9e5bf69a5477384677b6c9d8f2ce63bf"},
{file = "pyupgrade-2.12.0.tar.gz", hash = "sha256:eef4d77e44e57dfbae897a9a61543be1f34701dbbe51cc18462210021bd28dcf"},
{file = "pyupgrade-2.13.0-py2.py3-none-any.whl", hash = "sha256:1cb5a15573fc63824b952bf7dde5b96f9672a1179ec779ac2d159a845da743c8"},
{file = "pyupgrade-2.13.0.tar.gz", hash = "sha256:dc6b580b7bc82f357acb354bbba03d8d69da51425ecd5993a2651059bca80518"},
]
pywin32 = [
{file = "pywin32-300-cp35-cp35m-win32.whl", hash = "sha256:1c204a81daed2089e55d11eefa4826c05e604d27fe2be40b6bf8db7b6a39da63"},
@@ -4563,6 +4595,7 @@ scikit-learn = [
{file = "scikit_learn-0.24.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:c658432d8a20e95398f6bb95ff9731ce9dfa343fdf21eea7ec6a7edfacd4b4d9"},
{file = "scikit_learn-0.24.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:9dfa564ef27e8e674aa1cc74378416d580ac4ede1136c13dd555a87996e13422"},
{file = "scikit_learn-0.24.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:9c6097b6a9b2bafc5e0f31f659e6ab5e131383209c30c9e978c5b8abdac5ed2a"},
{file = "scikit_learn-0.24.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:5580eba7345a4d3b097be2f067cc71a306c44bab19e8717a30361f279c929bea"},
{file = "scikit_learn-0.24.1-cp36-cp36m-win32.whl", hash = "sha256:7b04691eb2f41d2c68dbda8d1bd3cb4ef421bdc43aaa56aeb6c762224552dfb6"},
{file = "scikit_learn-0.24.1-cp36-cp36m-win_amd64.whl", hash = "sha256:1adf483e91007a87171d7ce58c34b058eb5dab01b5fee6052f15841778a8ecd8"},
{file = "scikit_learn-0.24.1-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:ddb52d088889f5596bc4d1de981f2eca106b58243b6679e4782f3ba5096fd645"},
@@ -4570,6 +4603,7 @@ scikit-learn = [
{file = "scikit_learn-0.24.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:0567a2d29ad08af98653300c623bd8477b448fe66ced7198bef4ed195925f082"},
{file = "scikit_learn-0.24.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:99349d77f54e11f962d608d94dfda08f0c9e5720d97132233ebdf35be2858b2d"},
{file = "scikit_learn-0.24.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:83b21ff053b1ff1c018a2d24db6dd3ea339b1acfbaa4d9c881731f43748d8b3b"},
{file = "scikit_learn-0.24.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:abe835a851610f87201819cb315f8d554e1a3e8128912783a31e87264ba5ffb7"},
{file = "scikit_learn-0.24.1-cp37-cp37m-win32.whl", hash = "sha256:c3deb3b19dd9806acf00cf0d400e84562c227723013c33abefbbc3cf906596e9"},
{file = "scikit_learn-0.24.1-cp37-cp37m-win_amd64.whl", hash = "sha256:d54dbaadeb1425b7d6a66bf44bee2bb2b899fe3e8850b8e94cfb9c904dcb46d0"},
{file = "scikit_learn-0.24.1-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:3c4f07f47c04e81b134424d53c3f5e16dfd7f494e44fd7584ba9ce9de2c5e6c1"},
@@ -4577,6 +4611,7 @@ scikit-learn = [
{file = "scikit_learn-0.24.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:4ddd2b6f7449a5d539ff754fa92d75da22de261fd8fdcfb3596799fadf255101"},
{file = "scikit_learn-0.24.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:826b92bf45b8ad80444814e5f4ac032156dd481e48d7da33d611f8fe96d5f08b"},
{file = "scikit_learn-0.24.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:259ec35201e82e2db1ae2496f229e63f46d7f1695ae68eef9350b00dc74ba52f"},
{file = "scikit_learn-0.24.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:9599a3f3bf33f73fed0fe06d1dfa4e6081365a58c1c807acb07271be0dce9733"},
{file = "scikit_learn-0.24.1-cp38-cp38-win32.whl", hash = "sha256:8772b99d683be8f67fcc04789032f1b949022a0e6880ee7b75a7ec97dbbb5d0b"},
{file = "scikit_learn-0.24.1-cp38-cp38-win_amd64.whl", hash = "sha256:ed9d65594948678827f4ff0e7ae23344e2f2b4cabbca057ccaed3118fdc392ca"},
{file = "scikit_learn-0.24.1-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:8aa1b3ac46b80eaa552b637eeadbbce3be5931e4b5002b964698e33a1b589e1e"},
@@ -4584,6 +4619,7 @@ scikit-learn = [
{file = "scikit_learn-0.24.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:087dfede39efb06ab30618f9ab55a0397f29c38d63cd0ab88d12b500b7d65fd7"},
{file = "scikit_learn-0.24.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:895dbf2030aa7337649e36a83a007df3c9811396b4e2fa672a851160f36ce90c"},
{file = "scikit_learn-0.24.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:9a24d1ccec2a34d4cd3f2a1f86409f3f5954cc23d4d2270ba0d03cf018aa4780"},
{file = "scikit_learn-0.24.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:54be0a60a5a35005ad69c75902e0f5c9f699db4547ead427e97ef881c3242e6f"},
{file = "scikit_learn-0.24.1-cp39-cp39-win32.whl", hash = "sha256:fab31f48282ebf54dd69f6663cd2d9800096bad1bb67bbc9c9ac84eb77b41972"},
{file = "scikit_learn-0.24.1-cp39-cp39-win_amd64.whl", hash = "sha256:4562dcf4793e61c5d0f89836d07bc37521c3a1889da8f651e2c326463c4bd697"},
]

View File

@@ -59,6 +59,7 @@ tabulate = "^0.8.9"
pyportfolioopt = "^1.4.1"
selenium = "^3.141.0"
python-coinmarketcap = "^0.2"
oandapyV20 = "^0.6.3"
[tool.poetry.dev-dependencies]
pytest = "^6.2.2"

View File

@@ -1,4 +1,3 @@
absl-py==0.12.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.2.0"
aiohttp==3.7.4.post0; python_version >= "3.6"
alpaca-trade-api==1.2.0
alpha-vantage==2.3.1
@@ -6,7 +5,6 @@ ansiwrap==0.8.4; python_version >= "3.6"
appdirs==1.4.4; python_version >= "3.6"
appnope==0.1.2; platform_system == "Darwin" and python_version >= "3.6" and sys_platform == "darwin"
argon2-cffi==20.1.0; python_version >= "3.6"
astunparse==1.6.3
async-generator==1.10; python_full_version >= "3.6.1" and python_version >= "3.6"
async-timeout==3.0.1; python_full_version >= "3.5.3" and python_version >= "3.6"
attrs==20.3.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6"
@@ -14,15 +12,11 @@ backcall==0.2.0; python_version >= "3.6"
beautifulsoup4==4.9.3; python_version >= "3.5"
black==20.8b1; python_version >= "3.6"
bleach==3.3.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6"
bpemb==0.3.3; python_version >= "3.6"
bs4==0.0.1
cachetools==4.2.1; python_version >= "3.5" and python_version < "4.0" and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0")
certifi==2020.12.5; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0"
cffi==1.14.5; implementation_name == "pypy" and python_version >= "3.6"
chardet==4.0.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6"
click==7.1.2; python_full_version >= "3.6.0" and python_version >= "3.6"
cloudpickle==1.6.0; python_version >= "3.6"
cmdstanpy==0.4.0
click==7.1.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6"
colorama==0.4.4; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.5.0")
convertdate==2.3.2; python_version >= "3.5"
cryptography==3.4.7; python_version >= "3.6"
@@ -30,49 +24,32 @@ cssselect==1.1.0; python_version >= "2.7" and python_full_version < "3.0.0" or p
cvxpy==1.1.12; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5"
cycler==0.10.0; python_version >= "3.6"
cython==0.29.17; python_version >= "3.6" and python_full_version < "3.0.0" and sys_platform == "darwin" or python_full_version >= "3.3.0" and python_version >= "3.6" and sys_platform == "darwin"
dataclasses==0.8; python_version >= "3.6" and python_version < "3.7" and python_full_version >= "3.6.2"
dataclasses==0.8; python_version >= "3.6" and python_version < "3.7"
datetime==4.3; python_version >= "3.5"
decorator==4.4.2; python_full_version >= "3.6.1" and python_version >= "3.6" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.2.0" and python_version >= "3.6")
defusedxml==0.7.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6"
deprecated==1.2.12; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6"
detecta==0.0.5; python_version >= "3.6"
ecos==2.0.7.post1; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5"
entrypoints==0.3; python_version >= "3.6"
ephem==3.7.7.1; python_version >= "2.7" and python_version < "4"
fbprophet==0.6
filelock==3.0.12; python_full_version >= "3.6.0" and python_version >= "3.6"
finviz==1.4.1
finvizfinance==0.9.6; python_version >= "3.5"
flair==0.7; python_version >= "3.6"
flatbuffers==1.12
fredapi==0.4.3
ftfy==6.0.1; python_version >= "3.6"
fundamentalanalysis==0.2.7
future==0.18.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6"
gast==0.3.3; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0"
gdown==3.12.2; python_version >= "3.6"
gensim==3.8.2; python_version >= "3.6"
google-auth-oauthlib==0.4.4; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.2.0" and python_version >= "3.6"
google-auth==1.29.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6"
google-pasta==0.2.0
grpcio==1.32.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.2.0"
h5py==2.10.0
hijri-converter==2.1.1; python_version >= "3.6"
holidays==0.10.5.2
hyperopt==0.2.5; python_version >= "3.6"
idna-ssl==1.1.0; python_version < "3.7" and python_version >= "3.6"
idna==2.10; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "3.7" or python_version < "3.7" and python_version >= "3.6" and python_full_version >= "3.5.0"
importlib-metadata==4.0.0; python_version < "3.8" and python_version >= "3.6" and (python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "3.8" or python_full_version >= "3.2.0" and python_version >= "3.6" and python_version < "3.8")
importlib-metadata==4.0.1; python_version < "3.8" and python_version >= "3.6"
inflection==0.5.1; python_version >= "3.5"
ipykernel==5.5.3; python_version >= "3.6"
ipython-genutils==0.2.0; python_full_version >= "3.6.1" and python_version >= "3.6"
ipython==7.16.1; python_version >= "3.6"
ipywidgets==7.6.3
iso8601==0.1.14
janome==0.4.1; python_version >= "3.6"
jedi==0.18.0; python_version >= "3.6"
jinja2==2.11.3; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6"
joblib==1.0.1; python_version >= "3.6" and python_full_version >= "3.6.0"
joblib==1.0.1; python_version >= "3.6"
jsonschema==3.2.0; python_version >= "3.6"
jupyter-client==6.2.0; python_full_version >= "3.6.1" and python_version >= "3.6"
jupyter-console==6.4.0; python_version >= "3.6"
@@ -80,19 +57,13 @@ jupyter-core==4.7.1; python_full_version >= "3.6.1" and python_version >= "3.6"
jupyter==1.0.0
jupyterlab-pygments==0.1.2; python_version >= "3.6"
jupyterlab-widgets==1.0.0; python_version >= "3.6"
keras-preprocessing==1.1.2
kiwisolver==1.3.1; python_version >= "3.6"
konoha==4.6.3; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.6"
korean-lunar-calendar==0.2.1
langdetect==1.0.8; python_version >= "3.6"
lunarcalendar==0.0.9; python_version >= "2.7" and python_version < "4"
lxml==4.6.3; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6"
markdown==3.3.4; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.2.0" and python_version >= "3.6"
lxml==4.6.3; python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.5"
markupsafe==1.1.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6"
matplotlib==3.3.4; python_version >= "3.6"
mistune==0.8.4; python_version >= "3.6"
more-itertools==8.7.0; python_version >= "3.5"
mpld3==0.3; python_version >= "3.6"
mplfinance==0.12.7a12
msgpack==1.0.2
multidict==5.1.0; python_version >= "3.6"
@@ -102,14 +73,12 @@ nbclient==0.5.3; python_full_version >= "3.6.1" and python_version >= "3.6"
nbconvert==6.0.7; python_version >= "3.6"
nbformat==5.1.3; python_full_version >= "3.6.1" and python_version >= "3.6"
nest-asyncio==1.5.1; python_full_version >= "3.6.1" and python_version >= "3.6"
networkx==2.5.1; python_version >= "3.6"
notebook==6.3.0; python_version >= "3.6"
numpy==1.19.5; python_version >= "3.6"
oandapyv20==0.6.3
oauthlib==3.1.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0"
opt-einsum==3.3.0; python_version >= "3.5"
osqp==0.6.2.post0; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5"
overrides==3.1.0; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.6"
packaging==20.9; python_full_version >= "3.6.0" and python_version >= "3.6" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6")
packaging==20.9; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6"
pandas-ta==0.2.45b
pandas==1.1.5; python_full_version >= "3.6.1"
pandocfilters==1.4.3; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6"
@@ -127,13 +96,10 @@ prawcore==2.0.0; python_version >= "3.6" and python_version < "4.0"
prettytable==2.1.0; python_version >= "3.6"
prometheus-client==0.10.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6"
prompt-toolkit==3.0.18; python_full_version >= "3.6.1"
protobuf==3.15.8; python_full_version >= "3.6.0" and python_version >= "3.6"
psaw==0.0.12; python_version >= "3"
ptyprocess==0.7.0; os_name != "nt" and python_version >= "3.6" and sys_platform != "win32"
py==1.10.0; python_version >= "3.6" and python_full_version < "3.0.0" and implementation_name == "pypy" or implementation_name == "pypy" and python_version >= "3.6" and python_full_version >= "3.4.0"
pyally==1.1.2
pyasn1-modules==0.2.8; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0"
pyasn1==0.4.8; python_version >= "3.5" and python_full_version < "3.0.0" and python_version < "4" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6") or python_version >= "3.5" and python_version < "4" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6") and python_full_version >= "3.6.0"
pycoingecko==1.4.1
pycparser==2.20; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6"
pygments==2.8.1; python_version >= "3.6"
@@ -141,16 +107,15 @@ pymeeus==0.5.11; python_version >= "3.5"
pyobjc-core==7.1; python_version >= "3.6" and sys_platform == "darwin"
pyobjc-framework-cocoa==7.1; python_version >= "3.6" and sys_platform == "darwin"
pyotp==2.6.0; python_version >= "3"
pyparsing==2.4.7; python_full_version >= "3.6.0" and python_version >= "3.6" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6")
pyparsing==2.4.7; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6"
pyportfolioopt==1.4.1; python_full_version >= "3.6.1" and python_full_version < "4.0.0"
pyrsistent==0.14.11
pysocks==1.7.1; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0"
pystan==2.19.1.1
python-coinmarketcap==0.2
python-dateutil==2.8.1; python_full_version >= "3.6.1" and python_version >= "3.6" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6") and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.3.0") and (python_version >= "2.7" and python_full_version < "3.0.0" and python_version < "4" or python_version >= "2.7" and python_version < "4" and python_full_version >= "3.3.0")
python-dateutil==2.8.1; python_full_version >= "3.6.1" and python_version >= "3.6" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6") and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.3.0")
python-dotenv==0.17.0; python_version >= "3"
pytrends==4.7.3
pytz==2021.1; python_full_version >= "3.6.1" and python_version >= "3.5" and python_version < "4"
pytz==2021.1; python_full_version >= "3.6.1" and python_version >= "3.5"
pywin32==300; sys_platform == "win32" and python_version >= "3.6"
pywinpty==0.5.7; os_name == "nt" and python_version >= "3.6"
pyyaml==5.4.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6"
@@ -161,50 +126,35 @@ qtpy==1.9.0; python_version >= "3.6"
quandl==3.6.1; python_version >= "3.5"
rapidfuzz==1.4.1; python_version >= "3.5"
regex==2020.11.13
requests-oauthlib==1.3.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6"
requests-oauthlib==1.3.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0"
requests==2.25.1; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.5.0")
retrying==1.3.3
robin-stocks==2.0.3; python_version >= "3"
rsa==4.7.2; python_version >= "3.5" and python_version < "4" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6")
sacremoses==0.0.45; python_full_version >= "3.6.0" and python_version >= "3.6"
scikit-learn==0.24.1; python_version >= "3.6"
scipy==1.5.4; python_version >= "3.6"
screeninfo==0.6.7
scs==2.1.3; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5"
seaborn==0.11.1; python_version >= "3.6"
segtok==1.5.10; python_version >= "3.6"
selenium==3.141.0
send2trash==1.5.0; python_version >= "3.6"
sentencepiece==0.1.91; python_full_version >= "3.6.0" and python_version >= "3.6"
setuptools-git==1.2
six==1.15.0; python_full_version >= "3.6.1" and python_version >= "3.6" and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.3.0") and (python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.6" and python_version < "4.0" and python_full_version >= "3.4.0") and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6") and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0") and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6")
smart-open==5.0.0; python_version >= "3.6"
six==1.15.0; python_full_version >= "3.6.1" and python_version >= "3.6" and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.3.0") and (python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.6" and python_version < "4.0" and python_full_version >= "3.4.0") and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6") and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6")
soupsieve==2.2.1; python_version >= "3.6"
sqlitedict==1.7.0; python_version >= "3.6"
statsmodels==0.12.2; python_version >= "3.6"
tabulate==0.8.9
tenacity==7.0.0; python_version >= "3.6"
tensorboard-data-server==0.6.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.2.0" and python_version >= "3.6"
tensorboard-plugin-wit==1.8.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.2.0"
tensorboard==2.5.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.2.0"
tensorflow-estimator==2.4.0
tensorflow==2.4.1
termcolor==1.1.0
terminado==0.9.4; python_version >= "3.6"
testpath==0.4.4; python_version >= "3.6"
textwrap3==0.9.2; python_version >= "3.6"
threadpoolctl==2.1.0; python_version >= "3.6"
timeseriescrossvalidation @ git+https://github.com/DidierRLopes/TimeSeriesCrossValidation.git@master
tokenizers==0.9.3; python_full_version >= "3.6.0" and python_version >= "3.6"
toml==0.10.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6"
torch==1.7.1; python_full_version >= "3.6.2"
tornado==6.1; python_full_version >= "3.6.1" and python_version >= "3.6"
tqdm==4.60.0; python_full_version >= "3.6.0" and python_version >= "3.6" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6")
tqdm==4.60.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6"
tradingview-ta==3.2.3; python_version >= "3.5"
traitlets==4.3.3; python_full_version >= "3.6.1" and python_version >= "3.6"
transformers==3.5.1; python_full_version >= "3.6.0"
typed-ast==1.4.3; python_version >= "3.6"
typing-extensions==3.7.4.3; python_full_version >= "3.6.2" and python_version >= "3.6" and python_version < "3.8"
typing-extensions==3.7.4.3; python_version < "3.8" and python_version >= "3.6"
update-checker==0.18.0; python_version >= "3.6" and python_version < "4.0"
urllib3==1.26.4; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version < "4" and python_version >= "3.6"
user-agent==0.1.9
@@ -212,9 +162,7 @@ wcwidth==0.2.5; python_version >= "3.6" and python_full_version >= "3.6.1"
webencodings==0.5.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6"
websocket-client==0.58.0; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.6" and python_version < "4.0" and python_full_version >= "3.4.0"
websockets==8.1; python_full_version >= "3.6.1"
werkzeug==1.0.1; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0"
widgetsnbextension==3.5.1
wrapt==1.12.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6"
yarl==1.6.3; python_version >= "3.6"
yfinance==0.1.59
zipp==3.4.1; python_version < "3.8" and python_version >= "3.6"

View File

@@ -40,7 +40,7 @@ hijri-converter==2.1.1; python_version >= "3.6"
holidays==0.10.5.2
idna-ssl==1.1.0; python_version < "3.7" and python_version >= "3.6"
idna==2.10; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "3.7" or python_version < "3.7" and python_version >= "3.6" and python_full_version >= "3.5.0"
importlib-metadata==4.0.0; python_version < "3.8" and python_version >= "3.6"
importlib-metadata==4.0.1; python_version < "3.8" and python_version >= "3.6"
inflection==0.5.1; python_version >= "3.5"
ipykernel==5.5.3; python_version >= "3.6"
ipython-genutils==0.2.0; python_full_version >= "3.6.1" and python_version >= "3.6"
@@ -75,6 +75,7 @@ nbformat==5.1.3; python_full_version >= "3.6.1" and python_version >= "3.6"
nest-asyncio==1.5.1; python_full_version >= "3.6.1" and python_version >= "3.6"
notebook==6.3.0; python_version >= "3.6"
numpy==1.19.5; python_version >= "3.6"
oandapyv20==0.6.3
oauthlib==3.1.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0"
osqp==0.6.2.post0; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5"
packaging==20.9; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6"

View File

@@ -32,6 +32,7 @@ from gamestonk_terminal.portfolio import port_controller
from gamestonk_terminal.cryptocurrency import crypto_controller
from gamestonk_terminal.screener import screener_controller
from gamestonk_terminal.portfolio_optimization import po_controller
from gamestonk_terminal.forex import fx_controller
# pylint: disable=too-many-statements,too-many-branches
@@ -85,6 +86,7 @@ def main():
"crypto",
"ra",
"po",
"fx",
]
menu_parser.add_argument("opt", choices=choices)
@@ -220,6 +222,9 @@ def main():
s_interval,
)
elif ns_known_args.opt == "fx":
b_quit = fx_controller.menu()
elif ns_known_args.opt == "ta":
b_quit = ta_controller.menu(
df_stock,