2022-10-30 10:57:53 +00:00
|
|
|
from oandapyV20 import API
|
2022-10-30 11:21:48 +00:00
|
|
|
from oandapyV20.endpoints import accounts, orders, positions, trades
|
2022-11-02 18:25:34 +00:00
|
|
|
from pydantic import ValidationError
|
2022-10-30 11:21:48 +00:00
|
|
|
|
|
|
|
from core.exchanges import BaseExchange
|
2022-10-30 19:11:07 +00:00
|
|
|
from core.lib.schemas import oanda_s
|
|
|
|
|
2022-10-31 08:58:08 +00:00
|
|
|
OANDA_SCHEMA_MAPPING = {"OpenPositions": oanda_s.OpenPositions}
|
2022-10-30 11:21:48 +00:00
|
|
|
|
2022-10-30 10:57:53 +00:00
|
|
|
|
|
|
|
class OANDAExchange(BaseExchange):
|
2022-10-31 08:58:08 +00:00
|
|
|
def call(self, method, request):
|
|
|
|
self.client.request(request)
|
|
|
|
response = request.response
|
|
|
|
if isinstance(response, list):
|
|
|
|
response = {"itemlist": response}
|
|
|
|
if method not in self.schema:
|
|
|
|
self.log.error(f"Method cannot be validated: {method}")
|
|
|
|
self.log.debug(f"Response: {response}")
|
|
|
|
return (False, f"Method cannot be validated: {method}")
|
|
|
|
try:
|
2022-11-02 18:25:34 +00:00
|
|
|
# Return a dict of the validated response
|
|
|
|
response_valid = self.schema[method](**response).dict()
|
|
|
|
# Convert the response to a format that we can use
|
|
|
|
response_converted = self.convert_spec(response_valid, method)
|
|
|
|
return (True, response_converted)
|
2022-10-31 08:58:08 +00:00
|
|
|
except ValidationError as e:
|
|
|
|
self.log.error(f"Could not validate response: {e}")
|
|
|
|
return (False, e)
|
|
|
|
|
2022-10-30 19:11:07 +00:00
|
|
|
def set_schema(self):
|
|
|
|
self.schema = OANDA_SCHEMA_MAPPING
|
|
|
|
|
2022-10-30 10:57:53 +00:00
|
|
|
def connect(self):
|
|
|
|
self.client = API(access_token=self.account.api_secret)
|
|
|
|
self.account_id = self.account.api_key
|
|
|
|
|
2022-10-30 11:21:48 +00:00
|
|
|
def get_account(self):
|
|
|
|
r = accounts.AccountDetails(self.account_id)
|
|
|
|
self.client.request(r)
|
|
|
|
return r.response
|
|
|
|
|
2022-10-30 10:57:53 +00:00
|
|
|
def get_supported_assets(self):
|
2022-10-30 11:21:48 +00:00
|
|
|
return False
|
2022-10-30 10:57:53 +00:00
|
|
|
|
|
|
|
def get_balance(self):
|
|
|
|
raise NotImplementedError
|
|
|
|
|
|
|
|
def get_market_value(self, symbol):
|
|
|
|
raise NotImplementedError
|
|
|
|
|
|
|
|
def post_trade(self, trade):
|
|
|
|
raise NotImplementedError
|
2022-10-30 11:21:48 +00:00
|
|
|
r = orders.OrderCreate(accountID, data=data)
|
|
|
|
self.client.request(r)
|
|
|
|
return r.response
|
2022-10-30 10:57:53 +00:00
|
|
|
|
|
|
|
def get_trade(self, trade_id):
|
2022-10-30 11:21:48 +00:00
|
|
|
r = accounts.TradeDetails(accountID=self.account_id, tradeID=trade_id)
|
|
|
|
self.client.request(r)
|
|
|
|
return r.response
|
2022-10-30 10:57:53 +00:00
|
|
|
|
|
|
|
def update_trade(self, trade):
|
|
|
|
raise NotImplementedError
|
2022-10-30 11:21:48 +00:00
|
|
|
r = orders.OrderReplace(
|
|
|
|
accountID=self.account_id, orderID=trade.order_id, data=data
|
|
|
|
)
|
|
|
|
self.client.request(r)
|
|
|
|
return r.response
|
2022-10-30 10:57:53 +00:00
|
|
|
|
|
|
|
def cancel_trade(self, trade_id):
|
|
|
|
raise NotImplementedError
|
|
|
|
|
2022-11-02 18:25:34 +00:00
|
|
|
def get_position_info(self, symbol):
|
|
|
|
r = positions.PositionDetails(self.account_id, symbol)
|
2022-10-30 11:21:48 +00:00
|
|
|
self.client.request(r)
|
|
|
|
return r.response
|
2022-10-30 10:57:53 +00:00
|
|
|
|
|
|
|
def get_all_positions(self):
|
2022-11-02 18:25:34 +00:00
|
|
|
items = []
|
2022-10-30 11:21:48 +00:00
|
|
|
r = positions.OpenPositions(accountID=self.account_id)
|
2022-10-31 08:58:08 +00:00
|
|
|
success, response = self.call("OpenPositions", r)
|
|
|
|
if not success:
|
|
|
|
return (success, response)
|
|
|
|
|
|
|
|
print("Positions", response)
|
2022-11-02 18:25:34 +00:00
|
|
|
for item in response["itemlist"]:
|
2022-11-02 18:28:31 +00:00
|
|
|
item["account"] = self.account.name
|
2022-11-02 19:04:05 +00:00
|
|
|
item["account_id"] = self.account.id
|
2022-11-02 18:25:34 +00:00
|
|
|
item["unrealized_pl"] = float(item["unrealized_pl"])
|
|
|
|
items.append(item)
|
|
|
|
return (True, items)
|