-
Notifications
You must be signed in to change notification settings - Fork 47
/
Copy pathoanda_api_helpers.py
159 lines (133 loc) · 5.69 KB
/
oanda_api_helpers.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
"""
This is where all the code related to interacting with oanda is stored.
Sources:
https://media.readthedocs.org/pdf/oanda-api-v20/latest/oanda-api-v20.pdf
https://github.com/hootnot/oanda-api-v20
"""
import oandapyV20
import oandapyV20.endpoints.orders as orders
import oandapyV20.endpoints.trades as trades
import oandapyV20.endpoints.accounts as accounts
import oandapyV20.endpoints.positions as positions
from oandapyV20.contrib.requests import MarketOrderRequest
import json
# TODO: make sure send_request checks if order is through on weekends and no order_book is created
class TradingSession:
# initiate objects
def __init__(self, accountID, access_token):
self.accountID = accountID
self.access_token = access_token
self.api = oandapyV20.API(access_token=access_token, environment="practice")
self.order_book = self.oanda_order_book()
# initiate methods
def send_request(self, request):
"""
Sends request to oanda API.
Returns oanda's response if success, 1 if error.
"""
try:
rv = self.api.request(request)
# print(json.dumps(rv, indent=2))
return rv
except oandapyV20.exceptions.V20Error as err:
print(request.status_code, err)
return 1
def open_order(self, instrument, units):
# check if position is already open
if units < 0:
if self.order_book[instrument]['order_type'] is (not None and -1):
print('Short: {} (holding)'.format(instrument))
return 1
elif units > 0:
if self.order_book[instrument]['order_type'] is (not None and 1):
print('Long: {} (holding)'.format(instrument))
return 1
else:
print('Units specified: 0')
return 1
# define parameters, create and send a request
mkt_order = MarketOrderRequest(instrument=instrument, units=units)
r = orders.OrderCreate(self.accountID, data=mkt_order.data)
request_data = self.send_request(r)
# check if request was fulfilled and save its ID
if request_data is not 1:
instrument = request_data['orderCreateTransaction']['instrument']
self.order_book[instrument]['tradeID'] = request_data['lastTransactionID']
self.order_book[instrument]['order_type'] = -1 if units < 0 else 1
print('{}: {}'.format('Long' if units > 0 else 'Short', instrument))
return 0
else:
return 1
def close_order(self, instrument):
# check if position exist
if self.order_book[instrument]['order_type'] is None:
print('Position {} does not exist'.format(instrument))
return 1
# create and send a request
r = trades.TradeClose(accountID=self.accountID, tradeID=self.order_book[instrument]['tradeID'])
request_data = self.send_request(r)
# check if request was fulfilled and clear it
if request_data is not 1:
instrument = request_data['orderCreateTransaction']['instrument']
self.order_book[instrument]['order_type'] = None
self.order_book[instrument]['tradeID'] = None
print('Closed: {}'.format(instrument))
return 0
else:
return 1
def check_open_positions(self):
r = positions.OpenPositions(self.accountID)
return self.send_request(r)
def check_account_summary(self):
r = accounts.AccountSummary(self.accountID)
return self.send_request(r)
def oanda_order_book(self):
"""Synchronize open positions with this object's order_book"""
order_book_oanda = self.check_open_positions()
order_book = {'EUR_USD': {'order_type': None, 'tradeID': None},
'AUD_JPY': {'order_type': None, 'tradeID': None}}
for pos in order_book_oanda['positions']:
try:
trade_id = pos['long']['tradeIDs']
order_type = 1
except KeyError:
trade_id = pos['short']['tradeIDs']
order_type = -1
order_book[pos['instrument']]['tradeID'] = trade_id
order_book[pos['instrument']]['order_type'] = order_type
return order_book
def sync_with_oanda(self):
self.order_book = self.oanda_order_book()
def close_all_open_positions(self):
"""Close all opened positions"""
# check oanda for open positions
try:
open_positions = self.check_open_positions()['positions'][0]
except IndexError:
self.order_book = self.oanda_order_book()
print('No opened positions')
return 0
# get ID's of open positions
trade_ids = []
try:
[trade_ids.append(x) for x in open_positions['short']['tradeIDs']]
except KeyError:
pass
try:
[trade_ids.append(x) for x in open_positions['long']['tradeIDs']]
except KeyError:
pass
# close orders by ID
[close_order_manually(self.accountID, self.access_token, x) for x in trade_ids]
self.order_book = self.oanda_order_book()
print('All positions closed')
return 0
def close_order_manually(accountID, access_token, tradeID):
"""
Closes order manually using tradeID.
"""
api = oandapyV20.API(access_token=access_token, environment="practice")
request = trades.TradeClose(accountID, tradeID)
rv = api.request(request)
print(json.dumps(rv, indent=2))
return 0