Requested Changes

This commit is contained in:
DJ
2021-04-19 12:08:00 -06:00
parent e90d192609
commit a4914b775b
2 changed files with 299 additions and 91 deletions

View File

@@ -43,7 +43,7 @@ class ForexController:
self.instrument = None
@staticmethod
def print_help():
def print_help(self):
"""Print help"""
print("\nForex Mode:")
@@ -51,21 +51,23 @@ class ForexController:
print(" q Quit this menu and goes back to main menu")
print(" quit Quit to abandon program")
print("")
print(" cancel Cancel a pending order by ID -i order ID")
print(" candles Show candles")
print(" calendar Show calendar")
print(" closetrade Close a trade by id")
print(" list List order history")
print(" load Load an instrument to use")
print(" order Place limit order -u # of units -p price")
print(" orderbook Print orderbook")
print(" pending Get information on pending orders")
print(" positionbook Print positionbook")
print(" positions Get open positions")
print(" price Shows price for selected instrument")
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("")
if self.instrument is not None:
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
@@ -84,7 +86,7 @@ class ForexController:
def call_help(self, _):
"""Process Help Command"""
self.print_help()
self.print_help(self)
def call_q(self, _):
"""Process Q command - quit the menu"""
@@ -94,24 +96,24 @@ class ForexController:
"""Process Quit command - exit the program"""
return True
def call_price(self, _):
def call_price(self, other_args):
"""Process Price Command"""
fx_view.get_fx_price(account, self.instrument)
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, _):
def call_summary(self, other_args):
"""Process account summary command"""
fx_view.get_account_summary(account)
fx_view.get_account_summary(account, other_args)
def call_orderbook(self, _):
def call_orderbook(self, other_args):
"""Process Oanda Order Book"""
fx_view.get_order_book(self.instrument)
fx_view.get_order_book(self.instrument, other_args)
def call_positionbook(self, _):
def call_positionbook(self, other_args):
"""Process Oanda Position Book"""
fx_view.get_position_book(self.instrument)
fx_view.get_position_book(self.instrument, other_args)
def call_list(self, other_args: List[str]):
"""Process list orders command"""
@@ -125,13 +127,13 @@ class ForexController:
"""Cancel pending order by ID"""
fx_view.cancel_pending_order(account, other_args)
def call_positions(self, _):
def call_positions(self, other_args):
"""Get Open Positions"""
fx_view.get_open_positions(account)
fx_view.get_open_positions(account, other_args)
def call_pending(self, _):
def call_pending(self, other_args):
"""See up to 25 pending orders"""
fx_view.get_pending_orders(account)
fx_view.get_pending_orders(account, other_args)
def call_closetrade(self, other_args: List[str]):
"""Close a trade by id"""
@@ -140,9 +142,9 @@ class ForexController:
def call_candles(self, other_args: List[str]):
fx_view.show_candles(account, self.instrument, other_args)
def call_trades(self, _):
def call_trades(self, other_args):
"""List open trades"""
fx_view.get_open_trades(account)
fx_view.get_open_trades(account, other_args)
def call_calendar(self, other_args: List[str]):
"""Call calendar"""

View File

