mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-10-29 05:21:48 +00:00
@@ -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
|
||||
|
||||
@@ -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:])
|
||||
|
||||
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user