From ba9d46a19d6e32f114fb21c21199730a32b4a64b Mon Sep 17 00:00:00 2001 From: Joshua Harrison Date: Tue, 26 Apr 2022 15:10:00 +0000 Subject: [PATCH] Add the ability to create more bracket order types This change adds support for specifying more bracket order types to the program. Specifically, we recognize two new optional arguments for the order submit sub-command: --stop-loss-stop-price and --stop-loss-limit-price. If only --stop-loss-stop-price is provided, we create a one-triggers-other order with a stop loss (as opposed to a take profit, which we already support). If both the existing --take-profit-price and --stop-loss-stop-price are given, we will submit a "true" bracket order with both a take profit and a stop loss leg. Lastly, if --stop-loss-limit-price is specified additionally, the stop loss leg will actually be a stop-limit order (as opposed to a regular stop market order). --- CHANGELOG.md | 5 +++++ src/args.rs | 12 +++++++++++- src/main.rs | 21 ++++++++++++++++++++- 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cc0a4f..630bdba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +Unreleased +---------- +- Added support for submission of more kinds of bracket orders + + 0.1.5 ----- - Added support for historic aggregate bar retrieval via `bars` diff --git a/src/args.rs b/src/args.rs index bf40739..2cadad6 100644 --- a/src/args.rs +++ b/src/args.rs @@ -332,9 +332,19 @@ pub struct SubmitOrder { /// Create a stop order (or stop limit order) with the given stop price. #[structopt(short = "s", long)] pub stop_price: Option, - /// Create a one-triggers-other order with the given take-profit price. + /// Create a one-triggers-other or bracket order with the given + /// take-profit price. #[structopt(long)] pub take_profit_price: Option, + /// Create a one-triggers-other or bracket order with the given + /// stop-price under the stop-loss advanced order leg. + #[structopt(long)] + pub stop_loss_stop_price: Option, + /// Create a one-triggers-other or bracket order with the given + /// limit-price under the stop-loss advanced order leg. Note that this + /// option can only be used in conjunction with stop-loss-stop-price. + #[structopt(long)] + pub stop_loss_limit_price: Option, /// Create an order that is eligible to execute during /// pre-market/after hours. Note that only limit orders that are /// valid for the day are supported. diff --git a/src/main.rs b/src/main.rs index 5c1b44b..ab0d682 100644 --- a/src/main.rs +++ b/src/main.rs @@ -32,6 +32,7 @@ use apca::data::v2::stream; use apca::ApiInfo; use apca::Client; +use anyhow::anyhow; use anyhow::bail; use anyhow::ensure; use anyhow::Context; @@ -847,11 +848,21 @@ async fn order_submit(client: Client, submit: SubmitOrder) -> Result<()> { limit_price, stop_price, take_profit_price, + stop_loss_stop_price, + stop_loss_limit_price, extended_hours, time_in_force, } = submit; - let class = if take_profit_price.is_some() { + if stop_loss_limit_price.is_some() && stop_loss_stop_price.is_none() { + return Err(anyhow!( + "cannot create an one-triggers-other stop loss order without a + specified stop-loss-stop-price" + )) + } + let class = if take_profit_price.is_some() && stop_loss_stop_price.is_some() { + order::Class::Bracket + } else if take_profit_price.is_some() || stop_loss_stop_price.is_some() { order::Class::OneTriggersOther } else { order::Class::Simple @@ -883,6 +894,13 @@ async fn order_submit(client: Client, submit: SubmitOrder) -> Result<()> { let type_ = determine_order_type(&limit_price, &stop_price); let take_profit = take_profit_price.map(order::TakeProfit::Limit); + let stop_loss = match stop_loss_stop_price { + Some(stop_price) => match stop_loss_limit_price { + Some(limit_price) => Some(order::StopLoss::StopLimit(stop_price, limit_price)), + None => Some(order::StopLoss::Stop(stop_price)), + }, + None => None, + }; let time_in_force = time_in_force.to_time_in_force(); // TODO: We should probably support other forms of specifying @@ -894,6 +912,7 @@ async fn order_submit(client: Client, submit: SubmitOrder) -> Result<()> { limit_price, stop_price, take_profit, + stop_loss, extended_hours, ..Default::default() }