Skip to content

Commit

Permalink
support the 'distance' parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
hootnot committed Jul 7, 2019
1 parent f300734 commit 2ea92ee
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 5 deletions.
21 changes: 18 additions & 3 deletions oandapyV20/contrib/requests/onfill.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ class StopLossDetails(OnFill):
"""

def __init__(self,
price,
price=None,
distance=None,
timeInForce=OD.TimeInForce.GTC,
gtdTime=None,
clientExtensions=None):
Expand All @@ -138,9 +139,12 @@ def __init__(self,
Parameters
----------
price : float or string (required)
price : float or string (either price or distance is required)
the price to trigger take profit order
distance : float or string (either price or distance is required)
the distance to trigger take profit order
timeInForce : TimeInForce (required), default TimeInForce.GTC
the time in force
Expand Down Expand Up @@ -185,7 +189,18 @@ def __init__(self,
timeInForce=timeInForce,
gtdTime=gtdTime,
clientExtensions=clientExtensions)
self._data.update({"price": PriceValue(price).value})

if price is not None and distance is not None:
raise ValueError("price or distance is required")

if price is not None:
self._data.update({"price": PriceValue(price).value})

elif distance is not None:
self._data.update({"distance": PriceValue(distance).value})

else:
raise ValueError("price or distance is required")


class TrailingStopLossDetails(OnFill):
Expand Down
16 changes: 14 additions & 2 deletions oandapyV20/contrib/requests/stoplossorder.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ class StopLossOrderRequest(BaseRequest):

def __init__(self,
tradeID,
price,
price=None,
distance=None,
clientTradeID=None,
timeInForce=TimeInForce.GTC,
gtdTime=None,
Expand Down Expand Up @@ -71,7 +72,18 @@ def __init__(self,

# required
self._data.update({"tradeID": TradeID(tradeID).value})
self._data.update({"price": PriceValue(price).value})

if price is not None and distance is not None:
raise ValueError("price or distance is required")

if price is not None:
self._data.update({"price": PriceValue(price).value})

elif distance is not None:
self._data.update({"distance": str(distance)})

else:
raise ValueError("price or distance is required")

# optional
self._data.update({"clientExtensions": clientExtensions})
Expand Down
54 changes: 54 additions & 0 deletions tests/test_contrib_orders.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,33 @@ class TestContribRequests(unittest.TestCase):
'type': 'STOP_LOSS'},
ValueError
),
# SLO: distance instead of price
(req.StopLossOrderRequest,
{"tradeID": "1234",
"timeInForce": "GTC",
"distance": 50},
{'timeInForce': 'GTC',
'type': 'STOP_LOSS',
'distance': '50'},
),
# ... no price and no distance, should raise a ValueError
(req.StopLossOrderRequest,
{"tradeID": "1234"},
{'timeInForce': 'GTC',
'type': 'STOP_LOSS'},
ValueError
),
# ... price and distance, should raise a ValueError
(req.StopLossOrderRequest,
{"tradeID": "1234",
"price": 1.10,
"distance": 40},
{'timeInForce': 'GTC',
'price': 1.10,
'distance': 40,
'type': 'STOP_LOSS'},
ValueError
),
# ... FOK, should raise a ValueError
(req.StopLossOrderRequest,
{"tradeID": "1234",
Expand Down Expand Up @@ -239,6 +266,9 @@ def test__orders(self, cls, inpar, refpar, exc=None):

if not exc:
r = cls(**inpar)
print("*************")
print(r.data)
print(refpar)
self.assertTrue(r.data == reference)
else:
with self.assertRaises(exc):
Expand Down Expand Up @@ -318,6 +348,27 @@ def test__orders(self, cls, inpar, refpar, exc=None):
{'timeInForce': 'GTC',
'price': '1.10000'}
),
# ... distance instead of price
(req.StopLossDetails,
{"distance": 40},
{'timeInForce': 'GTC',
'distance': '40.00000'}
),
# .. raises ValueError because price and distance
(req.StopLossDetails,
{"distance": 40,
"price": 1.10},
{'timeInForce': 'GTC',
'price': '1.10000',
'distance': '40.00000'},
ValueError
),
# .. raises ValueError because no price and no distance
(req.StopLossDetails,
{"timeInForce": OD.TimeInForce.GTC},
{'timeInForce': 'GTC'},
ValueError
),
# .. raises ValueError because GTD required gtdTime
(req.StopLossDetails,
{"price": 1.10,
Expand Down Expand Up @@ -380,6 +431,9 @@ def test__anonymous_body(self, cls, inpar, refpar, exc=None):

if not exc:
r = cls(**inpar) if inpar else cls()
print("*************")
print(r.data)
print(refpar)
self.assertTrue(r.data == refpar)
else:
with self.assertRaises(exc):
Expand Down

0 comments on commit 2ea92ee

Please sign in to comment.