This commit is contained in:
DJ
2021-04-23 05:12:26 -06:00
parent fd31f7ac31
commit 13f4e112fe
3 changed files with 682 additions and 326 deletions

View File

@@ -0,0 +1,160 @@
# 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] [-aAbcCemorRstv]
```
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)
* -a : Adds AD (Accumulation/Distribution Index) to the chart. AD is a cumulative indicator that uses volume and price to assess whether a stock is being accumulated or distributed. This provides insight into how strong a trend is. [Investopedia](#https://www.investopedia.com/terms/a/accumulationdistribution.asp)
* -A : Adds ADX (Average Directional Index) to the chart. ADX is used to determine the strength of a trend. [Investopedia](#https://www.investopedia.com/terms/a/adx.asp)
* -b : Adds Bollinger Bands to the chart. Bollinger bands are a set of trendlines plotted two standard deviations (positively and negatively) away from a simple moving average of a security's price. [Investopedia](#https://www.investopedia.com/terms/b/bollingerbands.asp)
* -C : Adds CCI (Commodity Channel Index) to the chart. CCI is a momentum-based oscillator used to help determine when an investment vehicle is reaching a condition of being overbought or oversold. [Investopedia](#https://www.investopedia.com/terms/c/commoditychannelindex.asp)
* -e : Adds EMA (Exponential Moving Average) to the chart. EMA is a moving average that places a greater weight and significance on the most recent data points. [Investopedia](#https://www.investopedia.com/terms/e/ema.asp)
* -m : Adds MACD (Moving Average Convergence Divergence) to the chart. MACD is a trend-following momentum indicator that shows the relationship between two moving averages of a security’s price. [Investopedia](#https://www.investopedia.com/terms/m/macd.asp)
* -o : Adds OBV (On Balance Volume) to the chart. OBV is a momentum indicator that uses volume flow to predict changes in price. [Investopedia](#https://www.investopedia.com/terms/o/onbalancevolume.asp)
* -r : Adds RSI (Relative Strength Index) to the chart. RSI is a momentum indicator that measures the magnitude of recent price changes to evaluate overbought or oversold conditions. [Investopedia](#https://www.investopedia.com/terms/r/rsi.asp)
* -R : Adds Aroon to the chart. Aroon is used to identify trend changes in the price of an asset, as well as the strength of that trend by measureing the time between highs and the time between lows over a time period. [Investopedia](#https://www.investopedia.com/terms/a/aroon.asp)
* -s : Adds SMA (Simple Moving Average) to the chart. SMA calculates the average of a selected range of prices, usually closing prices, by the number of periods in that range. [Investopedia](#https://www.investopedia.com/terms/s/sma.asp)
* -t : Adds Stochastic Oscillator the chart. Stochastic Oscillator is a momentum indicator comparing a particular closing price of a security to a range of its prices over a certain period of time. [Investopedia](#https://www.investopedia.com/terms/s/stochasticoscillator.asp)
* -v : Adds VWAP (Volume Weighted Average Price) to the chart. VWAP gives the average price a security has traded at throughout the day, based on both volume and price. [Investopedia](#https://www.investopedia.com/terms/v/vwap.asp)
## 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

@@ -6,10 +6,6 @@ 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
from gamestonk_terminal.due_diligence import news_view
from gamestonk_terminal.behavioural_analysis import stocktwits_view
from gamestonk_terminal.exploratory_data_analysis import eda_api
import pandas as pd
account = cfg.OANDA_ACCOUNT
@@ -35,10 +31,6 @@ class ForexController:
"candles",
"pending",
"calendar",
"news",
"bullbear",
"messages",
"edasummary",
]
def __init__(self):
@@ -51,31 +43,32 @@ class ForexController:
self.instrument = None
@staticmethod
def print_help():
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(" help show this menu again")
print(" q quit this menu and goes back to main menu")
print(" quit quit to abandon program")
print("")
print(" bullbear Call bullbear from stocktwits")
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(" messages Get messages from stocktwits")
print(" news Get news")
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(" trades List open trades")
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):
@@ -95,7 +88,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"""
@@ -105,24 +98,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"""
@@ -136,13 +129,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"""
@@ -151,36 +144,14 @@ 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"""
fx_view.calendar(self.instrument, other_args)
def call_news(self, other_args: List[str]):
news_view.news(other_args, self.instrument)
def call_bullbear(self, other_args: List[str]):
instrument = remove_underscore(self.instrument)
stocktwits_view.bullbear(other_args, instrument)
def call_messages(self, other_args: List[str]):
instrument = remove_underscore(self.instrument)
stocktwits_view.messages(other_args, instrument)
def call_edasummary(self, other_args: List[str]):
df = pd.read_csv(".candles.csv")
eda_api.summary(other_args, df)
def remove_underscore(instrument):
instrument_list = list(instrument)
instrument_list.pop(3)
adjusted_instrument = "".join(map(str, instrument_list))
return adjusted_instrument
def menu():
"""Oanda Menu"""

View File

@@ -26,7 +26,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)
@@ -35,74 +44,129 @@ 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)
d_error = eval(e.msg)
print(d_error["errorMessage"], "\n")
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)
balance = response["account"]["balance"]
margin_available = response["account"]["marginAvailable"]
margin_closeout = response["account"]["marginCloseoutNAV"]
margin_closeout_percent = response["account"]["marginCloseoutPercent"]
margin_closeout_position_value = response["account"][
"marginCloseoutPositionValue"
]
margin_used = response["account"]["marginUsed"]
net_asset_value = response["account"]["NAV"]
open_trade_count = response["account"]["openTradeCount"]
total_pl = response["account"]["pl"]
unrealized_pl = response["account"]["unrealizedPL"]
print(f"Balance: {balance}")
print(f"NAV: {net_asset_value}")
print(f"Unrealized P/L: {unrealized_pl}")
print(f"Total P/L: {total_pl}")
print(f"Open Trade Count: {open_trade_count}")
print(f"Margin Available: ${margin_available}")
print(f"Margin Used: ${margin_used}")
print(f"Margin Closeout {margin_closeout}")
print(f"Margin Closeout Percent: {margin_closeout_percent}")
print(f"Margin Closeout Position Value: {margin_closeout_position_value}")
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:
print(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="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=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
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:
print(e)
d_error = eval(e.msg)
print(d_error["errorMessage"], "\n")
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:
instrument = format_instrument(instrument, "_")
request = instruments.InstrumentsOrderBook(
instrument=instrument, params=parameters
)
@@ -111,26 +175,42 @@ 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)
d_error = eval(e.msg)
print(d_error["errorMessage"], "\n")
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:
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:
print(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="create_order",
prog="order",
description="Create order",
)
parser.add_argument(
@@ -141,6 +221,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",
@@ -149,6 +231,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)
@@ -168,16 +251,44 @@ def create_order(accountID, instrument, other_args: List[str]):
try:
request = orders.OrderCreate(accountID, data)
response = client.request(request)
print(response)
except V20Error as e:
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="cancelpendingorder",
description="Cancel Pending Order",
prog="cancel",
description="Cancel Pending Order ",
)
parser.add_argument(
"-i",
@@ -185,44 +296,67 @@ 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)
d_error = eval(e.msg)
print(d_error["errorMessage"], "\n")
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)
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
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:
print(e)
d_error = eval(e.msg)
print(d_error["errorMessage"], "\n")
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)
@@ -242,44 +376,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)
d_error = eval(e.msg)
print(d_error["errorMessage"], "\n")
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",
"unrealizedPL": "Unrealized P/L",
}
)
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,63 +442,104 @@ def close_trade(accountID, other_args: List[str]):
dest="orderID",
action="store",
type=str,
required=True,
required=False,
help="The Trade ID to close. ",
)
parser.add_argument(
"-u",
"--units",
dest="units",
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 "-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 = {
"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)
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:
print(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="show_candles",
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 ",
)
parser.add_argument(
"-g",
"--granularity",
dest="granularity",
action="store",
default="D",
)
parser.add_argument("-a", "--ad", dest="ad", action="store_true")
parser.add_argument("-A", "--adx", dest="adx", action="store_true")
parser.add_argument("-b", "--bollinger-bands", dest="bbands", action="store_true")
parser.add_argument("-C", "--cci", dest="cci", action="store_true")
parser.add_argument("-e", "--ema", dest="ema", action="store_true")
parser.add_argument("-f", "--fwma", dest="fwma", action="store_true")
parser.add_argument("-m", "--macd", dest="macd", action="store_true")
parser.add_argument("-o", "--obv", dest="obv", action="store_true")
parser.add_argument("-r", "--rsi", dest="rsi", action="store_true")
parser.add_argument("-R", "--aroon", dest="aroon", action="store_true")
parser.add_argument("-s", "--sma", dest="sma", action="store_true")
parser.add_argument("-S", "--stoch", dest="stoch", action="store_true")
parser.add_argument("-v", "--vwap", dest="vwap", action="store_true")
parser.add_argument("-a", "--ad", dest="ad", action="store_true",
help="Adds ad (Accumulation/Distribution Indicator) to the chart")
parser.add_argument("-A", "--adx", dest="adx", action="store_true",
help="Adds adx (Average Directional Index) the the chart")
parser.add_argument("-b", "--bbands", dest="bbands",
action="store_true", help="Adds Bollinger Bands to the chart")
parser.add_argument("-C", "--cci", dest="cci", action="store_true",
help="Adds cci (Commodity Channel Index) to the chart")
parser.add_argument("-e", "--ema", dest="ema", action="store_true",
help="Adds ema (Exponential Moving Average) to the chart")
parser.add_argument("-m", "--macd", dest="macd", action="store_true",
help="Adds macd (Moving Average Convergence Divergence) to the chart")
parser.add_argument("-o", "--obv", dest="obv", action="store_true",
help="Adds obv (On Balance Volume) to the chart")
parser.add_argument("-r", "--rsi", dest="rsi", action="store_true",
help="Adds rsi (Relative Strength Index) to the chart")
parser.add_argument("-R", "--aroon", dest="aroon", action="store_true",
help="Adds Aroon to the chart.")
parser.add_argument("-s", "--sma", dest="sma", action="store_true",
help="Adds sma (Simple Moving Average) to the chart")
parser.add_argument("-t", "--stoch", dest="stoch", action="store_true",
help="Adds stochastic oscillator to the chart")
parser.add_argument("-v", "--vwap", dest="vwap", action="store_true",
help="Adds vwap (Volume Weighted Average Price) to the chart")
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
@@ -353,120 +549,128 @@ def show_candles(accountID, instrument, other_args: List[str]):
parameters["granularity"] = ns_parser.granularity
parameters["count"] = ns_parser.candlecount
try:
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"]
instrument = format_instrument(instrument, "_")
df = get_candles_dataframe(accountID, instrument, parameters)
plots_to_add = []
if ns_parser.ad:
ad = ta.ad(df["High"], df["Low"], df["Close"], df["Volume"])
ad_plot = mpf.make_addplot(ad, panel=3)
plots_to_add.append(ad_plot)
if ns_parser.adx:
adx = ta.adx(df["High"], df["Low"], df["Close"])
adx_plot = mpf.make_addplot(adx, panel=3)
plots_to_add.append(adx_plot)
if ns_parser.aroon:
aroon = ta.aroon(df["High"], df["Low"])
aroon_plot = mpf.make_addplot(aroon, panel=3)
plots_to_add.append(aroon_plot)
if ns_parser.cci:
cci = ta.cci(df["High"], df["Low"], df["Close"], length=20)
cci_plot = mpf.make_addplot(cci, panel=3)
plots_to_add.append(cci_plot)
if ns_parser.bbands:
bbands = ta.bbands(df["Close"])
bbands = bbands.drop("BBB_5_2.0", axis=1)
bbands_plot = mpf.make_addplot(bbands, panel=0)
plots_to_add.append(bbands_plot)
if ns_parser.ema:
ema = ta.ema(df["Close"])
ema_plot = mpf.make_addplot(ema, panel=0)
plots_to_add.append(ema_plot)
if ns_parser.fwma:
fwma = ta.fwma(df["Close"])
fwma_plot = mpf.make_addplot(fwma, panel=0)
plots_to_add.append(fwma_plot)
if ns_parser.rsi:
rsi = ta.rsi(df["Close"], length=14)
rsi_plot = mpf.make_addplot(rsi, panel=2)
plots_to_add.append(rsi_plot)
if ns_parser.macd:
macd = ta.macd(df["Close"], fast=12, slow=26, signal=9)
macd_plot = mpf.make_addplot(macd, panel=3)
plots_to_add.append(macd_plot)
if ns_parser.obv:
obv = ta.obv(df["Close"], df["Volume"])
obv_plot = mpf.make_addplot(obv, panel=3)
plots_to_add.append(obv_plot)
if ns_parser.sma:
sma = ta.sma(df["Close"])
sma_plot = mpf.make_addplot(sma, panel=0)
plots_to_add.append(sma_plot)
if ns_parser.stoch:
stoch = ta.stoch(df["High"], df["Low"], df["Close"])
stoch_plot = mpf.make_addplot(stoch, panel=0)
plots_to_add.append(stoch_plot)
if ns_parser.vwap:
vwap = ta.vwap(df["High"], df["Low"], df["Close"], df["Volume"])
vwap_plot = mpf.make_addplot(vwap, panel=0)
plots_to_add.append(vwap_plot)
plots_to_add, legends, subplots = add_plots(df, ns_parser)
if gtff.USE_ION:
plt.ion()
mpf.plot(
fig, ax = mpf.plot(
df,
type="candle",
style="charles",
volume=True,
title=f"{instrument} {ns_parser.granularity}",
returnfig=True,
addplot=plots_to_add,
)
except Exception as e:
print(e)
except NameError as e:
ax[0].set_title(f"{instrument} {ns_parser.granularity}")
print(legends)
ax[0].legend(legends)
for i in range(0, len(subplots), 2):
ax[subplots.pop(0)].legend(subplots.pop(0))
print("")
except V20Error as e:
d_error = eval(e.msg)
print(d_error["errorMessage"], "\n")
except TypeError as e:
print(e)
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 add_plots(df, ns_parser):
panel_number = 2
plots_to_add = []
legends = []
subplots = []
if ns_parser.ad:
ad = ta.ad(df["High"], df["Low"], df["Close"], df["Volume"])
ad_plot = mpf.make_addplot(ad, panel=panel_number)
plots_to_add.append(ad_plot)
subplots.extend([panel_number*2, ["AD"]])
panel_number +=1
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:])
if ns_parser.adx:
adx = ta.adx(df["High"], df["Low"], df["Close"])
adx_plot = mpf.make_addplot(adx, panel=panel_number)
plots_to_add.append(adx_plot)
subplots.extend([panel_number*2, ["ADX"]])
panel_number +=1
if ns_parser.aroon:
aroon = ta.aroon(df["High"], df["Low"])
aroon_plot = mpf.make_addplot(aroon, panel=panel_number)
plots_to_add.append(aroon_plot)
subplots.extend([panel_number*2, ["Aroon"]])
panel_number += 1
if ns_parser.bbands:
bbands = ta.bbands(df["Close"])
bbands = bbands.drop("BBB_5_2.0", axis=1)
bbands_plot = mpf.make_addplot(bbands, panel=0)
plots_to_add.append(bbands_plot)
legends.extend(["Lower BBand", "Middle BBand", "Upper BBand"])
if ns_parser.cci:
cci = ta.cci(df["High"], df["Low"], df["Close"])
cci_plot = mpf.make_addplot(cci, panel=panel_number)
plots_to_add.append(cci_plot)
subplots.extend([panel_number*2, ["CCI"]])
panel_number += 1
if ns_parser.ema:
ema = ta.ema(df["Close"])
ema_plot = mpf.make_addplot(ema, panel=0)
plots_to_add.append(ema_plot)
legends.append("20 EMA")
if ns_parser.rsi:
rsi = ta.rsi(df["Close"])
rsi_plot = mpf.make_addplot(rsi, panel=panel_number)
plots_to_add.append(rsi_plot)
subplots.extend([panel_number*2, ["RSI"]])
panel_number += 1
if ns_parser.macd:
macd = ta.macd(df["Close"])
macd_plot = mpf.make_addplot(macd, panel=panel_number)
plots_to_add.append(macd_plot)
subplots.append(panel_number*2)
subplots.append(["Fast","Slow","Signal"])
print(subplots)
panel_number += 1
if ns_parser.obv:
obv = ta.obv(df["Close"], df["Volume"])
obv_plot = mpf.make_addplot(obv, panel=panel_number)
plots_to_add.append(obv_plot)
subplots.extend([panel_number*2, ["OBV"]])
panel_number += 1
if ns_parser.sma:
sma_length = [20,50]
for length in sma_length:
sma = ta.sma(df["Close"], length=length)
sma_plot = mpf.make_addplot(sma, panel=0)
plots_to_add.append(sma_plot)
legends.append(f"{length} SMA")
if ns_parser.stoch:
stoch = ta.stoch(df["High"], df["Low"], df["Close"])
stoch_plot = mpf.make_addplot(stoch, panel=panel_number)
plots_to_add.append(stoch_plot)
subplots.extend([panel_number*2, ["Stoch"]])
panel_number += 1
if ns_parser.vwap:
vwap = ta.vwap(df["High"], df["Low"], df["Close"], df["Volume"])
vwap_plot = mpf.make_addplot(vwap, panel=0)
plots_to_add.append(vwap_plot)
legends.append("vwap")
return plots_to_add, legends, subplots
def calendar(instrument, other_args: List[str]):
@@ -483,6 +687,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:
@@ -492,54 +698,32 @@ def calendar(instrument, other_args: List[str]):
try:
request = labs.Calendar(params=parameters)
response = client.request(request)
l_data = []
for i in range(len(response)):
if "title" in response[i]:
title = response[i]["title"]
print(f"Title: {title}")
if "timestamp" in response[i]:
timestamp = response[i]["timestamp"]
time = datetime.fromtimestamp(timestamp)
print(f"Time: {time}")
if "impact" in response[i]:
impact = response[i]["impact"]
print(f"Impact: {impact}")
if "forecast" in response[i]:
forecast = response[i]["forecast"]
unit = response[i]["unit"]
if unit != "Index":
print(f"Forecast: {forecast}{unit}")
else:
print(f"Forecast: {forecast}")
if response[i]["unit"] != "Index":
forecast += response[i]["unit"]
else:
forecast = ""
if "market" in response[i]:
market = response[i]["market"]
unit = response[i]["unit"]
if unit != "Index":
print(f"Market Forecast: {market}{unit}")
else:
print(f"Market Forecast: {market}")
if "currency" in response[i]:
currency = response[i]["currency"]
print(f"Currency: {currency}")
if "region" in response[i]:
region = response[i]["region"]
print(f"Region: {region}")
if response[i]["unit"] != "Index":
market += response[i]["unit"]
else:
market = ""
if "actual" in response[i]:
actual = response[i]["actual"]
unit = response[i]["unit"]
if unit != "Index":
print(f"Actual: {actual}{unit}")
else:
print(f"Actual: {actual}")
if response[i]["unit"] != "Index":
actual += response[i]["unit"]
else:
actual = ""
if "previous" in response[i]:
previous = response[i]["previous"]
<<<<<<< Updated upstream
unit = response[i]["unit"]
if unit != "Index":
print(f"Previous: {previous}{unit}")
else:
print(f"Previous: {previous}")
print("-" * 30)
=======
if response[i]["unit"] != "Index":
previous += response[i]["unit"]
else:
@@ -550,7 +734,6 @@ def calendar(instrument, other_args: List[str]):
else:
impact = ""
l_data.append(
{
"Title": response[i]["title"],
@@ -568,16 +751,46 @@ def calendar(instrument, other_args: List[str]):
print(pd.DataFrame(l_data).to_string(index=False))
print("")
>>>>>>> Stashed changes
except V20Error as e:
print(e)
d_error = eval(e.msg)
print(d_error["message"], "\n")
def get_candles_dataframe(accountID, instrument, parameters):
if not parameters:
parameters = {
"granularity": "D",
"count": "1500",
}
try:
request = instruments.InstrumentsCandles(instrument, params=parameters)
response = client.request(request)
candles_data=[]
for i in range(len(response["candles"])):
candles_data.append(
{
"Date": response["candles"][i]["time"][:10] + " " + response["candles"][i]["time"][11:19],
"Open": float(response["candles"][i]["mid"]["o"]),
"High": float(response["candles"][i]["mid"]["h"]),
"Low": float(response["candles"][i]["mid"]["l"]),
"Close": float(response["candles"][i]["mid"]["c"]),
"Volume": response["candles"][i]["volume"],
}
)
df = pd.DataFrame(candles_data)
df.set_index("Date", inplace=True)
df.index = pd.to_datetime(df.index)
return df
except V20Error as e:
d_error = eval(e.msg)
print(d_error["errorMessage"], "\n")
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",
)
@@ -587,7 +800,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:
@@ -596,12 +809,15 @@ def load(other_args: List[str]):
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)
print(e, "\n")
return None
def book_plot(df, instrument, book_type):
@@ -643,6 +859,15 @@ def book_plot(df, instrument, book_type):
plt.ion()
plt.show()
def format_instrument(instrument, char):
if char not in instrument:
def format_instrument(instrument, char):
try:
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
except TypeError:
print("Please load an instrument")
print("")