Compare commits
1
Commits
development
...
sniper
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d942676765 |
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 //////////////////////////////
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
+150
@@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}}
|
||||
+42
@@ -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;
|
||||
};
|
||||
}}
|
||||
+10
-3
@@ -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
|
||||
|
||||
+6
-2
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user