@@ -25,7 +25,16 @@ client = API(access_token=cfg.OANDA_TOKEN, environment="live")
account = cfg.OANDA_ACCOUNT
def get_fx_price(accountID, instrument):
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)
@@ -34,11 +43,24 @@ def get_fx_price(accountID, instrument):
ask = response["prices"][0]["asks"][0]["price"]
print(instrument + " Bid: " + bid)
print(instrument + " Ask: " + ask)
print("")
except V20Error as e:
print(e)
msg_length = len(e.msg)
msg = e.msg[17 : msg_length - 2]
print(msg)
print("")
def get_account_summary(accountID):
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)
@@ -65,21 +87,37 @@ def get_account_summary(accountID):
print(f"Margin Closeout {margin_closeout}")
print(f"Margin Closeout Percent: {margin_closeout_percent}")
print(f"Margin Closeout Position Value: {margin_closeout_position_value}")
print("")
except V20Error as e:
print(e)
msg_length = len(e.msg)
msg = e.msg[17 : msg_length - 2]
print(msg)
print("")
def list_orders(accountID, other_args: List[str]):
parser = argparse.ArgumentParser(
add_help=False,
prog="listorders",
prog="list",
description="List order history",
)
parser.add_argument(
"-s", "--state", dest="state", action="store", default="ALL", required=False
"-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=50, required=False
"-c",
"--count",
dest="count",
action="store",
default=50,
required=False,
help="the number of orders to retrive ",
)
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
@@ -92,14 +130,31 @@ def list_orders(accountID, other_args: List[str]):
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)
try:
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")
print("")
except V20Error as e:
print(e)
msg_length = len(e.msg)
msg = e.msg[17 : msg_length - 2]
print(msg)
print("")
def get_order_book(instrument):
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:
request = instruments.InstrumentsOrderBook(
@@ -110,11 +165,24 @@ def get_order_book(instrument):
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:
print(e)
msg_length = len(e.msg)
msg = e.msg[17 : msg_length - 2]
print(msg)
print("")
def get_position_book(instrument):
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:
request = instruments.InstrumentsPositionBook(instrument=instrument)
response = client.request(request)
@@ -122,14 +190,18 @@ def get_position_book(instrument):
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:
print(e)
msg_length = len(e.msg)
msg = e.msg[17 : msg_length - 2]
print(msg)
print("")
def create_order(accountID, instrument, other_args: List[str]):
parser = argparse.ArgumentParser(
add_help=False,
prog="create_order",
prog="order",
description="Create order",
)
parser.add_argument(
@@ -140,6 +212,8 @@ def create_order(accountID, instrument, other_args: List[str]):
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",
@@ -148,6 +222,7 @@ def create_order(accountID, instrument, other_args: List[str]):
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)
@@ -167,16 +242,52 @@ def create_order(accountID, instrument, other_args: List[str]):
try:
request = orders.OrderCreate(accountID, data)
response = client.request(request)
print(response)
try:
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:
print(e)
msg_length = len(e.msg)
msg = e.msg[17 : msg_length - 2]
print(msg)
print("")
def cancel_pending_order(accountID, other_args: List[str]):
parser = argparse.ArgumentParser(
add_help=False,
prog="cancelpendingorder",
description="Cancel Pending Order",
prog="pending",
description="Cancel Pending Order ",
)
parser.add_argument(
"-i",
@@ -184,19 +295,37 @@ def cancel_pending_order(accountID, other_args: List[str]):
dest="orderID",
action="store",
type=str,
required=True,
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)
client.request(request)
response = client.request(request)
order_id = response["orderCancelTransaction"]["orderID"]
print(f"Order {order_id} canceled.")
print("")
except V20Error as e:
print(e)
msg_length = len(e.msg)
msg = e.msg[17 : msg_length - 2]
print(msg)
print("")
def get_pending_orders(accountID):
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)
@@ -217,11 +346,23 @@ def get_pending_orders(accountID):
print("-" * 30)
except IndexError:
break
print("")
except V20Error as e:
print(e)
msg_length = len(e.msg)
msg = e.msg[17 : msg_length - 2]
print(msg)
print("")
def get_open_positions(accountID):
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)
@@ -241,44 +382,65 @@ def get_open_positions(accountID):
print(f"Total Short P/L: {short_pl}")
print(f"Short Unrealized P/L: {short_upl}")
print("-" * 30 + "\n")
print("")
except V20Error as e:
print(e)
msg_length = len(e.msg)
msg = e.msg[17 : msg_length - 2]
print(msg)
print("")
def get_open_trades(accountID):
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)
df = pd.DataFrame.from_dict(response["trades"])
df = df[
[
"id",
"instrument",
"initialUnits",
"currentUnits",
"price",
"unrealizedPL",
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",
}
)
print(df)
df = df.rename(
columns={
"id": "ID",
"instrument": "Instrument",
"initialUnits": "Initial Units",
"currentUnits": "Current Units",
"price": "Entry Price",
}
)
print(df)
print("")
except KeyError:
print("No trades were found")
print("")
except V20Error as e:
print(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="close_trade",
description="close a trade",
prog="closetrade",
description="Close a trade by id.",
)
parser.add_argument(
"-i",
@@ -287,6 +449,7 @@ def close_trade(accountID, other_args: List[str]):
action="store",
type=str,
required=True,
help="The Trade ID to close. ",
)
parser.add_argument(
"-u",
@@ -295,25 +458,55 @@ def close_trade(accountID, other_args: List[str]):
action="store",
type=str,
required=False,
help="The number of units on the trade to close. If not set it "
+ "defaults to all units. ",
)
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
data = {
"units": ns_parser.units,
}
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)
print(response)
try:
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)
print("")
except V20Error as e:
print(e)
if "orderRejectTransaction" in e.msg:
msg_length = len(e.msg)
order_id = e.msg[355 : msg_length - 149]
print(f"Order ID {order_id} doesn't exist")
print("")
else:
msg_length = len(e.msg)
msg = e.msg[17 : msg_length - 2]
print(msg)
print("")
def show_candles(accountID, instrument, other_args: List[str]):
parser = argparse.ArgumentParser(
add_help=False,
prog="show_candles",
prog="candles",
description="Display Candle Data",
)
parser.add_argument(
@@ -324,6 +517,9 @@ def show_candles(accountID, instrument, other_args: List[str]):
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, Wee: W Month: M",
)
parser.add_argument(
"-c",
@@ -333,6 +529,7 @@ def show_candles(accountID, instrument, other_args: List[str]):
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)
@@ -359,10 +556,12 @@ def show_candles(accountID, instrument, other_args: List[str]):
volume=True,
title=f"{instrument} {ns_parser.granularity}",
)
except Exception as e:
print(e)
except NameError as e:
print(e)
print("")
except V20Error as e:
msg_length = len(e.msg)
msg = e.msg[17 : msg_length - 2]
print(msg)
print("")
def process_candle_response(response):
@@ -414,6 +613,8 @@ def calendar(instrument, other_args: List[str]):
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:
@@ -469,15 +670,20 @@ def calendar(instrument, other_args: List[str]):
else:
print(f"Previous: {previous}")
print("-" * 30)
print("")
except V20Error as e:
print(e)
msg_length = len(e.msg)
msg = e.msg[17 : msg_length - 2]
print(msg)
print("")
print("")
def load(other_args: List[str]):
"""Load a forex instrument to use"""
parser = argparse.ArgumentParser(
add_help=False,
prog="Forex",
prog="load",
description="Forex using oanda",
)
@@ -487,7 +693,7 @@ def load(other_args: List[str]):
required=True,
type=str,
dest="instrument",
help="Instrument to use for function calls",
help="Forex pair to use. ",
)
try: