Compare commits

...
Author SHA1 Message Date
Taha Afzal d942676765 sniper done, need to test more 2018-11-06 17:23:18 -05:00
15 changed files with 398 additions and 23 deletions

No files matched your search

@@ -28,6 +28,7 @@ _state_worker(nullptr),
_start_state_worker(this),
_waiting_for_initial_data_state_worker(this),
_working_state_worker(this),
_sniper_working_state_worker (this),
_waiting_for_cancel_all_state_worker(this),
_end_state_worker(this){
_transform_to_START();
@@ -201,8 +202,13 @@ void SpreaderOrder::_transform_to_WORKING(){
bts_assert(_state_worker->state() == SpreaderState::WAITING_FOR_INIT_DATA);
_switch_state(&_working_state_worker);
}
void SpreaderOrder::_transform_to_SNIPER_WORKING(){
bts_assert(_state_worker->state() == SpreaderState::WAITING_FOR_INIT_DATA);
_switch_state(&_sniper_working_state_worker);
}
void SpreaderOrder::_transform_to_WAITING_FOR_CANCEL_ALL(){
bts_assert(_state_worker->state() == SpreaderState::WORKING);
bts_assert(_state_worker->state() == SpreaderState::WORKING ||
_state_worker->state() == SpreaderState::SNIPER_STATE_WORKING);
_switch_state(&_waiting_for_cancel_all_state_worker);
}
void SpreaderOrder::_transform_to_END(std::string*){
@@ -310,6 +316,17 @@ bool SpreaderOrder::_quoters_can_accept_modification (){
}
return true;
}
bool SpreaderOrder::_any_hedger_waiting_for_exchange_ack (){
for (size_t q_idx = 0; q_idx < _bookkeeping_data().n_legs(); q_idx++){
SpreaderLegData& leg_data = _bookkeeping_data().get_leg_data(q_idx);
for (size_t h_idx = 0; h_idx < leg_data.n_hedgers(); h_idx++){
SingleFillHedger& hedger = leg_data.get_hedger(h_idx);
if(hedger.waiting_for_exchange_ack())
return true;
}
}
return false;
}
void SpreaderOrder::_send_hedge(size_t hedge_leg_index,
Price hedge_price,
Quantity hedge_qty,
@@ -389,6 +406,7 @@ bts::api::orderman::OrderStatus SpreaderOrder::_get_order_status () const{
SpreaderState::START : _state_worker->state();
switch (curr_state){
case SpreaderState::WORKING:
case SpreaderState::SNIPER_STATE_WORKING:
return bts::api::orderman::OrderStatus::ORDER_STATUS_WORKING;
case SpreaderState::WAITING_FOR_CANCEL_ALL:
return bts::api::orderman::OrderStatus::ORDER_STATUS_WORKING;
@@ -438,4 +456,13 @@ Price SpreaderOrder::_compute_effective_price (Price input_price){
else
return input_price;
}
bool SpreaderOrder::_is_sniper() const{
for(size_t i=0; i<_bookkeeping_data().n_legs();i++){
const LegPropertyData& leg_data=
_bookkeeping_data().get_leg_data(i).leg_property_data();
if(leg_data.is_active_quoting())
return false;
}
return true;
}
}}
@@ -11,6 +11,7 @@
#include "lib/orderman/orders/spreader_orders/spreader_states/SpreaderStartStateWorker.h"
#include "lib/orderman/orders/spreader_orders/spreader_states/SpreaderWaitingForInitialDataStateWorker.h"
#include "lib/orderman/orders/spreader_orders/spreader_states/SpreaderWorkingStateWorker.h"
#include "lib/orderman/orders/spreader_orders/spreader_states/SpreaderSniperModeWorkingStateWorker.h"
#include "lib/orderman/orders/spreader_orders/spreader_states/SpreaderWaitingForCancelAllStateWorker.h"
#include "lib/orderman/orders/spreader_orders/spreader_states/SpreaderEndStateWorker.h"
#include "lib/utils/is_unittest_environment.h"
@@ -32,6 +33,7 @@ class SpreaderOrder : public Order, public ISpreaderManager
friend class SpreaderStartStateWorker;
friend class SpreaderWaitingForInitialDataStateWorker;
friend class SpreaderWorkingStateWorker;
friend class SpreaderSniperModeWorkingStateWorker;
friend class SpreaderWaitingForCancelAllStateWorker;
friend class SpreaderEndStateWorker;
private:
@@ -72,6 +74,7 @@ private:
SpreaderStartStateWorker _start_state_worker;
SpreaderWaitingForInitialDataStateWorker _waiting_for_initial_data_state_worker;
SpreaderWorkingStateWorker _working_state_worker;
SpreaderSniperModeWorkingStateWorker _sniper_working_state_worker;
SpreaderWaitingForCancelAllStateWorker _waiting_for_cancel_all_state_worker;
SpreaderEndStateWorker _end_state_worker;
// const/dest ////////////////////
@@ -136,6 +139,7 @@ private:
void _transform_to_START();
void _transform_to_WAITING_FOR_INITIAL_DATA();
void _transform_to_WORKING();
void _transform_to_SNIPER_WORKING();
void _transform_to_WAITING_FOR_CANCEL_ALL();
// optionally parameter to state the end reason
void _transform_to_END(std::string* m = nullptr);
@@ -171,6 +175,9 @@ private:
void _terminate_hedgers();
// this returns true is all quoters can accept modification
bool _quoters_can_accept_modification();
// returns true is any hedger is waiting for a submit
// or cancel order ack
bool _any_hedger_waiting_for_exchange_ack ();
// this sends a hedge (creates a hedger and inits it)
// on leg 'leg_to_hedge_index' in response to a fill
// on leg 'filled_leg_index' with price 'filled_price'
@@ -240,11 +247,14 @@ private:
// (if settlements are not available returns nan)
// Otherwise effectiv_price==order_price.
Price _compute_effective_price (Price order_price);
// as the name says, iterates over the legs
// and if none of them are quoting returns true
bool _is_sniper() const;
// testing only //////////////////
// this provides direct way to inject
// data into the spreader, as well as
// access to the internal state
//////////////////////////////////
//////////////////////////////////
public:
SpreaderState test_only_func_spreader_state () {return _state_worker->state();}
SpreaderLegData& test_only_func_spreader_leg_data (size_t index) {return _bookkeeping_data().get_leg_data (index);}
@@ -113,6 +113,19 @@ void SingleFillHedger::on_time (const bts::TimeStamp& ts){
bool SingleFillHedger::is_terminal_state () const {
return _worker->state() == HedgerState::END;
}
bool SingleFillHedger::is_active_order() const{
HedgerState state = _worker->state();
return state == HedgerState::WAITING_FOR_FIRST_ACK ||
state == HedgerState::WAITING_FOR_FIRST_ACK_CANCELLED ||
state == HedgerState::WORKING ||
state == HedgerState::WAITING_FOR_CANCEL_ACK;
}
bool SingleFillHedger::waiting_for_exchange_ack() const{
HedgerState state = _worker->state();
return state == HedgerState::WAITING_FOR_FIRST_ACK ||
state == HedgerState::WAITING_FOR_FIRST_ACK_CANCELLED ||
state == HedgerState::WAITING_FOR_CANCEL_ACK;
}
/********************************************************************/
/*************************State Transformations**********************/
/********************************************************************/
@@ -99,10 +99,17 @@ public:
// returns true if the quoter is in the final state, from which
// it will never come back
bool is_terminal_state () const;
// true if the hedger can accept a price change
// analogous to quoter's expecting_cancel_update
bool expecting_cancel_update() const {
return _worker->state() == HedgerState::WAITING_FOR_CANCEL_ACK;
}
// analogous to the quoter (if order is
// out there)
bool is_active_order() const;
// if the hedger is waiting for a submit
// or cancel ack (not a modify ack since
// we dont keep state for those)
bool waiting_for_exchange_ack() const;
public:
HedgerState test_only_func_hedger_state() const { return _worker->state (); }
const HedgePriceQuantityState& test_only_func_price_quantity_state () const {
@@ -8,10 +8,13 @@ SpreaderBookkeepingData::SpreaderBookkeepingData (ISpreaderManager& spreader_man
const api::orderman::OrderDefinition& order_def,
const SpreaderPreActivationOrderServices& spreader_pao_services,
const std::vector<LegPropertyData>& legs,
const api::ContractSpecification& contract_spec,
bool inited_new)
:
_is_live(spreader_pao_services.is_live()),
_n_legs(legs.size()),
_side(order_def.side()),
_contract_spec(contract_spec),
_inited_new (inited_new),
_order_def(order_def),
_reported_state(){
@@ -52,13 +55,15 @@ _reported_state(){
SpreaderBookkeepingData::SpreaderBookkeepingData (ISpreaderManager& spreader_manager,
const bts::api::orderman::OrderRecord& order_record,
const SpreaderPreActivationOrderServices& spreader_pao_services,
const std::vector<LegPropertyData>& legs)
const std::vector<LegPropertyData>& legs,
const api::ContractSpecification& contract_spec)
:
SpreaderBookkeepingData(spreader_manager,
OrderKey(order_record.key()),
order_record.def(),
spreader_pao_services,
legs,
contract_spec,
false){
_reported_state=order_record.state();
}
@@ -5,13 +5,14 @@
#include "SpreaderLegData.h"
#include "lib/api/services/OrderService.pb.h"
#include "lib/domain_model/Security.h"
#include "lib/orderman/actors/order_manager/OrderBuilder.h"
#include "lib/orderman/orders/PreActivationOrderServices.h"
#include "lib/orderman/orders/spreader_orders/spreader/external_interfacing/SpreaderOrderBuilder.h"
#include "lib/orderman/orders/spreader_orders/spreader/hedger/UnhedgedDelta.h"
namespace bts{
namespace orderman {
namespace orderman {
class SingleFillHedger;
// encapsulates, organizes and provides easy access
// and lookups for data needed by the spreader.
@@ -22,6 +23,8 @@ class SpreaderBookkeepingData
private:
const bool _is_live;
const size_t _n_legs;
const api::Side _side;
const api::ContractSpecification _contract_spec;
// when the order is not created from the disk
// (ie created live) this is set to true
const bool _inited_new;
@@ -48,11 +51,13 @@ public:
const api::orderman::OrderDefinition& order_def,
const SpreaderPreActivationOrderServices& spreader_pao_services,
const std::vector<LegPropertyData>& legs,
const api::ContractSpecification& contract_spec,
bool inited_new=true);
SpreaderBookkeepingData (ISpreaderManager& spreader_manager,
const bts::api::orderman::OrderRecord& order_record,
const SpreaderPreActivationOrderServices& spreader_pao_services,
const std::vector<LegPropertyData>& legs);
const std::vector<LegPropertyData>& legs,
const api::ContractSpecification& contract_spec);
SpreaderBookkeepingData()=delete;
SpreaderBookkeepingData (const SpreaderBookkeepingData&) = delete;
SpreaderBookkeepingData (SpreaderBookkeepingData&&) = delete;
@@ -61,6 +66,8 @@ public:
// accessors ////////////////////
/////////////////////////////////
size_t n_legs() const { return _n_legs; }
api::Side side() const { return _side;}
double tick_size() const {return _contract_spec.low_tick();}
bool all_legs_resolved() const {return n_legs() > 0;}
const api::orderman::OrderDefinition& order_def() const {return _order_def;}
Price input_price () const {return _input_price;}
@@ -17,6 +17,7 @@ api::Side SpreaderUtils::get_leg_side(api::Side spreader_order_side,
bool SpreaderUtils::resolve_synthetic_spread (const SpreaderPreActivationOrderServices& spreader_pao_services,
const api::orderman::OrderDefinition& order_def,
std::vector<LegPropertyData>& out_resolved,
api::ContractSpecification& out_synthetic_spec,
bool resolve_synthetic){
bts_assert(order_def.has_custom_def() && order_def.custom_def().has_spreader());
const bts::api::Security* sec_ptr = resolve_synthetic ? spreader_pao_services.resolve (SecurityKey(order_def.security_key())) :
@@ -25,6 +26,7 @@ bool SpreaderUtils::resolve_synthetic_spread (const SpreaderPreActivationOrderSe
const spark::ExecutionStrategy& execution_strategy = order_def.custom_def().spreader().execution_strategy();
const bts::api::Security& sec = *sec_ptr;
if (sec.has_synthetic() && sec.synthetic().legs().size() > 0){
out_synthetic_spec = sec.contract_spec();
size_t leg_idx = 0;
for (auto it = sec.synthetic().legs().begin(); it != sec.synthetic().legs().end(); ++it){
const bts::api::ContractLeg& leg = *it;
@@ -59,6 +59,7 @@ public:
static bool resolve_synthetic_spread (const SpreaderPreActivationOrderServices& spreader_pao_services,
const api::orderman::OrderDefinition& order_def,
std::vector<LegPropertyData>& out_resolved,
api::ContractSpecification& out_synthetic_spec,
bool resolve_synthetic = true);
////////////////////////////////////////////////////
// orders //////////////////////////////////////////
@@ -554,7 +555,7 @@ public:
out_qty,
out_cum_qty);
quantity = Quantity(std::min(quantity.value(),out_cum_qty.value()));
}
}
////////////////////////2 legged spreads
// given a quoting target qty, finds the "driver" price
// and qty, thats needed to hedge the quote. It also
@@ -587,6 +588,46 @@ public:
out_quote_target_uint = std::min(out_quote_target_uint,quote_target.value());
out_quote_target = Quantity (out_quote_target_uint);
}
// anologous to the function above, but the target is
// specified in terms of spread (and not the quoting leg)
static void compute_driver(Quantity spread_target,
const LegPropertyData& hedge_leg_data,
const bts::orderman::Book& hedge_leg_book,
Price& out_hedge_price,
Quantity& out_hedge_quantity,
Quantity& out_spread_target){
// effective_mult is the number of contracts needed to
// hedge one quoting contract
double effective_mult = hedge_leg_data.leg_params().quote_params().lean_quantity_ratio() *
hedge_leg_data.size_multiplier();
compute_driver(spread_target,effective_mult,hedge_leg_data,hedge_leg_book,
out_hedge_price,out_hedge_quantity,out_spread_target);
}
// given a target qty, and a mult,
// finds the hedging qty, price
// and ammended target
static void compute_driver(Quantity target,
double hedge_mult,
const LegPropertyData& hedge_leg_data,
const bts::orderman::Book& hedge_leg_book,
Price& out_hedge_price,
Quantity& out_hedge_quantity,
Quantity& out_target){
bts_assert(hedge_mult>0);
// rounding hedging up
uint32_t hedge_requirement = _round_hedge_target (hedge_mult * target.value());
SpreaderUtils::traverse_depth_for_quantity(
hedge_leg_book,
SpreaderUtils::invert_side (hedge_leg_data.trading_side()),
Quantity(hedge_requirement),
out_hedge_price,
out_hedge_quantity);
// rounding quoting down
uint32_t out_target_uint =
_round_quoting_qty (out_hedge_quantity.value() / hedge_mult);
out_target_uint = std::min(out_target_uint,target.value());
out_target = Quantity (out_target_uint);
}
// calculates the computed price and quantity for a quoting
// leg given the data for the other leg
static void compute_price_quantity_2_legs(Price target_spread_price,
@@ -697,6 +738,55 @@ public:
quote_fill_quantity,
hedge_leg);
}
////////////////////////Sniper
// for the quantity (4th arg), finds the spreader
// price that would result in an immediate cross
static void compute_sniper_hedges (const ISpreaderManager& spreader,
Quantity in_quantity,
std::vector<QuoteLegDriver>& out_driver_vector){
size_t n_legs = out_driver_vector.size();
for (size_t idx = 0; idx < n_legs; idx++){
const bts::orderman::Book& hedge_leg_book = spreader.get_book(idx);
const LegPropertyData& hedge_leg_data = spreader.get_leg_data(idx);
Price hedge_price;
Quantity hedge_qty, spread_qty;
compute_driver(in_quantity,
hedge_leg_data,
hedge_leg_book,
hedge_price,
hedge_qty,
spread_qty);
out_driver_vector[idx].set (hedge_price, hedge_qty, spread_qty);
}
}
static void compute_sniper_data (const ISpreaderManager& spreader,
Quantity in_quantity,
Quantity& out_quantity,
Price& out_price,
std::vector<QuoteLegDriver>& out_driver_vector){
compute_sniper_hedges(spreader,in_quantity,out_driver_vector);
out_quantity = compute_quoting_quantity_from_drivers (10000, out_driver_vector);
if (out_quantity.value() == 0){
out_quantity = Quantity(0);
out_price = Price (0);
}
else{
compute_sniper_hedges(spreader,out_quantity,out_driver_vector);
out_price = _compute_sniper_price(spreader,out_driver_vector);
}
}
static Price _compute_sniper_price (
const ISpreaderManager& spreader,
const std::vector<QuoteLegDriver>& driver_vector){
size_t l_idx=0;
double rv = 0;
for(const QuoteLegDriver& d : driver_vector){
rv += spreader.get_leg_data(l_idx).price_multiplier() *
d.driver_price().value();
l_idx++;
}
return Price(rv);
}
////////////////////////////////////////////////////
// Rounding functions //////////////////////////////
////////////////////////////////////////////////////
@@ -0,0 +1,150 @@
#include "SpreaderSniperModeWorkingStateWorker.h"
#include "lib/orderman/orders/spreader_orders/SpreaderOrder.h"
namespace bts {
namespace orderman {
SpreaderSniperModeWorkingStateWorker::SpreaderSniperModeWorkingStateWorker
(SpreaderOrder* spreader)
:
_spreader(spreader),
_fired_qty(0),
_aux_calc_data(){
}
SpreaderState SpreaderSniperModeWorkingStateWorker::state() const {
return SpreaderState::SNIPER_STATE_WORKING;
}
void SpreaderSniperModeWorkingStateWorker::on_transition (){
size_t n_legs=_spreader->_bookkeeping_data().n_legs();
_aux_calc_data.reserve(n_legs);
for(size_t l_idx=0;l_idx<n_legs;l_idx++)
_aux_calc_data.push_back (QuoteLegDriver());
PerfTrace trace;
_analyze_and_fire(trace);
}
void SpreaderSniperModeWorkingStateWorker::on_init_new(
api::orderman::OrderDefinition const&,
const SpreaderPreActivationOrderServices&){
bts_assert_msg (false, "SpreaderSniperModeWorkingStateWorker::on_init_new "
"is an illegal operation");
}
void SpreaderSniperModeWorkingStateWorker::on_init_recovered(
const bts::api::orderman::OrderRecord&,
const SpreaderPreActivationOrderServices&){
bts_assert_msg (false, "SpreaderSniperModeWorkingStateWorker::on_init_new "
"is an illegal operation");
}
void SpreaderSniperModeWorkingStateWorker::on_activate(
Price,
Quantity,
SpreaderOrderServices&){
bts_assert_msg (false, "SpreaderSniperModeWorkingStateWorker::on_activate "
"is an illegal operation");
}
void SpreaderSniperModeWorkingStateWorker::on_update(Price price,
Quantity quantity){
_spreader->_set_price_quantity (price, quantity);
PerfTrace trace;
_analyze_and_fire(trace);
}
void SpreaderSniperModeWorkingStateWorker::on_cancel(){
_spreader->_cancel_orders (true, true);
_spreader->_transform_to_WAITING_FOR_CANCEL_ALL ();
}
void SpreaderSniperModeWorkingStateWorker::on_book(const Book& book,
PerfTrace& perf_trace){
SpreaderBookkeepingData& bookkeeping_data = _spreader->_bookkeeping_data();
SpreaderLegData& md_leg = bookkeeping_data.get_leg_data(book.security_key());
md_leg.update_book(book);
_analyze_and_fire(perf_trace);
}
void SpreaderSniperModeWorkingStateWorker::on_settlement_price(
const SettlementUpdateEvent&){
}
void SpreaderSniperModeWorkingStateWorker::on_time(const TimeStamp& ts){
SpreaderBookkeepingData& bookkeeping_data = _spreader->_bookkeeping_data();
for (size_t q_idx = 0; q_idx < bookkeeping_data.n_legs(); q_idx++){
SpreaderLegData& leg_data = bookkeeping_data.get_leg_data(q_idx);
for (size_t h_idx = 0; h_idx < leg_data.n_hedgers(); h_idx++)
leg_data.get_hedger(h_idx).on_time (ts);
}
}
void SpreaderSniperModeWorkingStateWorker::on_quoter_order_error(
SpreaderLegData&){
bts_assert_msg (false, "SpreaderSniperModeWorkingStateWorker::"
"on_quoter_order_error is an illegal operation");
}
void SpreaderSniperModeWorkingStateWorker::on_quoter_order_fill(
SpreaderLegData&,
PerfTrace&){
bts_assert_msg (false, "SpreaderSniperModeWorkingStateWorker::"
"on_quoter_order_fill is an illegal operation");
}
void SpreaderSniperModeWorkingStateWorker::on_quoter_order_status_update(
SpreaderLegData&){
bts_assert_msg (false, "SpreaderSniperModeWorkingStateWorker::"
"on_quoter_order_status_update is an illegal operation");
}
void SpreaderSniperModeWorkingStateWorker::on_hedger_order_error(
SingleFillHedger& hedger){
hedger.on_order_update(hedger.order_state());
_spreader->_cancel_orders (true, true);
_spreader->_transform_to_WAITING_FOR_CANCEL_ALL ();
}
void SpreaderSniperModeWorkingStateWorker::on_hedger_order_update(
SingleFillHedger& hedger){
hedger.on_order_update(hedger.order_state());
PerfTrace trace;
_analyze_and_fire(trace);
}
void SpreaderSniperModeWorkingStateWorker::on_check_termination(){
if (_remaining_qty().value() == 0 &&
_spreader->_all_hedger_orders_in_terminal_state())
_spreader->_transform_to_END();
}
void SpreaderSniperModeWorkingStateWorker::on_quoter_irrecoverable_error (){
bts_assert_msg (false, "SpreaderSniperModeWorkingStateWorker::"
"on_quoter_irrecoverable_error is an illegal operation");
}
Quantity SpreaderSniperModeWorkingStateWorker::_remaining_qty() const{
const SpreaderBookkeepingData& data = _spreader->_bookkeeping_data();
if(_fired_qty.value() >= data.quantity().value())
return Quantity(0);
else
return Quantity(data.quantity().value()-_fired_qty.value());
}
void SpreaderSniperModeWorkingStateWorker::_analyze_and_fire(PerfTrace& perf_trace){
const SpreaderBookkeepingData& data = _spreader->_bookkeeping_data();
Quantity remaining_qty=_remaining_qty();
if(remaining_qty.value()>0){
Quantity out_quantity(0);
Price out_price(0);
SpreaderUtils::compute_sniper_data(*_spreader,
remaining_qty,
out_quantity,
out_price,
_aux_calc_data);
if(out_quantity.value() > 0){
bool cross=(data.side() == api::Side::SIDE_BUY &&
securities::gr_than_eq(data.effective_price().value(),
out_price.value(),
data.tick_size()))
||
(data.side() == api::Side::SIDE_SELL &&
securities::gr_than_eq(out_price.value(),
data.effective_price().value(),
data.tick_size()));
if(cross){
size_t leg_idx=0;
_fired_qty = Quantity(_fired_qty.value()+out_quantity.value());
for (const QuoteLegDriver d : _aux_calc_data){
_spreader->_send_hedge(leg_idx,d.driver_price(),
d.driver_quantity(),perf_trace);
leg_idx++;
}
}
}
}
}
}}
@@ -0,0 +1,42 @@
#pragma once
#include "lib/orderman/orders/spreader_orders/ISpreaderStateWorker.h"
namespace bts {
namespace orderman {
class SpreaderOrder;
class SpreaderSniperModeWorkingStateWorker : public ISpreaderStateWorker
{
private:
SpreaderOrder* const _spreader;
public:
SpreaderSniperModeWorkingStateWorker (SpreaderOrder*);
void on_transition() override;
SpreaderState state() const override;
void on_init_new(api::orderman::OrderDefinition const&,
const SpreaderPreActivationOrderServices&) override;
void on_init_recovered(const bts::api::orderman::OrderRecord&,
const SpreaderPreActivationOrderServices&) override;
void on_activate(Price, Quantity,
SpreaderOrderServices&) override;
void on_update(Price, Quantity) override;
void on_cancel() override;
void on_book(const Book&,PerfTrace &) override;
void on_settlement_price(const SettlementUpdateEvent&) override;
void on_time(const TimeStamp&) override;
void on_quoter_order_error(SpreaderLegData& leg_data) override;
void on_quoter_order_fill(SpreaderLegData& leg_data,
PerfTrace &) override;
void on_quoter_order_status_update(SpreaderLegData& leg_data) override;
void on_hedger_order_error(SingleFillHedger&) override;
void on_hedger_order_update(SingleFillHedger&) override;
void on_check_termination () override;
void on_quoter_irrecoverable_error () override;
private:
void _analyze_and_fire(PerfTrace& perf_trace);
Quantity _remaining_qty() const;
Quantity _fired_qty;
std::vector<QuoteLegDriver> _aux_calc_data;
};
}}
@@ -21,26 +21,31 @@ void SpreaderStartStateWorker::on_init_new(const api::orderman::OrderDefinition&
{
bts_assert(!_spreader->_inited());
std::vector<LegPropertyData> spreader_legs;
api::ContractSpecification synthetic_spec;
if (SpreaderUtils::resolve_synthetic_spread (spreader_pao_services,
order_def,
spreader_legs,
synthetic_spec,
false)){
_spreader->_bookkeeping_data_ptr =
std::make_unique<SpreaderBookkeepingData>(*_spreader,
_spreader->key(),
order_def,
spreader_pao_services,
spreader_legs);
spreader_legs,
synthetic_spec);
_spreader->_cancel_hedges_on_cancel=
order_def.custom_def().spreader().execution_strategy().cancel_hedges_on_cancel();
}
else
{
api::ContractSpecification synthetic_spec;
_spreader->_bookkeeping_data_ptr = std::make_unique<SpreaderBookkeepingData>(*_spreader,
_spreader->key(),
order_def,
spreader_pao_services,
std::vector<LegPropertyData>());
std::vector<LegPropertyData>(),
synthetic_spec);
// if securities can not be resolved, the order is terminated
LOG(OrderMan, Error, "SpreaderStartStateWorker.on_init_new key: {} , could not resolve securities", _spreader->key().value());
std::string msg = "Could not resolve securities";
@@ -58,10 +63,12 @@ void SpreaderStartStateWorker::on_init_recovered(const bts::api::orderman::Order
bts::api::orderman::OrderRecord order_record_copy = order_record;
if (!SpreaderUtils::order_in_terminal_state(order_record_copy.mutable_state()->status()))
order_record_copy.mutable_state()->set_status(bts::api::orderman::OrderStatus::ORDER_STATUS_CANCELED);
api::ContractSpecification synthetic_spec;
_spreader->_bookkeeping_data_ptr = std::make_unique<SpreaderBookkeepingData>(*_spreader,
order_record_copy,
spreader_pao_services,
std::vector<LegPropertyData>());
std::vector<LegPropertyData>(),
synthetic_spec);
LOG(OrderMan, Warn, "SpreaderStartStateWorker.on_init_recovered key: {} , going to END", _spreader->key().value());
std::string msg = "Recovered spreader orders (from last session) are cancelled";
_spreader->_transform_to_END (&msg);
@@ -10,6 +10,8 @@ enum class SpreaderState
WAITING_FOR_INIT_DATA,
// after the first connection, the general waiting state
WORKING,
// anologous of the above but for sniper mode
SNIPER_STATE_WORKING,
// waiting for all quoters and hedgers to be done
WAITING_FOR_CANCEL_ALL,
// end state
@@ -103,7 +103,11 @@ void SpreaderWaitingForInitialDataStateWorker::_init_quoters(){
}
}
void SpreaderWaitingForInitialDataStateWorker::_go_to_working(){
_init_quoters();
_spreader->_transform_to_WORKING();
if(_spreader->_is_sniper())
_spreader->_transform_to_SNIPER_WORKING();
else{
_init_quoters();
_spreader->_transform_to_WORKING();
}
}
}}
@@ -275,7 +275,8 @@ TEST_CASE ("spreader bookkeeping data", "[spreader]")
SpreaderPreActivationOrderServices::TestOnlySpreaderPreActivationOrderServices testonly_spreader_pao_services = _create_spreader_pao_services(synthetic_security);
SpreaderPreActivationOrderServices pao_services (&testonly_spreader_pao_services);
std::vector<LegPropertyData> leg_props;
SpreaderUtils::resolve_synthetic_spread(pao_services, order_def, leg_props);
api::ContractSpecification synth_spec;
SpreaderUtils::resolve_synthetic_spread(pao_services, order_def, leg_props,synth_spec);
SpreaderManagerForTest spreader_manager (order_key, order_def, pao_services, leg_props);
SpreaderBookkeepingData& bookkeeping_data = spreader_manager.bookkeeping_data();
SECTION("verify security key access")
@@ -1618,7 +1619,8 @@ TEST_CASE ("spreader_START", "[spreader]")
SpreaderPreActivationOrderServices::TestOnlySpreaderPreActivationOrderServices testonly_spreader_pao_services = _create_spreader_pao_services(synthetic_security);
SpreaderPreActivationOrderServices pao_services (&testonly_spreader_pao_services);
std::vector<LegPropertyData> leg_props;
SpreaderUtils::resolve_synthetic_spread(pao_services, order_def, leg_props);
api::ContractSpecification synth_spec;
SpreaderUtils::resolve_synthetic_spread(pao_services, order_def, leg_props,synth_spec);
SpreaderManagerForTest spreader_manager (order_key, order_def, pao_services, leg_props);
SpreaderBookkeepingData& bookkeeping_data = spreader_manager.bookkeeping_data();
SpreaderOrder spreader;
@@ -1674,7 +1676,8 @@ TEST_CASE ("spreader_WORKING", "[spreader]")
SpreaderPreActivationOrderServices::TestOnlySpreaderPreActivationOrderServices testonly_spreader_pao_services = _create_spreader_pao_services(synthetic_security);
SpreaderPreActivationOrderServices pao_services (&testonly_spreader_pao_services);
std::vector<LegPropertyData> leg_props;
SpreaderUtils::resolve_synthetic_spread(pao_services, order_def, leg_props);
api::ContractSpecification synth_spec;
SpreaderUtils::resolve_synthetic_spread(pao_services, order_def, leg_props,synth_spec);
SpreaderManagerForTest spreader_manager (order_key, order_def, pao_services, leg_props);
SpreaderOrder spreader;
REQUIRE(spreader.test_only_func_spreader_state() == SpreaderState::START);
@@ -2003,7 +2006,8 @@ TEST_CASE ("spreader_WAITING_FOR_CANCEL_ACK", "[spreader]")
SpreaderPreActivationOrderServices::TestOnlySpreaderPreActivationOrderServices testonly_spreader_pao_services = _create_spreader_pao_services(synthetic_security);
SpreaderPreActivationOrderServices pao_services (&testonly_spreader_pao_services);
std::vector<LegPropertyData> leg_props;
SpreaderUtils::resolve_synthetic_spread(pao_services, order_def, leg_props);
api::ContractSpecification synth_spec;
SpreaderUtils::resolve_synthetic_spread(pao_services, order_def, leg_props,synth_spec);
SpreaderManagerForTest spreader_manager (order_key, order_def, pao_services, leg_props);
SpreaderOrder spreader;
REQUIRE(spreader.test_only_func_spreader_state() == SpreaderState::START);
@@ -2395,7 +2399,8 @@ TEST_CASE ("nlegs_compute_driver", "[spreader]"){
testonly_spreader_pao_services = _create_spreader_pao_services(sec);
SpreaderPreActivationOrderServices pao_services (&testonly_spreader_pao_services);
std::vector<LegPropertyData> leg_props;
SpreaderUtils::resolve_synthetic_spread(pao_services, order_def, leg_props);
api::ContractSpecification synth_spec;
SpreaderUtils::resolve_synthetic_spread(pao_services, order_def, leg_props,synth_spec);
SpreaderManagerForTest spreader_manager (order_key, order_def, pao_services, leg_props);
SpreaderBookkeepingData& bookkeeping_data = spreader_manager.bookkeeping_data();
SECTION("compute_1"){
@@ -2595,7 +2600,8 @@ TEST_CASE ("spreader_perf_2legs", "[spreader]")
testonly_spreader_pao_services = _create_spreader_pao_services(synthetic_security);
SpreaderPreActivationOrderServices pao_services (&testonly_spreader_pao_services);
std::vector<LegPropertyData> leg_props;
SpreaderUtils::resolve_synthetic_spread(pao_services, order_def, leg_props);
api::ContractSpecification synth_spec;
SpreaderUtils::resolve_synthetic_spread(pao_services, order_def, leg_props,synth_spec);
SpreaderManagerForTest spreader_manager (order_key, order_def, pao_services, leg_props);
SpreaderOrder spreader;
REQUIRE(spreader.test_only_func_spreader_state() == SpreaderState::START);
@@ -2746,7 +2752,8 @@ TEST_CASE ("spreader_perf_4legs", "[spreader]")
testonly_spreader_pao_services = _create_spreader_pao_services(synthetic_security);
SpreaderPreActivationOrderServices pao_services (&testonly_spreader_pao_services);
std::vector<LegPropertyData> leg_props;
SpreaderUtils::resolve_synthetic_spread(pao_services, order_def, leg_props);
api::ContractSpecification synth_spec;
SpreaderUtils::resolve_synthetic_spread(pao_services, order_def, leg_props,synth_spec);
SpreaderManagerForTest spreader_manager (order_key, order_def, pao_services, leg_props);
SpreaderOrder spreader;
REQUIRE(spreader.test_only_func_spreader_state() == SpreaderState::START);
@@ -36,8 +36,8 @@ public:
const SpreaderPreActivationOrderServices& spreader_pao_services,
const std::vector<LegPropertyData>& legs)
:
_spreader_order_key (spreader_order_key),
_bookkeeping_data (*this, spreader_order_key, order_def, spreader_pao_services, legs)
_spreader_order_key (spreader_order_key),
_bookkeeping_data (*this, spreader_order_key, order_def, spreader_pao_services, legs, api::ContractSpecification())
{}
SpreaderBookkeepingData& bookkeeping_data() {return _bookkeeping_data;}
@@ -364,7 +364,8 @@ SpreaderManagerForTest* create_spreader_manager_2_legs (bts::orderman::OrderKey
SpreaderPreActivationOrderServices::TestOnlySpreaderPreActivationOrderServices testonly_spreader_pao_services = _create_spreader_pao_services(synthetic_security);
SpreaderPreActivationOrderServices pao_services (&testonly_spreader_pao_services);
std::vector<LegPropertyData> leg_props;
SpreaderUtils::resolve_synthetic_spread(pao_services, order_def, leg_props);
api::ContractSpecification synth_spec;
SpreaderUtils::resolve_synthetic_spread(pao_services, order_def, leg_props, synth_spec);
return new SpreaderManagerForTest (order_key, order_def, pao_services, leg_props);
}
@@ -381,7 +382,8 @@ SpreaderManagerForTest* create_spreader_manager_n_legs (bts::orderman::OrderKey
SpreaderPreActivationOrderServices::TestOnlySpreaderPreActivationOrderServices testonly_spreader_pao_services = _create_spreader_pao_services(synthetic_security);
SpreaderPreActivationOrderServices pao_services (&testonly_spreader_pao_services);
std::vector<LegPropertyData> leg_props;
SpreaderUtils::resolve_synthetic_spread(pao_services, order_def, leg_props);
api::ContractSpecification synth_spec;
SpreaderUtils::resolve_synthetic_spread(pao_services, order_def, leg_props, synth_spec);
return new SpreaderManagerForTest (order_key, order_def, pao_services, leg_props);
}