Merge pull request #9 from alokan/forex

Forex
This commit is contained in:
DJ
2021-04-15 22:41:32 -06:00
committed by GitHub
3 changed files with 446 additions and 62 deletions

View File

@@ -1,5 +1,5 @@
import argparse
# import matplotlib.pyplot as plt
from typing import List
from prompt_toolkit.completion import NestedCompleter
from gamestonk_terminal.helper_funcs import get_flair, parse_known_args_and_warn
from gamestonk_terminal import feature_flags as gtff
@@ -17,21 +17,28 @@ class OandaController:
"help",
"q",
"quit",
"hist",
"price",
"summary",
"list"]
"list",
"orderbook",
"positionbook",
"limitorder",
"cancel",
"positions",
"closetrade",
"trades",
"candles",
"pending",
]
def __init__(
self,
# instrument:str,
):
):
"""Construct Data"""
# self.instrument = instrument
self.oanda_parser = argparse.ArgumentParser(add_help=False, prog="fx")
self.oanda_parser.add_argument(
"cmd",
choices=self.CHOICES,
"cmd",
choices=self.CHOICES,
)
@staticmethod
@@ -39,13 +46,22 @@ class OandaController:
"""Print help"""
print("\nForex Mode:")
print("\t help \t show this menu again")
print("\t q \t quit this menu and goes back to main menu")
print("\t quit \t quit to abandon program")
print("help \t show this menu again")
print("q \t quit this menu and goes back to main menu")
print("quit \t quit to abandon program")
print("")
print("\t price \t shows price for selected instrument")
print("\t summary shows account summary")
print("\t list \t list orders")
print("price \t shows price for selected instrument")
print("summary shows account summary")
print("list \t list order history")
print("trades \t list open trades")
print("orderbook \t print orderbook")
print("positionbook \t print positionbook")
print("limitorder \t place limit order -u # of units -p price")
print("cancel \t cancel a pending order by ID -i order ID")
print("pending \t get information on pending orders")
print("positions \t Get open positions")
print("closetrade \t Close a trade by id")
print("candles \t show candles")
def switch(self, an_input: str):
"""Process and dispatch input
@@ -58,7 +74,9 @@ class OandaController:
"""
(known_args, other_args) = self.oanda_parser.parse_known_args(an_input.split())
return getattr(self, "call_" + known_args.cmd, lambda: "command not recognized!")(other_args)
return getattr(
self, "call_" + known_args.cmd, lambda: "command not recognized!"
)(other_args)
def call_help(self, _):
"""Process Help Command"""
@@ -72,46 +90,77 @@ class OandaController:
"""Process Quit command - exit the program"""
return True
def call_price(self, _):
def call_price(self, other_args: List[str]):
"""Process Price Command"""
try:
oanda_functions.get_fx_price(account, instrument)
except NameError as e:
print(e)
oanda_functions.get_fx_price(account, other_args)
def call_summary(self, _):
"""Process account summary command"""
oanda_functions.get_account_summary(account)
def call_list(self, _):
def call_orderbook(self, other_args: List[str]):
"""Process Oanda Order Book"""
oanda_functions.get_order_book(other_args)
def call_positionbook(self, other_args: List[str]):
"""Process Oanda Position Book"""
oanda_functions.get_position_book(other_args)
def call_list(self, other_args: List[str]):
"""Process list orders command"""
oanda_functions.list_orders(account)
oanda_functions.list_orders(account, other_args)
def call_limitorder(self, other_args: List[str]):
"""Place limit order"""
oanda_functions.create_limit_order(account, other_args)
def call_cancel(self, other_args: List[str]):
"""Cancel pending order by ID"""
oanda_functions.cancel_pending_order(account, other_args)
def call_positions(self, _):
"""Get Open Positions"""
oanda_functions.get_open_positions(account)
def call_pending(self, _):
"""See up to 25 pending orders"""
oanda_functions.get_pending_orders(account)
def call_closetrade(self, other_args: List[str]):
"""Close a trade by id"""
oanda_functions.close_trade(account, other_args)
def call_candles(self, _):
oanda_functions.show_candles(account)
def call_trades(self, _):
"""List open trades"""
oanda_functions.get_open_trades(account)
def menu():
"""Oanda Menu"""
oanda_controller = OandaController()
oanda_controller.call_help(None)
while True:
if session and gtff.USE_PROMPT_TOOLKIT:
completer = NestedCompleter.from_nested_dict(
{c: None for c in oanda_controller.CHOICES}
)
"""Oanda Menu"""
oanda_controller = OandaController()
oanda_controller.call_help(None)
while True:
if session and gtff.USE_PROMPT_TOOLKIT:
completer = NestedCompleter.from_nested_dict(
{c: None for c in oanda_controller.CHOICES}
)
an_input = session.prompt(
an_input = session.prompt(
f"{get_flair()} (fx)> ",
completer=completer,
)
else:
an_input = input(f"{get_flair()} (fx)> ")
)
else:
an_input = input(f"{get_flair()} (fx)> ")
try:
process_input = oanda_controller.switch(an_input)
try:
process_input = oanda_controller.switch(an_input)
if process_input is not None:
return process_input
except SystemExit:
print("The command selected doesn't exit\n")
continue
if process_input is not None:
return process_input
except SystemExit:
print("The command selected doesn't exit\n")
continue

