Compare commits

...
9 changed files with 75 additions and 16 deletions

No files matched your search

@@ -10,13 +10,13 @@ namespace mbts.spark {
public override string man_page { get; } = string.Empty;
public override bool get_value(LegSpreaderParamsTuple leg_tup) =>
leg_tup.leg_params.EnableHedging;
leg_tup.leg_params.SendHedge is null || leg_tup.leg_params.SendHedge.Val;
public override void set_value(LegSpreaderParamsTuple leg_tup, bool value) =>
leg_tup.leg_params.EnableHedging = value;
public override bool has_errors(IReadOnlyCollection<LegSpreaderParamsTuple> leg_tups) =>
!leg_tups.Any(lt => lt.leg_params.EnableHedging);
public override void set_value(LegSpreaderParamsTuple leg_tup, bool value) {
if (leg_tup.leg_params.SendHedge is null)
leg_tup.leg_params.SendHedge = new bts.spark.NullableBoolean();
leg_tup.leg_params.SendHedge.Val = value;
}
}
}
}
}
@@ -0,0 +1,21 @@
using mbts.ui.spark;
using System;
namespace mbts.spark {
partial class SyntheticEditorVM {
class LeanOffsetTicksModel : RowModelBase<int> {
public override string display_name { get; } = "Lean Offset Ticks";
public override string help_text { get; } = "Send hedge this many ticks away from the opposite market.";
public override string man_page { get; } = string.Empty;
public override int get_value(LegSpreaderParamsTuple leg_tup) =>
leg_tup.leg_params.QuoteParams?.LeanOffsetTicks ?? 0;
public override void set_value(LegSpreaderParamsTuple leg_tup, int value) {
if (leg_tup.leg_params.QuoteParams is null)
leg_tup.leg_params.QuoteParams = new bts.spark.QuoteParams();
leg_tup.leg_params.QuoteParams.LeanOffsetTicks = value;
}
}
}
}
@@ -223,9 +223,10 @@ namespace mbts.spark {
_quantity_model,
_price_mult_model,
is_quote_model,
//new EnableHedgeModel(), //TAHA_SPREADER
new EnableHedgeModel(), //TAHA_SPREADER
new HedgeRatioModel(),
//new MinLeanQtyModel(), //TAHA_SPREADER
new LeanOffsetTicksModel(),
//new QuoteHiddenModel(),
new QuoteQueueHolderModel(),
new MarketDataTypeModel(),
@@ -37,6 +37,14 @@ public:
double size_multiplier() const { return _leg_contract.quantity(); }
double tick_size() const { return _leg_contract.security().contract_spec().low_tick(); }
bool is_active_quoting() const {return _leg_params.is_active_quoting();}
bool send_hedge() const {
// for backwards compat, if its unset, then hedges are sent
return !_leg_params.has_send_hedge() || _leg_params.send_hedge().val();
}
// if both quoting and hedging are turned off, this results false, else true
bool is_active_trading() const{
return is_active_quoting() || send_hedge();
}
bool is_net_change() const{
return _price_calc==bts::api::SyntheticContract::PRICECALC_NET_CHANGE;
}
@@ -162,7 +162,8 @@ bool SingleLegQuoter::accept_modifications() const {
_worker->state() == QuoterState::WORKING;
}
void SingleLegQuoter::_incorporate_other_leg_fill (size_t, Quantity hedge_reduction){
_price_quantity_state.add_hedged_reduction (hedge_reduction);
if(_this_leg_data.send_hedge())
_price_quantity_state.add_hedged_reduction (hedge_reduction);
}
void SingleLegQuoter::_compute_quote(
Quantity target_qty,
@@ -79,6 +79,8 @@ void SpreaderBookkeepingData::total_fills (Quantity& out_quantity,
double avg_price = 0.0;
double fills = std::numeric_limits<double>::max();
for (const SpreaderLegData& leg_data : _leg_data){
if(!leg_data.leg_property_data().is_active_trading())
continue;
Quantity leg_fill_qty; Price leg_fill_price;
leg_data.total_fills(leg_fill_qty, leg_fill_price);
double leg_normalized_qty = static_cast<double>(leg_fill_qty.value()) /
@@ -727,6 +727,7 @@ public:
Quantity hedge_qty;
compute_driver(quote_target,quote_leg_data,hedge_leg_data,hedge_leg_book,
hedge_price,hedge_qty,quote_qty);
hedge_price = Price(offset_driver_price(hedge_price.value(),hedge_leg_data));
double out_price = (target_spread_price.value() - hedge_price.value() * hedge_leg_data.price_multiplier())/quote_leg_data.price_multiplier();
out_price = bts::securities::raw_round_to_quote_price (out_price, quote_leg_data.tick_size(), quote_leg_data.trading_side());
quote_price = Price(out_price);
@@ -784,6 +785,15 @@ public:
out_driver_vector[idx].set (hedge_price, hedge_qty, quote_qty);
}
}
static double offset_driver_price (double driver_price,
const LegPropertyData& driver_lp){
int offset_ticks = driver_lp.leg_params().quote_params().lean_offset_ticks();
double offset_price = offset_ticks * driver_lp.tick_size();
if(driver_lp.trading_side() == api::Side::SIDE_BUY)
return driver_price + offset_price;
else
return driver_price - offset_price;
}
// computes the quoting price from the leg drivers
// ie (spreader_price - sum (price_mult * price))/quoting_leg_mult
static Price compute_quoting_price_from_drivers(Price target_spread_price,
@@ -794,8 +804,11 @@ public:
size_t n_legs = driver_vector.size();
double sum = 0;
for (size_t idx = 0; idx < n_legs; idx++)
if (idx != quoting_leg_index)
sum += driver_vector[idx].driver_price().value() * spreader.get_leg_data (idx).price_multiplier();
if (idx != quoting_leg_index){
double driver_price = driver_vector[idx].driver_price().value();
driver_price = offset_driver_price(driver_price,spreader.get_leg_data(idx));
sum += driver_price * spreader.get_leg_data(idx).price_multiplier();
}
double rv = (target_spread_price.value() - sum)/quoting_leg_data.price_multiplier();
rv = bts::securities::raw_round_to_quote_price (rv, quoting_leg_data.tick_size(), quoting_leg_data.trading_side());
return Price(rv);
@@ -16,10 +16,14 @@ void HedgerStartStateWorker::on_transition (){
void HedgerStartStateWorker::init (Price price,
Quantity quantity){
_hedger->_price_quantity_state.re_init(price,quantity);
if(quantity.value() > 0){
_hedger->_place_order (price, quantity);
_hedger->transform_to_WAITING_FOR_FIRST_ACK ();
if(_hedger->_leg_property_data.send_hedge()){
if(quantity.value() > 0){
_hedger->_place_order (price, quantity);
_hedger->transform_to_WAITING_FOR_FIRST_ACK ();
}
}
else
_hedger->cancel_hedge();
}
void HedgerStartStateWorker::on_order_update(const SpreaderChildOrderState&){
bts_assert_msg (false, "HedgerStartStateWorker::on_order_update "
+11 -2
View File
@@ -19,6 +19,9 @@ message QuantityMeasure
message NullableQuantity{
uint32 quantity = 10;
}
message NullableBoolean{
bool val = 10;
}
// /*************************************************************************************************/
// /*************************************************************************************************/
// /*************************************Spreader Parameters*****************************************/
@@ -46,7 +49,8 @@ message LegSpreaderParams
PreHedgeParams pre_hedge_params = 50;
PostHedgeParams post_hedge_params = 60;
MarketDataType market_data_type = 70;
//reserve LegMarketDataCalculation leg_md_calc = 80;
//reserve LegMarketDataCalculation leg_md_calc = 80;
NullableBoolean send_hedge = 90;
}
// /*************************************************************************************************
@@ -76,6 +80,8 @@ message QuoteParams
uint32 n_queue_holder_orders=2000;
// this is the show quantity on the quoter order
NullableQuantity show_quantity = 2010;
int32 lean_offset_ticks = 2020;
QuoteTimeBasedThrottle time_based_throttle = 2030;
}
/*************************************Quote MuteZone***********************************
@@ -134,7 +140,10 @@ message QuoteInsideMarketDistanceThrottle
{
uint32 on_toward_distance = 10;
}
message QuoteTimeBasedThrottle{
uint32 delay_to_run = 10;
uint32 delay_to_improve = 20;
}
/*************************************Quote RepriceThrottled (unused)*******************************
(Stellar's sensitivity)
This parameter defines regions (wrt their distance from the inside market)