oanda / oandapy

Python wrapper for the OANDA REST API
MIT License
321 stars 147 forks source link

OANDA API returned error code 0 (INTERNAL_SERVER_ERROR) #40

Closed houmie closed 7 years ago

houmie commented 7 years ago

Hey guys,

Just wondering if you are aware that this wrapper doesn't work with the latest API version. Considering all new signup demo accounts utilise the new API version, that's bad news.

This happens when I do a create_order:

trade_id = oanda.create_order(OANDA_ACCOUNT_ID, instrument="EUR_USD",
                                  units=1000,
                                  side='buy',
                                  type='market', price=1)

Traceback:

------ System online ------- 2016-11-24 01:24:19.212130
Buy at 1.05493
Traceback (most recent call last):
  File "/Users/houmie/projects/forex_algotrading/post3/runner.py", line 30, in <module>
    main()
  File "/Users/houmie/projects/forex_algotrading/post3/runner.py", line 24, in main
    type='market', price=1)
  File "/Users/houmie/.pyenv/versions/venv2712/lib/python2.7/site-packages/oandapy/oandapy.py", line 77, in create_order
    return self.request(endpoint, "POST", params=params)
  File "/Users/houmie/.pyenv/versions/venv2712/lib/python2.7/site-packages/oandapy/oandapy.py", line 284, in request
    raise OandaError(content)
oandapy.exceptions.OandaError: OANDA API returned error code 0 (INTERNAL_SERVER_ERROR) 
ronensingerr commented 7 years ago

​You forgot to put your account_id It should be:

​trade_id = oanda.create_order(account_id=OANDA_ACCOUNT_ID, instrument="EUR_USD",

                              units=1000,
                              side='buy',
                              type='market', price=1)

​Let me know if that works​

On Wed, Nov 23, 2016 at 5:17 PM, Houman Khorasani notifications@github.com wrote:

Hey guys,

Just wondering if you are aware that this wrapper doesn't work with the latest API version. Considering all new signup demo accounts utilise the new API version, that's bad news.

This happens when I do a create_order:

trade_id = oanda.create_order(OANDA_ACCOUNT_ID, instrument="EUR_USD", units=1000, side='buy', type='market', price=1)

Traceback:

------ System online ------- 2016-11-24 01:24:19.212130 Buy at 1.05493 Traceback (most recent call last): File "/Users/houmie/projects/forex_algotrading/post3/runner.py", line 30, in main() File "/Users/houmie/projects/forex_algotrading/post3/runner.py", line 24, in main type='market', price=1) File "/Users/houmie/.pyenv/versions/venv2712/lib/python2.7/site-packages/oandapy/oandapy.py", line 77, in create_order return self.request(endpoint, "POST", params=params) File "/Users/houmie/.pyenv/versions/venv2712/lib/python2.7/site-packages/oandapy/oandapy.py", line 284, in request raise OandaError(content) oandapy.exceptions.OandaError: OANDA API returned error code 0 (INTERNAL_SERVER_ERROR)

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/oanda/oandapy/issues/40, or mute the thread https://github.com/notifications/unsubscribe-auth/AJDXz3YTqAInKtU6zv6NM5hNOhEgCZjOks5rBLt7gaJpZM4K7GUs .

houmie commented 7 years ago

Account_id is the first param anyway:

def create_order(self, account_id, **params):
        """ Create a new order
        Docs: http://developer.oanda.com/rest-live/orders
        """
        endpoint = 'v1/accounts/%s/orders' % (account_id)
        return self.request(endpoint, "POST", params=params)

But even doing it nonetheless oanda.create_order(account_id=OANDA_ACCOUNT_ID, it still won't work. Crashes with 500 error. :(

Thanks,

hootnot commented 7 years ago

You are placing a market order with a price (that is not a valid combination)

didn't check it, but I guess that is it

houmie commented 7 years ago

I changed it as you say and still the same error:

trade_id = oanda.create_order(account_id=OANDA_ACCOUNT_ID, instrument="EUR_USD",
                                  units=1000,
                                  side='buy',
                                  type='market')

The issue is that the underlying API has changed for new accounts. Your test account is still using the old API, hence when you use this wrapper with your old account credentials it still works. Create a new practice account and see it for yourself. :)

hootnot commented 7 years ago

Reading the first lines of your issue I guess you have a v20 account ... So you will need to use the REST-V20 interface. If so, the oandapy wrapper will not work for you. But you can use the oandapyV20 wrapper (and v20 and possible other options):


