hootnot / oanda-api-v20

OANDA REST-V20 API wrapper. Easy access to OANDA's REST v20 API with oandapyV20 package. Checkout the Jupyter notebooks!
MIT License
402 stars 107 forks source link

Allow floats as unit size instead of integers #187

Closed sword134 closed 3 years ago

sword134 commented 3 years ago

Currently, you can only input integers on orders even though oanda actually allows you to trade smaller sizes. I have adjusted the unit size to 0.1 but this yields an UNITS_INVALID error.

Bear in mind that everything works perfectly as soon as the unit size is set to 1 instead of 0.1.

The following is an extract from the JSON message when inputting 0.1 in the unit size. There is no reason for this to be fixed as an integer "rejectReason":"UNITS_INVALID","reason":"CLIENT_ORDER"},"relatedTransactionIDs":["546"],"lastTransactionID":"546","errorMessage":"Order units specified are invalid","errorCode":"UNITS_INVALID"}

hootnot commented 3 years ago

The fractional units only apply for some instruments:

One other thing: you get the error from OANDA, not from the oandapyV20 wrapper. So, it definitely is the instrument where you apply a fractional unit for which it is not supported.

sword134 commented 3 years ago

The fractional units only apply for some instruments:

  • EUR_EU50 index (0.1)
  • BTC_USD (0.01)

One other thing: you get the error from OANDA, not from the oandapyV20 wrapper. So, it definitely is the instrument where you apply a fractional unit for which it is not supported.

This applies for the DAX and DOW as well. I manually edited the stoporder.py function to not convert the units into a integer. It works flawlessly now, there is simply no reason to force people to use an integer when floats works with oanda.

hootnot commented 3 years ago

If you use the latest version (0.7.2), you will have the Units type adapted for these fractions.

OANDA uses string representations (https://developer.oanda.com/rest-live-v20/primitives-df/#DecimalNumber) for int's and floats representing the units.

>>> import oandapyV20.contrib.requests as rq
>>> import oandapyV20.types as tp
>>> num = tp.Units('10.25').value
>>> num
'10.25'
>>> so = rq.StopOrderRequest('SOME_INSTR', num, 100.1)
>>> print(json.dumps(so.data, indent=2))
{
  "order": {
    "type": "STOP",
    "instrument": "SOME_INSTR",
    "units": "10.25",
    "price": "100.10000",
    "timeInForce": "GTC",
    "positionFill": "DEFAULT"
  }
}

...but ... I will change the documentation of StopOrderRequest (and possible others) to reflect the use of fractional units also.