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
398 stars 107 forks source link

Examples for limit orders with GTD? #93

Closed mullenba closed 7 years ago

mullenba commented 7 years ago

I'm trying to figure out limit orders with take profit and time limits. Here's an example of my code:

     lmtOrder = LimitOrderRequest(
                            instrument = "USD_CHR",
                            units = 100,
                            price = 1.234,
                            takeProfitOnFill = TakeProfitDetails(price=1.345).data,
                            timeInForce = "GTD"
                            )

I'm not sure where/how to put the time in for the GTD portion of the limit order. I don't see anything called out in the docs.

Here's the error I get.

oandapyV20.exceptions.V20Error:
 {"orderRejectTransaction": {
    "type":"LIMIT_ORDER_REJECT",
    "instrument":"USD_CHF",
    "units":"828",
    "price":"0.97325",
    "timeInForce":"GTD",
    "triggerCondition":"DEFAULT",
    "partialFill":"DEFAULT",
    "positionFill":"DEFAULT",
    "takeProfitOnFill":    {
        "price":"0.97525",
        "timeInForce":"GTC"},
    "reason":"CLIENT_ORDER",
    "rejectReason":"TIME_IN_FORCE_GTD_TIMESTAMP_MISSING",
    "id":"15513",
    "userID":1485009,
    "accountID":"001-001-1485009-001",
    "batchID":"15513",
    "requestID":"24314887390732863",
    "time":"2017-08-08T00:53:26.992772654Z"},
"relatedTransactionIDs":["15513"],"lastTransactionID":"15513",

"errorMessage":"The TimeInForce is GTD but no GTD timestamp is provided","errorCode":"TIME_IN_FORCE_GTD_TIMESTAMP_MISSING"}

Thanks!

mullenba commented 7 years ago

So I changed some code... I'm not very knowledgeable about GIT pulls and such, so I'll include my changes here if it helps.

From the Oanda docs, it appears that the gtdTime field was missing from the limit orders when a GTD order is used. So I made the following changes to the init function of the LimitOrderRequest class in requests/limitorder.py (I'm removing the big comment block for clarity.)

class LimitOrderRequest(BaseRequest):
    """create a LimitOrderRequest.

    LimitOrderRequest is used to build the body for a LimitOrder.
    The body can be used to pass to the OrderCreate endpoint.
    """

    def __init__(self,
                 instrument,
                 units,
                 price,
                 positionFill=OrderPositionFill.DEFAULT,
                 clientExtensions=None,
                 takeProfitOnFill=None,
                 timeInForce=TimeInForce.GTC,
                 gtdTime = None,  # inserting missing field for GTD trades
                 stopLossOnFill=None,
                 trailingStopLossOnFill=None,
                 tradeClientExtensions=None):

        super(LimitOrderRequest, self).__init__()

        # by default for a LIMIT order
        self._data.update({"type": OrderType.LIMIT})
        self._data.update({"timeInForce": timeInForce})

        # required
        self._data.update({"instrument": instrument})
        self._data.update({"units": Units(units).value})
        self._data.update({"price": PriceValue(price).value})

        # Only if GTD
        if timeInForce == 'GTD':
            self._data.update({"gtdTime": gtdTime})

        # optional
        self._data.update({"positionFill": positionFill})
        self._data.update({"clientExtensions": clientExtensions})
        self._data.update({"takeProfitOnFill": takeProfitOnFill})
        self._data.update({"stopLossOnFill": stopLossOnFill})
        self._data.update({"trailingStopLossOnFill": trailingStopLossOnFill})
        self._data.update({"tradeClientExtensions": tradeClientExtensions})

Also, the time value provided to gtdDate needs to be UTC. I used the following code:

from oandapyV20.types import DateTime
gtdTime = DateTime(datetime.utcnow() + timedelta(seconds = 30*60)).value

Hope this helps! Your stuff is great!

hootnot commented 7 years ago

Hi, I'm a bit limited available (holiday) , but it seems you found a missing parameter, gtdTime. Will come back to it.

hootnot commented 7 years ago

@mullenba fixed this one. Thanks!