Compare commits

...
Author SHA1 Message Date
John Colvin 07beda3fc6 fix: Support fractional show qty in iceberg orders 2025-03-07 20:42:24 +00:00
2 changed files with 33 additions and 18 deletions

No files matched your search

@@ -248,7 +248,7 @@ OrderOpResult AlgoWrapperOrder::on_activate(
me->set_price_quantity(p, q);
for (auto &ct : me->child_templates)
ct->builder.activate(*me->services);
if (q.value() == 0) {
if (q.full_value() == 0) {
ReportStateGuard _(*this);
terminate(ORDER_STATUS_COMPLETED);
} else if (is_attaching())
@@ -292,8 +292,11 @@ OrderOpResult AlgoWrapperOrder::on_update(Update const &update) {
}
case Status::WORKING: {
ReportStateGuard _(*this);
const double frac_qty = update.has_fractional_quantity()
? update.fractional_quantity().fraction()
: 0;
me->set_price_quantity(
Price(update.price()), Quantity(update.quantity()));
Price(update.price()), Quantity(update.quantity(), frac_qty));
if (update.has_custom()) {
*me->definition.mutable_custom_def() = update.custom();
me->services->report_definition(me->definition);
@@ -313,6 +316,7 @@ OrderOpResult AlgoWrapperOrder::on_update(Price p, Quantity q) {
Update up;
up.set_price(p.value());
up.set_quantity(q.value());
up.mutable_fractional_quantity()->set_fraction(q.fractional_part());
return on_update(up);
}
@@ -396,11 +400,17 @@ std::vector<api::Security const *> AlgoWrapperOrder::known_securities() const {
Price AlgoWrapperOrder::price() const { return Price(me->state().price()); }
Quantity AlgoWrapperOrder::quantity() const {
return Quantity(me->state().quantity());
const auto &s = me->state();
return s.has_fractional_quantity()
? Quantity{s.quantity(), s.fractional_quantity().fraction()}
: Quantity{s.quantity()};
}
Quantity AlgoWrapperOrder::total_fills() const {
return Quantity(me->state().filled_quantity());
const auto &s = me->state();
return s.has_fractional_filled_quantity()
? Quantity{s.filled_quantity(), s.fractional_filled_quantity().fraction()}
: Quantity{s.filled_quantity()};
}
bool AlgoWrapperOrder::is_shutting_down() const {
@@ -46,7 +46,7 @@ OrderOpResult IcebergAlgo::do_before_launch(IBeforeLaunchAlgoServices &serv) {
"Show quantity must be greater than 0"};
me->pause_between_orders_ms = iceberg.pause_between_orders_ms();
me->show_quantity = Quantity((uint32_t)iceberg.show_quantity());
me->show_quantity = CQuantity::create_new(iceberg.show_quantity());
// Create a child template so we can quickly launch our child when
// the time comes.
@@ -91,7 +91,11 @@ void IcebergAlgo::do_update(api::orderman::Update const &update) {
return;
}
if (update.quantity() < algo().total_fills().value()) {
const double frac_qty = update.has_fractional_quantity()
? update.fractional_quantity().fraction()
: 0;
const Quantity new_qty{update.quantity(), frac_qty};
if (new_qty < algo().total_fills()) {
algo().complete();
return;
}
@@ -108,7 +112,7 @@ void IcebergAlgo::do_update(api::orderman::Update const &update) {
return;
}
me->show_quantity = Quantity((uint32_t)iceberg_update.show_quantity());
me->show_quantity = CQuantity::create_new(iceberg_update.show_quantity());
bool had_timer = me->pause_between_orders_ms > 0;
bool should_have_timer = iceberg_update.pause_between_orders_ms() > 0;
@@ -122,7 +126,10 @@ void IcebergAlgo::do_update(api::orderman::Update const &update) {
init_child_template(algo(), iceberg_update.child());
}
}
child_update.set_quantity(remaining_quantity().value());
const auto rem_qty = remaining_quantity();
child_update.set_quantity(rem_qty.value());
child_update.mutable_fractional_quantity()->set_fraction(
rem_qty.fractional_part());
if (me->status == Status::WORKING)
algo().update_child(me->child_key, child_update);
}
@@ -130,10 +137,9 @@ void IcebergAlgo::do_update(api::orderman::Update const &update) {
void IcebergAlgo::on_child_change(OrderKey k, ChildState const &st) {
if (k == me->child_key) {
algo().update_fill_state(
Quantity(algo().total_fills().value() + st.last_fills.value()),
st.last_price);
algo().total_fills() + st.last_fills, st.last_price);
if (algo().total_fills().value() >= algo().quantity().value()) {
if (algo().total_fills() >= algo().quantity()) {
algo().complete();
return;
}
@@ -164,7 +170,7 @@ void IcebergAlgo::on_timer() {
void IcebergAlgo::send_next_order() {
bts_assert(me->status == Status::WORKING);
bts_assert(algo().quantity().value() > algo().total_fills().value());
bts_assert(algo().quantity() > algo().total_fills());
me->child_key = algo().launch_child(
*me->child_template, algo().price(), remaining_quantity());
@@ -172,9 +178,8 @@ void IcebergAlgo::send_next_order() {
LOG(OrderMan, Info,
"Iceberg order {} creating new child order {} with size "
"{} price {}. Filled {} so far out of {}",
algo().order_key().value(), me->child_key.value(),
remaining_quantity().value(), algo().price().value(),
algo().total_fills().value(), algo().quantity().value());
algo().order_key(), me->child_key, remaining_quantity(), algo().price(),
algo().total_fills(), algo().quantity());
}
void orderman::IcebergAlgo::init_child_template(
@@ -186,9 +191,9 @@ void orderman::IcebergAlgo::init_child_template(
}
Quantity IcebergAlgo::remaining_quantity() const {
bts_assert(algo().quantity().value() > algo().total_fills().value());
auto remaining = algo().quantity().value() - algo().total_fills().value();
return Quantity(std::min(remaining, me->show_quantity.value()));
bts_assert(algo().quantity() > algo().total_fills());
auto remaining = algo().quantity() - algo().total_fills();
return std::min(remaining, me->show_quantity);
}
} // namespace orderman