Drop stale broker sizing helpers
This commit is contained in:
@@ -924,65 +924,6 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn estimate_value_buy_quantity(
|
|
||||||
&self,
|
|
||||||
date: NaiveDate,
|
|
||||||
portfolio: &PortfolioState,
|
|
||||||
data: &DataSet,
|
|
||||||
symbol: &str,
|
|
||||||
round_lot: u32,
|
|
||||||
value_budget: f64,
|
|
||||||
intraday_turnover: &BTreeMap<String, u32>,
|
|
||||||
execution_cursors: &BTreeMap<String, NaiveDateTime>,
|
|
||||||
global_execution_cursor: Option<NaiveDateTime>,
|
|
||||||
) -> Option<u32> {
|
|
||||||
if self.execution_price_field != PriceField::Last {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
let snapshot = data.market(date, symbol)?;
|
|
||||||
let market_limited_qty = self
|
|
||||||
.market_fillable_quantity(
|
|
||||||
snapshot,
|
|
||||||
OrderSide::Buy,
|
|
||||||
u32::MAX,
|
|
||||||
round_lot,
|
|
||||||
*intraday_turnover.get(symbol).unwrap_or(&0),
|
|
||||||
)
|
|
||||||
.ok()?;
|
|
||||||
let max_requested_qty = market_limited_qty;
|
|
||||||
let start_cursor = self
|
|
||||||
.intraday_execution_start_time
|
|
||||||
.map(|start_time| date.and_time(start_time));
|
|
||||||
let quotes = data.execution_quotes_on(date, symbol);
|
|
||||||
if let Some(estimated) = self.select_buy_sizing_fill(
|
|
||||||
date,
|
|
||||||
snapshot,
|
|
||||||
quotes,
|
|
||||||
start_cursor,
|
|
||||||
max_requested_qty,
|
|
||||||
round_lot,
|
|
||||||
Some(portfolio.cash()),
|
|
||||||
Some(value_budget),
|
|
||||||
) {
|
|
||||||
return Some(estimated.quantity);
|
|
||||||
}
|
|
||||||
|
|
||||||
let execution_price = self.snapshot_execution_price(snapshot, OrderSide::Buy);
|
|
||||||
let fallback_qty = self.affordable_buy_quantity(
|
|
||||||
date,
|
|
||||||
portfolio.cash(),
|
|
||||||
Some(value_budget),
|
|
||||||
execution_price,
|
|
||||||
max_requested_qty,
|
|
||||||
round_lot,
|
|
||||||
);
|
|
||||||
if fallback_qty > 0 {
|
|
||||||
Some(fallback_qty)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn maybe_expand_periodic_value_buy_quantity(
|
fn maybe_expand_periodic_value_buy_quantity(
|
||||||
&self,
|
&self,
|
||||||
_date: NaiveDate,
|
_date: NaiveDate,
|
||||||
@@ -999,105 +940,6 @@ where
|
|||||||
requested_qty
|
requested_qty
|
||||||
}
|
}
|
||||||
|
|
||||||
fn select_buy_sizing_fill(
|
|
||||||
&self,
|
|
||||||
date: NaiveDate,
|
|
||||||
snapshot: &crate::data::DailyMarketSnapshot,
|
|
||||||
quotes: &[IntradayExecutionQuote],
|
|
||||||
start_cursor: Option<NaiveDateTime>,
|
|
||||||
requested_qty: u32,
|
|
||||||
round_lot: u32,
|
|
||||||
cash_limit: Option<f64>,
|
|
||||||
gross_limit: Option<f64>,
|
|
||||||
) -> Option<ExecutionFill> {
|
|
||||||
if requested_qty == 0 {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let lot = round_lot.max(1);
|
|
||||||
let mut filled_qty = 0_u32;
|
|
||||||
let mut gross_amount = 0.0_f64;
|
|
||||||
let mut last_timestamp = None;
|
|
||||||
|
|
||||||
for quote in quotes {
|
|
||||||
if start_cursor.is_some_and(|cursor| quote.timestamp < cursor) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let fallback_quote_price = if quote.last_price.is_finite() && quote.last_price > 0.0 {
|
|
||||||
Some(quote.last_price)
|
|
||||||
} else {
|
|
||||||
quote.buy_price()
|
|
||||||
};
|
|
||||||
|
|
||||||
if quote.volume_delta == 0 {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let Some(raw_quote_price) = fallback_quote_price else {
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
let quote_price = self.quote_execution_price(snapshot, OrderSide::Buy, raw_quote_price);
|
|
||||||
if !quote_price.is_finite() || quote_price <= 0.0 {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let available_qty = quote
|
|
||||||
.ask1_volume
|
|
||||||
.saturating_mul(lot as u64)
|
|
||||||
.min(u32::MAX as u64) as u32;
|
|
||||||
if available_qty == 0 {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let remaining_qty = requested_qty.saturating_sub(filled_qty);
|
|
||||||
if remaining_qty == 0 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
let mut take_qty = remaining_qty.min(available_qty);
|
|
||||||
take_qty = self.round_buy_quantity(take_qty, lot);
|
|
||||||
if take_qty == 0 {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(cash) = cash_limit {
|
|
||||||
while take_qty > 0 {
|
|
||||||
let candidate_gross = gross_amount + quote_price * take_qty as f64;
|
|
||||||
if gross_limit.is_some_and(|limit| candidate_gross > limit + 1e-6) {
|
|
||||||
take_qty = take_qty.saturating_sub(lot);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let candidate_cost =
|
|
||||||
self.cost_model
|
|
||||||
.calculate(date, OrderSide::Buy, candidate_gross);
|
|
||||||
if candidate_gross + candidate_cost.total() <= cash + 1e-6 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
take_qty = take_qty.saturating_sub(lot);
|
|
||||||
}
|
|
||||||
if take_qty == 0 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gross_amount += quote_price * take_qty as f64;
|
|
||||||
filled_qty += take_qty;
|
|
||||||
last_timestamp = Some(quote.timestamp);
|
|
||||||
|
|
||||||
if filled_qty >= requested_qty {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if filled_qty == 0 {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(ExecutionFill {
|
|
||||||
price: gross_amount / filled_qty as f64,
|
|
||||||
quantity: filled_qty,
|
|
||||||
next_cursor: last_timestamp.unwrap() + Duration::seconds(1),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn process_buy(
|
fn process_buy(
|
||||||
&self,
|
&self,
|
||||||
date: NaiveDate,
|
date: NaiveDate,
|
||||||
@@ -1383,8 +1225,8 @@ where
|
|||||||
data: &DataSet,
|
data: &DataSet,
|
||||||
requested_qty: u32,
|
requested_qty: u32,
|
||||||
round_lot: u32,
|
round_lot: u32,
|
||||||
execution_cursors: &mut BTreeMap<String, NaiveDateTime>,
|
_execution_cursors: &mut BTreeMap<String, NaiveDateTime>,
|
||||||
global_execution_cursor: Option<NaiveDateTime>,
|
_global_execution_cursor: Option<NaiveDateTime>,
|
||||||
cash_limit: Option<f64>,
|
cash_limit: Option<f64>,
|
||||||
gross_limit: Option<f64>,
|
gross_limit: Option<f64>,
|
||||||
) -> Option<ExecutionFill> {
|
) -> Option<ExecutionFill> {
|
||||||
|
|||||||
@@ -653,7 +653,7 @@ impl JqMicroCapStrategy {
|
|||||||
round_lot,
|
round_lot,
|
||||||
);
|
);
|
||||||
let projected_execution_price = self.projected_execution_price(market, OrderSide::Buy);
|
let projected_execution_price = self.projected_execution_price(market, OrderSide::Buy);
|
||||||
let mut projected_fill = self.projected_select_execution_fill(
|
let projected_fill = self.projected_select_execution_fill(
|
||||||
ctx,
|
ctx,
|
||||||
date,
|
date,
|
||||||
symbol,
|
symbol,
|
||||||
|
|||||||
Reference in New Issue
Block a user