View File

@@ -1,24 +1,49 @@
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
from oandapyV20.exceptions import V20Error
from gamestonk_terminal import config_terminal as cfg
from gamestonk_terminal.helper_funcs import parse_known_args_and_warn
import pandas as pd
import matplotlib.pyplot as plt
import mplfinance as mpf
import matplotlib.dates as mdates
client = API(access_token=cfg.OANDA_TOKEN, environment="live")
account = cfg.OANDA_ACCOUNT
def get_fx_price(accountID, instrument):
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)
def get_fx_price(accountID, other_args: List[str]):
parser = argparse.ArgumentParser(
add_help=False,
prog="getfxprice",
description="Get price for forex",
)
parser.add_argument(
"-i", "--instrument", dest="instrument", action="store", required=True
)
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
try:
parameters = {"instruments": ns_parser.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(ns_parser.instrument + " Bid: " + bid)
print(ns_parser.instrument + " Ask: " + ask)
except V20Error as e:
print(e)
except NameError as e:
print(e)
def get_account_summary(accountID):
@@ -47,13 +72,34 @@ def get_account_summary(accountID):
print(f"Margin Closeout Position Value: {margin_closeout_position_value}")
def list_orders(accountID, state="ALL", count="50"):
def list_orders(accountID, other_args: List[str]):
parser = argparse.ArgumentParser(
add_help=False,
prog="listorders",
description="List order history",
)
parser.add_argument(
"-s", "--state", dest="state", action="store", default="ALL", required=False
)
parser.add_argument(
"-c", "--count", dest="count", action="store", default=50, required=False
)
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
parameters = {
"state": state,
"count": count
# "state": ns_parser.state,
# "count": ns_parser.count,
}
request = orders.OrderList(accountID, parameters) response = client.request(request)
for i in range(0, int(count), 1):
if ns_parser.state is not None:
parameters["state"] = ns_parser.state
if ns_parser.count is not None:
parameters["count"] = ns_parser.count
request = orders.OrderList(accountID, parameters)
response = client.request(request)
for i in range(0, int(ns_parser.count), 1):
try:
order_id = response["orders"][i]["id"]
instrument = response["orders"][i]["instrument"]
@@ -66,12 +112,299 @@ def list_orders(accountID, state="ALL", count="50"):
print(f"Units: {units}")
print(f"Order State: {order_state}")
print(f"Order Type: {order_type}")
print("")
except KeyError as e:
print(f"Key error: {e} not found \n")
print("-" * 30)
except KeyError:
continue
except IndexError as e:
print(e)
except IndexError:
break
def get_order_book(other_args: List[str]):
parser = argparse.ArgumentParser(
add_help=False,
prog="get_order_book",
description="Get Order book",
)
parser.add_argument(
"-i", "--instrument", dest="instrument", action="store", required=True
)
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
parameters = {"bucketWidth": 0.1}
request = instruments.InstrumentsOrderBook(
instrument=ns_parser.instrument, params=parameters
)
response = client.request(request)
for i in range(400, 700, 1):
order_instrument = response["orderBook"]["instrument"]
price = response["orderBook"]["buckets"][i]["price"]
short_count_percent = response["orderBook"]["buckets"][i]["shortCountPercent"]
long_count_percent = response["orderBook"]["buckets"][i]["longCountPercent"]
print(f"Instrument: {order_instrument}")
print(f"Price: {price}")
print(f"Short count percent: {short_count_percent}")
print(f"Long count percent: {long_count_percent}")
print("-" * 30)
def get_position_book(other_args: List[str]):
parser = argparse.ArgumentParser(
add_help=False,
prog="get_position_book ",
description="Get Position Book",
)
parser.add_argument(
"-i", "--instrument", dest="instrument", action="store", required=True
)
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
parameters = {"bucketWidth": 0.1}
request = instruments.InstrumentsPositionBook(
instrument=ns_parser.instrument, params=parameters
)
response = client.request(request)
for i in range(200, 400, 1):
order_instrument = response["positionBook"]["instrument"]
price = response["positionBook"]["buckets"][i]["price"]
short_count_percent = response["positionBook"]["buckets"][i][
"shortCountPercent"
]
long_count_percent = response["positionBook"]["buckets"][i]["longCountPercent"]
print(f"Instrument: {order_instrument}")
print(f"Price: {price}")
print(f"Short count percent: {short_count_percent}")
print(f"Long count percent: {long_count_percent}")
print("-" * 30)
def create_limit_order(accountID, other_args: List[str]):
parser = argparse.ArgumentParser(
add_help=False,
prog="create_limit_order",
description="Create limit order",
)
parser.add_argument(
"-u",
"--unit",
dest="units",
action="store",
type=int,
default=0,
required=True,
)
parser.add_argument(
"-p",
"--price",
dest="price",
action="store",
type=float,
required=True,
)
parser.add_argument(
"-i",
"--instrument",
dest="instrument",
action="store",
required=True)
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
data = {
"order": {
"price": ns_parser.price,
"instrument": ns_parser.instrument,
"units": ns_parser.units,
"type": "LIMIT",
"timeInForce": "GTC",
"positionFill": "DEFAULT",
}
}
request = orders.OrderCreate(accountID, data)
response = client.request(request)
print(response)
def cancel_pending_order(accountID, other_args: List[str]):
parser = argparse.ArgumentParser(
add_help=False,
prog="cancelpendingorder",
description="Cancel Pending Order",
)
parser.add_argument(
"-i",
"--id",
dest="orderID",
action="store",
type=str,
required=True,
)
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
try:
request = orders.OrderCancel(accountID, ns_parser.orderID)
client.request(request)
except V20Error as e:
print(e)
def get_pending_orders(accountID):
request = orders.OrdersPending(accountID)
response = client.request(request)
for i in range(len(response["orders"])):
try:
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)
except IndexError:
break
def get_open_positions(accountID):
request = positions.OpenPositions(accountID)
response = client.request(request)
for i in range(0, 100, 1):
try:
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")
except IndexError:
break
def get_open_trades(accountID):
request = trades.OpenTrades(accountID)
response = client.request(request)
for i in range(len(response["trades"])):
try:
order_id = response["trades"][i]["id"]
instrument = response["trades"][i]["instrument"]
initial_units = response["trades"][i]["initialUnits"]
current_units = response["trades"][i]["currentUnits"]
price = response["trades"][i]["price"]
unrealized_pl = response["trades"][i]["unrealizedPL"]
print(f"Order ID: {order_id}\n")
print(f"Instrument: {instrument}")
print(f"Initial Units: {initial_units}")
print(f"Current Units: {current_units}")
print(f"Entry Price: {price}")
print(f"Unrealized P/L: {unrealized_pl}")
print("-" * 30 + "\n")
except IndexError:
break
def close_trade(accountID, other_args: List[str]):
parser = ArgumentParser(
add_help=False,
prog="close_trade",
description="close a trade",
)
parser.add_argument(
"-i",
"--id",
dest="orderID",
action="store",
type=str,
required=True,
)
parser.add_argument(
"-u",
"--units",
dest="units",
action="store",
type=str,
required=False,
)
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
data = {
"units": ns_parser.units,
}
try:
request = trades.TradeClose(accountID, ns_parser.orderID, data)
response = client.request(request)
except V20Error as e:
print(e)
def show_candles(accountID):
parameters = {
"granularity": "D"
}
try:
request = instruments.InstrumentsCandles("EUR_USD", params=parameters)
response = client.request(request)
process_response(response)
oanda_fix_date(".temp_candles.csv")
df = pd.read_csv(".candles.csv")
df["Datetime"] = pd.to_datetime(df["Datetime"])
df.set_index(pd.DatetimeIndex(df["Datetime"]), inplace=True)
print(df)
# dvalues = df[["Open", "High", "Low", "Close"]].values.tolist()
# pdates = mdates.date2num(data.index)
# ohlc = [ ppdates[i] + dvalues[i] for i in range(len(pdates))]
# plt.style.use("fivethirtyeight")
# fix, ax = plt.subplots(figsize = (12, 6))
# mpf.candlestick_ohlc(ax, ohlc[-50:], width=0.4)
# ax.set_xlabel("Date")
# ax.set_ylabel("Price")
# ax.set_title("Chart for EUR_USD")
# ax.xaxis.set_major_formatter(mdates.DateFormatter('%b %d'))
# fig.autofmt_xdate()
mpf.plot(df, type="candlestick")
# plt.show()
except Exception as e:
print(e)
def process_response(response):
with open(".temp_candles.csv", 'w') as out:
for i in range(len(response["candles"])):
time = response["candles"][i]["time"]
o = response["candles"][i]["mid"]["o"]
h = response["candles"][i]["mid"]["h"]
l = response["candles"][i]["mid"]["l"]
c = response["candles"][i]["mid"]["c"]
out.write(str(time) + "," + str(o) + "," + str(h) + "," + str(l) + "," + str(c) + "\n")
def oanda_fix_date(file):
with open(file, 'r') as candle_file:
lines = candle_file.readlines()
with open(".candles.csv", 'w') as out:
out.write("Datetime, Open, High, Low, Close\n")
for line in lines:
with open(".candles.csv", "a") as output:
output.write(line[:10] + " " + line[11:19] + line[30:])

View File

@@ -33,6 +33,8 @@ 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.oanda import oanda_controller
from gamestonk_terminal.portfolio_optimization import po_controller
# import warnings
# warnings.simplefilter("always")