@Artic The basic issue (as you noticed) is one cannot really know the entry price of the original parent order. However, you can make an educated guess.
If the initial parent order is a limit order, it will typically fill at the limit price. Use the limit price as the entry price.
If the initial parent order is a market order, it will typically fill at the quote price (the ask price for buy orders and the bid price for sell orders). Use the quote price as the entry price.
There are really just two order ‘timeouts’ or Time-In-Force values you can use. Day or Good-Till-Cancelled (GTC). There is info in the docs here. You can also cancel the order at any time using the cancel_order_by_id method.
Here is an example of placing a limit and market order
!pip install -q alpaca-py
from alpaca.trading.client import TradingClient
from alpaca.trading.requests import MarketOrderRequest, LimitOrderRequest, StopLossRequest, TakeProfitRequest
from alpaca.trading.enums import OrderSide, OrderClass, TimeInForce
from alpaca.data import StockHistoricalDataClient
from alpaca.data.requests import StockLatestQuoteRequest
API_KEY = 'xxxxx'
SECRET_KEY = 'xxxxx'
client = TradingClient(api_key=API_KEY, secret_key=SECRET_KEY)
# Bracket order with limit order as initial 'parent' order
symbol = 'VXX'
limit_price = 11.00
limit_bracket_order = client.submit_order(LimitOrderRequest(
order_class = OrderClass.BRACKET,
time_in_force=TimeInForce.DAY,
symbol=symbol,
qty=1,
side=OrderSide.BUY,
limit_price=limit_price,
stop_loss=StopLossRequest(stop_price=limit_price-1.00),
take_profit=TakeProfitRequest(limit_price=limit_price+1.00)
))
# Bracket order with market order as initial 'parent' order
symbol = 'VXX'
latest_quote = client.get_stock_latest_quote(StockLatestQuoteRequest(symbol_or_symbols=symbol))
expected_entry_price = latest_quote[symbol].ask_price
market_bracket_order = client.submit_order(MarketOrderRequest(
order_class = OrderClass.BRACKET,
time_in_force=TimeInForce.DAY,
symbol=symbol,
qty=1,
side=OrderSide.BUY,
stop_loss=StopLossRequest(stop_price=expected_entry_price-1.00),
take_profit=TakeProfitRequest(limit_price=expected_entry_price+1.00)
))
One thing to note is you need to have access to real time full market SIP data to fetch actual quotes. If you are only using the free Basic Market Data, the latest_quote
will only reflect quotes on the IEX exchange and will generally NOT be what your order will fill at.
If you want to be exact about the stop and take-profit limit prices, you can 1) fetch the actual filled price once the parent order fills and 2) replace the stop and take-profit limit prices based on that actual entry price.