From 85c0d763c2a5fd7183ba8c2e169414c100033254 Mon Sep 17 00:00:00 2001 From: sai-g Date: Wed, 12 Feb 2025 08:13:02 -0500 Subject: [PATCH 1/2] Make position_intent optional in PlaceOrderRequest --- alpaca/rest.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/alpaca/rest.go b/alpaca/rest.go index 688677d..e169967 100644 --- a/alpaca/rest.go +++ b/alpaca/rest.go @@ -558,7 +558,7 @@ type PlaceOrderRequest struct { StopLoss *StopLoss `json:"stop_loss"` TrailPrice *decimal.Decimal `json:"trail_price"` TrailPercent *decimal.Decimal `json:"trail_percent"` - PositionIntent PositionIntent `json:"position_intent"` + PositionIntent *PositionIntent `json:"position_intent"` Legs []Leg `json:"legs"` // mleg order legs } From 354e993b9d89b040997b65b8dd69c767636bb428 Mon Sep 17 00:00:00 2001 From: sai-g Date: Wed, 19 Feb 2025 14:00:47 -0500 Subject: [PATCH 2/2] address pr suggestion(s) --- alpaca/rest.go | 2 +- alpaca/rest_test.go | 44 +++++++++++++++++++++++++++++++++++++------- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/alpaca/rest.go b/alpaca/rest.go index e169967..fc58f50 100644 --- a/alpaca/rest.go +++ b/alpaca/rest.go @@ -558,7 +558,7 @@ type PlaceOrderRequest struct { StopLoss *StopLoss `json:"stop_loss"` TrailPrice *decimal.Decimal `json:"trail_price"` TrailPercent *decimal.Decimal `json:"trail_percent"` - PositionIntent *PositionIntent `json:"position_intent"` + PositionIntent PositionIntent `json:"position_intent,omitempty"` Legs []Leg `json:"legs"` // mleg order legs } diff --git a/alpaca/rest_test.go b/alpaca/rest_test.go index ad1c5ce..b71642c 100644 --- a/alpaca/rest_test.go +++ b/alpaca/rest_test.go @@ -392,14 +392,25 @@ func TestPlaceOrder(t *testing.T) { if err := json.NewDecoder(req.Body).Decode(&por); err != nil { return nil, err } + order := Order{ + Qty: por.Qty, + Notional: por.Notional, + Side: por.Side, + TimeInForce: por.TimeInForce, + Type: por.Type, + } + if por.PositionIntent != "" { + order.PositionIntent = por.PositionIntent + } else { + // default to BuyToOpen/SellToOpen if not specified (for testing) + if por.Side == Buy { + order.PositionIntent = BuyToOpen + } else { + order.PositionIntent = SellToOpen + } + } return &http.Response{ - Body: genBody(Order{ - Qty: por.Qty, - Notional: por.Notional, - Side: por.Side, - TimeInForce: por.TimeInForce, - Type: por.Type, - }), + Body: genBody(order), }, nil } @@ -418,6 +429,7 @@ func TestPlaceOrder(t *testing.T) { assert.Nil(t, req.Notional) assert.Nil(t, order.Notional) assert.Equal(t, req.Type, order.Type) + assert.Equal(t, BuyToOpen, order.PositionIntent) // successful (w/ Notional) req = PlaceOrderRequest{ @@ -434,6 +446,24 @@ func TestPlaceOrder(t *testing.T) { assert.Nil(t, req.Qty) assert.Nil(t, order.Qty) assert.Equal(t, req.Type, order.Type) + assert.Equal(t, BuyToOpen, order.PositionIntent) + + // successful (w/ Qty,PositionIntent) + req = PlaceOrderRequest{ + Qty: &one, + Side: Sell, + TimeInForce: GTC, + Type: Limit, + PositionIntent: SellToClose, + } + + order, err = c.PlaceOrder(req) + require.NoError(t, err) + assert.NotNil(t, order) + assert.NotNil(t, req.Qty) + assert.NotNil(t, order.Qty) + assert.Equal(t, req.Type, order.Type) + assert.Equal(t, SellToClose, order.PositionIntent) // api failure c.do = func(_ *Client, _ *http.Request) (*http.Response, error) {