pip install oandapyV20

I have no problems placing an order on either account.

client = oandapy.API(access_token=t)
r = client.create_order(account_id=accountID, instrument="EUR_USD",
             units=1000, side="buy", type="market")

print r
{u'price': 1.05617, u'tradeReduced': {}, u'instrument': u'EUR_USD', u'tradesClosed': [], u'time': u'2016-11-24T09:07:59.000000Z', u'tradeOpened': {u'stopLoss': 0, u'takeProfit': 0, u'side': u'buy', u'trailingStop': 0, u'units': 1000, u'id': 10530344175}}

Using the V20 wrapper:


import json
from oandapyV20.contrib.requests import MarketOrderRequest
import oandapyV20.endpoints.orders as orders
import oandapyV20

accountID, access_token = ...
api = oandapyV20.API(access_token=access_token)

r = orders.OrderCreate(
        accountID,
        data=MarketOrderRequest(instrument="EUR_USD", units=1000).data)
rv = api.request(r)
print json.dumps(rv, indent=2)

{
  "orderFillTransaction": {
    "orderID": "2641", 
    "financing": "0.0000", 
    "instrument": "EUR_USD", 
    "price": "1.05702", 
    "userID": 1435156, 
    "batchID": "2641", 
    "accountBalance": "97813.9246", 
    "reason": "MARKET_ORDER", 
    "tradeOpened": {
      "units": "1000", 
      "tradeID": "2642"
    }, 
    "time": "2016-11-24T09:18:59.284674918Z", 
    "units": "1000", 
    "type": "ORDER_FILL", 
    "id": "2642", 
    "pl": "0.0000", 
    "accountID": "101-004-1435156-001"
  }, 
  "orderCreateTransaction": {
    "timeInForce": "FOK", 
    "positionFill": "DEFAULT", 
    "userID": 1435156, 
    "batchID": "2641", 
    "instrument": "EUR_USD", 
    "reason": "CLIENT_ORDER", 
    "time": "2016-11-24T09:18:59.284674918Z", 
    "units": "1000", 
    "type": "MARKET_ORDER", 
    "id": "2641", 
    "accountID": "101-004-1435156-001"
  }, 
  "relatedTransactionIDs": [
    "2641", 
    "2642"
  ], 
  "lastTransactionID": "2642"
}

There are different account ID's. If you use the oandapy API-wrapper you need to use the v1 account, which is 7 digits. If you want to use the rest-v20 interface, you need to use the rest-v20 account which is of format: ddd-ddd-ddddddd-ddd.

The only issue I've had several months ago was that I had to get a new token after applying for a v20-account. The new token worked on both accounts . The old did not.

houmie commented 7 years ago

Many Thanks for the update.

I can confirm your code for v2.0 wrapper works. But it's drastically different than v1.0. Compare order creation between the two, very different classes.

However, your V1.0 snippet doesn't work with my ddd-ddd-ddddddd-ddd account ID format. I get this exception:

oandapy.exceptions.OandaError: OANDA API returned error code 52 (Invalid or malformed resource identifier: accountId) 
dmpettyp commented 7 years ago

Hootnot is correct, the library found in this repo does not work with v20 accounts, as it only works with legacy accounts through the /v1 API.

v20 Accounts are accessible through the /v3 API, and can use the wrapper library found at https://github.com/oanda/v20-python

houmie commented 7 years ago

v2.0 accounts work also with oandapyV20, it seems. Thanks for pointing out the other wrapper as well.

hootnot commented 7 years ago

... I'm the author of oandapyV20, so that was easy. But there are other options too. I'm not familliar with those. The different wrappers have their own approach how to cover the specs.

oandapyV20 has different layers:

REST V20 offers a lot more compared to the legacy v1 REST. But the specs are also more complex. Therefore the simple passing of parameters for an order ends up easily in errors. To take that away the oandapyV20.contrib offfers classes to construct the data.

So your example could also have been written as:

r = orders.OrderCreate(
        accountID,
        data={'order': {'timeInForce': 'FOK', 'instrument': 'EUR_USD', 'positionFill': 'DEFAULT', 'units': '1000', 'type': 'MARKET'}}
rv = api.request(r)

I prefer:

r = orders.OrderCreate(
        accountID,
        data=MarketOrderRequest(instrument="EUR_USD", units=1000).data)

Good Luck!

houmie commented 7 years ago

Thank you.