Align jq microcap sizing and snapshot pricing
This commit is contained in:
@@ -121,23 +121,10 @@ where
|
|||||||
if self.execution_price_field == PriceField::Last
|
if self.execution_price_field == PriceField::Last
|
||||||
&& self.intraday_execution_start_time.is_some()
|
&& self.intraday_execution_start_time.is_some()
|
||||||
{
|
{
|
||||||
let tick = snapshot.effective_price_tick();
|
return match side {
|
||||||
let base_price = snapshot.price(PriceField::Last);
|
OrderSide::Buy => self.buy_price(snapshot),
|
||||||
let adjusted = match side {
|
OrderSide::Sell => self.sell_price(snapshot),
|
||||||
OrderSide::Buy => base_price + tick * 2.0,
|
|
||||||
OrderSide::Sell => base_price - tick,
|
|
||||||
};
|
};
|
||||||
let lower = if snapshot.lower_limit.is_finite() && snapshot.lower_limit > 0.0 {
|
|
||||||
snapshot.lower_limit
|
|
||||||
} else {
|
|
||||||
tick
|
|
||||||
};
|
|
||||||
let upper = if snapshot.upper_limit.is_finite() && snapshot.upper_limit > 0.0 {
|
|
||||||
snapshot.upper_limit
|
|
||||||
} else {
|
|
||||||
f64::INFINITY
|
|
||||||
};
|
|
||||||
return adjusted.clamp(lower, upper);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
match side {
|
match side {
|
||||||
@@ -1053,8 +1040,7 @@ where
|
|||||||
quantity = quantity.saturating_sub(lot);
|
quantity = quantity.saturating_sub(lot);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let cost = self.cost_model.calculate(OrderSide::Buy, gross);
|
if gross <= cash + 1e-6 {
|
||||||
if gross + cost.total() <= cash + 1e-6 {
|
|
||||||
return quantity;
|
return quantity;
|
||||||
}
|
}
|
||||||
quantity = quantity.saturating_sub(lot);
|
quantity = quantity.saturating_sub(lot);
|
||||||
@@ -1251,8 +1237,7 @@ where
|
|||||||
take_qty = take_qty.saturating_sub(lot);
|
take_qty = take_qty.saturating_sub(lot);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let candidate_cost = self.cost_model.calculate(OrderSide::Buy, candidate_gross);
|
if candidate_gross <= cash + 1e-6 {
|
||||||
if candidate_gross + candidate_cost.total() <= cash + 1e-6 {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
take_qty = take_qty.saturating_sub(lot);
|
take_qty = take_qty.saturating_sub(lot);
|
||||||
@@ -1284,9 +1269,7 @@ where
|
|||||||
residual_qty = residual_qty.saturating_sub(lot);
|
residual_qty = residual_qty.saturating_sub(lot);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let candidate_cost =
|
if candidate_gross <= cash + 1e-6 {
|
||||||
self.cost_model.calculate(OrderSide::Buy, candidate_gross);
|
|
||||||
if candidate_gross + candidate_cost.total() <= cash + 1e-6 {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
residual_qty = residual_qty.saturating_sub(lot);
|
residual_qty = residual_qty.saturating_sub(lot);
|
||||||
|
|||||||
@@ -580,8 +580,7 @@ impl JqMicroCapStrategy {
|
|||||||
let mut quantity = self.round_lot_quantity((cash / sizing_price).floor() as u32, 100);
|
let mut quantity = self.round_lot_quantity((cash / sizing_price).floor() as u32, 100);
|
||||||
while quantity > 0 {
|
while quantity > 0 {
|
||||||
let gross_amount = execution_price * quantity as f64;
|
let gross_amount = execution_price * quantity as f64;
|
||||||
let cash_out = gross_amount + self.buy_commission(gross_amount);
|
if gross_amount <= cash + 1e-6 {
|
||||||
if cash_out <= cash + 1e-6 {
|
|
||||||
return quantity;
|
return quantity;
|
||||||
}
|
}
|
||||||
quantity = quantity.saturating_sub(100);
|
quantity = quantity.saturating_sub(100);
|
||||||
@@ -594,23 +593,10 @@ impl JqMicroCapStrategy {
|
|||||||
market: &crate::data::DailyMarketSnapshot,
|
market: &crate::data::DailyMarketSnapshot,
|
||||||
side: OrderSide,
|
side: OrderSide,
|
||||||
) -> f64 {
|
) -> f64 {
|
||||||
let tick = market.effective_price_tick();
|
match side {
|
||||||
let base_price = market.price(PriceField::Last);
|
OrderSide::Buy => market.buy_price(PriceField::Last),
|
||||||
let adjusted = match side {
|
OrderSide::Sell => market.sell_price(PriceField::Last),
|
||||||
OrderSide::Buy => base_price + tick * 2.0,
|
}
|
||||||
OrderSide::Sell => base_price - tick,
|
|
||||||
};
|
|
||||||
let lower = if market.lower_limit.is_finite() && market.lower_limit > 0.0 {
|
|
||||||
market.lower_limit
|
|
||||||
} else {
|
|
||||||
tick
|
|
||||||
};
|
|
||||||
let upper = if market.upper_limit.is_finite() && market.upper_limit > 0.0 {
|
|
||||||
market.upper_limit
|
|
||||||
} else {
|
|
||||||
f64::INFINITY
|
|
||||||
};
|
|
||||||
adjusted.clamp(lower, upper)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn project_order_value(
|
fn project_order_value(
|
||||||
@@ -654,9 +640,8 @@ impl JqMicroCapStrategy {
|
|||||||
let mut quantity = snapshot_requested_qty;
|
let mut quantity = snapshot_requested_qty;
|
||||||
while quantity > 0 {
|
while quantity > 0 {
|
||||||
let gross_amount = projected_execution_price * quantity as f64;
|
let gross_amount = projected_execution_price * quantity as f64;
|
||||||
let cash_out = gross_amount + self.buy_commission(gross_amount);
|
|
||||||
if gross_amount <= order_value + 400.0
|
if gross_amount <= order_value + 400.0
|
||||||
&& cash_out <= projected.cash() + 1e-6
|
&& gross_amount <= projected.cash() + 1e-6
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -671,8 +656,7 @@ impl JqMicroCapStrategy {
|
|||||||
.unwrap_or(projected_execution_price);
|
.unwrap_or(projected_execution_price);
|
||||||
while quantity > 0 {
|
while quantity > 0 {
|
||||||
let gross_amount = execution_price * quantity as f64;
|
let gross_amount = execution_price * quantity as f64;
|
||||||
let cash_out = gross_amount + self.buy_commission(gross_amount);
|
if gross_amount <= projected.cash() + 1e-6 {
|
||||||
if cash_out <= projected.cash() + 1e-6 {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
quantity = quantity.saturating_sub(round_lot);
|
quantity = quantity.saturating_sub(round_lot);
|
||||||
@@ -687,7 +671,7 @@ impl JqMicroCapStrategy {
|
|||||||
};
|
};
|
||||||
let gross_amount = fill.price * fill.quantity as f64;
|
let gross_amount = fill.price * fill.quantity as f64;
|
||||||
let cash_out = gross_amount + self.buy_commission(gross_amount);
|
let cash_out = gross_amount + self.buy_commission(gross_amount);
|
||||||
if cash_out > projected.cash() + 1e-6 {
|
if gross_amount > projected.cash() + 1e-6 {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
projected.apply_cash_delta(-cash_out);
|
projected.apply_cash_delta(-cash_out);
|
||||||
@@ -890,8 +874,7 @@ impl JqMicroCapStrategy {
|
|||||||
take_qty = take_qty.saturating_sub(lot);
|
take_qty = take_qty.saturating_sub(lot);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let candidate_cash_out = candidate_gross + self.buy_commission(candidate_gross);
|
if candidate_gross <= cash + 1e-6 {
|
||||||
if candidate_cash_out <= cash + 1e-6 {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
take_qty = take_qty.saturating_sub(lot);
|
take_qty = take_qty.saturating_sub(lot);
|
||||||
@@ -923,9 +906,7 @@ impl JqMicroCapStrategy {
|
|||||||
residual_qty = residual_qty.saturating_sub(lot);
|
residual_qty = residual_qty.saturating_sub(lot);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let candidate_cash_out =
|
if candidate_gross <= cash + 1e-6 {
|
||||||
candidate_gross + self.buy_commission(candidate_gross);
|
|
||||||
if candidate_cash_out <= cash + 1e-6 {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
residual_qty = residual_qty.saturating_sub(lot);
|
residual_qty = residual_qty.saturating_sub(lot);
|
||||||
|
|||||||
Reference in New Issue
Block a user