Compare commits

...
23 Commits
Author SHA1 Message Date
Eric Harding 5aab80aed6 Merged cave_paintings into prod 2018-10-29 16:34:49 -04:00
Eric Harding 12e7c82698 Merged prod into cave_paintings 2018-10-29 16:32:59 -04:00
Taha Afzal 0c4cdd0bc9 Merge branch 'net_change_final' into prod 2018-10-29 16:11:29 -04:00
Taha Afzal 00d8ea9322 Avg fill price reporting for net change spreads fixed 2018-10-28 22:25:34 -04:00
Taha Afzal a586b75226 case statamenet was missing the new state, settlement_populated fixed 2018-10-27 22:13:01 -04:00
John Colvin c6039723da Synthetic Editor - re-enable 'Market Data Calculation' param-row 2018-10-26 22:17:37 -04:00
Taha Afzal 6f26164072 net_change is done from the server side 2018-10-26 19:23:13 -04:00
Jake Norbut 7b01fdcb23 Merge branch 'prod' of bitbucket.org:bluetradesys/spark into prod 2018-10-26 14:25:41 -05:00
Jake Norbut d6df085d8e SPARK-1648 - My Windows, now with more Scrollbar 2018-10-26 14:25:31 -05:00
Kevin Darby c6f2fe9b13 Merged in nupkg (pull request #81)
added <PackageOutputPath> to spark_sdk/spark_sdk.csproj so the nupkg can be shipped with the build

Approved-by: Eric Harding <eric.harding@bluetradesys.com>
2018-10-26 18:28:59 +00:00
John Colvin c56b41bf47 add SoundNotifications toggle.conf 2018-10-26 11:35:47 -05:00
Jake Norbut 484c7a98a8 Sound crash fixed in both INotifier and SoundAnimationView (the preview sound) 2018-10-26 10:57:34 -05:00
Taha Afzal 559b6f8fd1 changed the state transition, so START->WAITING_FOR_DATA->WORKING 2018-10-25 21:12:43 -04:00
Taha Afzal 41fa3046f1 Added new spreader state WAITING_FOR_INIT_DATA, not hooked up though 2018-10-25 20:01:32 -04:00
Eric Harding fdf21c71bb Enable separate thread config for different market data channels 2018-10-25 12:49:10 -04:00
Eric Harding f03453f7c5 Let threads float by default. We will override to tune specific systems 2018-10-25 12:28:42 -04:00
Jake Norbut 9ebdb107fa fixing SODTime defaults 2018-10-25 10:28:38 -05:00
Eric Harding 057d5df6da Add --name to spark_vm_shell.sh 2018-10-24 17:24:30 -04:00
Eric Harding f539659ab5 Update ReleaseNotesParade (but leave disabled) 2018-10-24 17:07:55 -04:00
Eric Harding e4d9b902d8 Teach webserver.cpp where manual is 2018-10-24 17:03:23 -04:00
Eric Harding 9fb180ff20 Add --name to spark_vm_shell.sh 2018-10-24 16:26:43 -04:00
Eric Harding a6fde760ff Docs build 2018-10-24 16:08:57 -04:00
Kevin Darby c705867218 added <PackageOutputPath> to spark_sdk/spark_sdk.csproj so the nupkg can be shipped with the build 2018-10-10 18:06:12 -04:00
35 changed files with 363 additions and 99 deletions

No files matched your search

+1
View File
@@ -44,6 +44,7 @@ else ()
add_subdirectory(src/server/sparkd)
add_subdirectory(src/lib)
add_subdirectory(src/web)
add_subdirectory(doc/user)
add_subdirectory(src/sdk)
add_subdirectory(src/data_files)
+30
View File
@@ -0,0 +1,30 @@
cmake_minimum_required(VERSION 3.5)
project(doc)
include(${CMAKE_SOURCE_DIR}/tools/safe_dep_glob.cmake)
include(${CMAKE_SOURCE_DIR}/tools/Protobuf.cmake)
# DEPENDENCIES
set(DOC_GLOBS
*.md
*.jpeg
*.png
*.html
*.css
*.js
*.eot
favicon.ico
)
file (GLOB_RECURSE All_Deps RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${DOC_GLOBS})
update_deps_file("${All_Deps}")
# END DEPENDENCIES
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/web/docs/index.html
COMMAND /bin/bash ${CMAKE_CURRENT_SOURCE_DIR}/build.sh
ARGS ${CMAKE_BINARY_DIR}/web/docs/
COMMENT "Building Manual UI"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS ${All_Deps})
add_custom_target(doc_manual_bundle ALL DEPENDS ${CMAKE_BINARY_DIR}/web/docs/index.html)
@@ -1,18 +0,0 @@
@font-face {
font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 300;
src: local('Source Sans Pro Light'), local('SourceSansPro-Light'), url(../fonts/Source-Sans-Pro-300.ttf) format('truetype');
}
@font-face {
font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 400;
src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'), url(../fonts/Source-Sans-Pro-400.ttf) format('truetype');
}
@font-face {
font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 600;
src: local('Source Sans Pro SemiBold'), local('SourceSansPro-SemiBold'), url(../fonts/Source-Sans-Pro-600.ttf) format('truetype');
}
@@ -204,7 +204,7 @@ namespace mbts.spark {
new HedgeRatioModel(),
new QuoteHiddenModel(),
new MarketDataTypeModel(),
//new MarketDataCalculationModel(),
new MarketDataCalculationModel(),
new QuoteThrottleEnabledModel(quote_throttle_inside_ticks, quote_throttle_outside_ticks),
quote_throttle_inside_ticks,
quote_throttle_outside_ticks,
@@ -53,7 +53,7 @@ namespace bts.shell {
Configuration.get<bts.config.System>().config_port);
string temp = uristr;
if (uristr.StartsWith("bts://m/")) {
temp = uristr.Replace("bts://m/", http_base + "doc/manual/");
temp = uristr.Replace("bts://m/", http_base + "docs/");
}
else {
temp = uristr.Replace("bts://", http_base);
+15 -9
View File
@@ -53,18 +53,22 @@ namespace mbts.ui {
ToastNotificationController _toast_controller;
SoundNotificationPlayer _sound_player;
Dispatcher _dispatcher;
bool _toast_notifications_enabled, _sound_notifications_enabled = NotificationSettings.Default.sound_notification.enabled;
bool
_sound_notifications_enabled = Configuration.get<bts.config.toggles.SoundNotifications>().enabled,
_toast_notifications_enabled = Configuration.get<bts.config.toggles.ToastNotifications>().enabled;
[ImportingConstructor]
public Notifier(IBus bus, UserSettingsHub settings_hub) {
_disposer = new ThreadSafeDisposable(dispose_core);
Thread thread = new Thread(start) {
IsBackground = true,
Priority = ThreadPriority.BelowNormal,
Name = "BTSNotifications"
};
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
if (_sound_notifications_enabled || _toast_notifications_enabled) {
Thread thread = new Thread(start) {
IsBackground = true,
Priority = ThreadPriority.BelowNormal,
Name = "BTSNotifications"
};
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
}
void start() {
try {
@@ -102,7 +106,9 @@ namespace mbts.ui {
(_dispatcher = Dispatcher.CurrentDispatcher).UnhandledException += _on_dispatcher_UnhandledException;
Dispatcher.Run();
}
} catch (Exception ex) {
}
catch (NAudio.MmException) { }
catch (Exception ex) {
Log.assert(false, $"Exception in {Thread.CurrentThread.Name} thread: {ex}");
_disposer.Dispose();
}
+8 -6
View File
@@ -521,12 +521,14 @@
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ItemsControl}">
<Border
BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true"
>
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
<ScrollViewer HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Auto">
<Border
BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true"
>
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
</ScrollViewer>
</ControlTemplate>
</Setter.Value>
</Setter>
+1 -1
View File
@@ -77,7 +77,7 @@ namespace bts.spark
SparkCommand.create("Manual", Icons.Browser, SparkTags.ShowUri, new Uri("https://www.bluetradingsystems.com/documentation/"));
public static SparkCommand ShowReleaseNotes =>
SparkCommand.create("Release Notes", Icons.Browser, SparkTags.ShowUri, new Uri("bts://files/release_notes.txt"));
SparkCommand.create("Release Notes", Icons.Browser, SparkTags.ShowUri, new Uri("bts://docs/release_notes/"));
public static SparkCommand DoNothing =>
SparkCommand.create("Nothing", Icons.Support, SparkTags.NotImplemented);
@@ -28,7 +28,7 @@ namespace mbts.ui.controls {
new AnonymousValueConverter(obj =>
obj is SoundNotification.SystemSound s ?
EnumHelper.get_attribute<SoundNotification.SystemSound, LicenseAttribute>(s)?.link : null);
public static readonly DependencyProperty BusProperty =
WPFHelper.create_dp<IBus, SoundAnimationView>(nameof(Bus));
@@ -38,7 +38,11 @@ namespace mbts.ui.controls {
}
public static ICommand PreviewSoundCommand =>
new DelegateCommand<SoundNotification.SystemSound>(s => NAudioPlayer.create(s).play());
new DelegateCommand<SoundNotification.SystemSound>(s => {
try {
NAudioPlayer.create(s).play();
} catch (NAudio.MmException) { }
});
#region SoundTypes
public static readonly DependencyProperty SoundTypesProperty =
+1
View File
@@ -4,6 +4,7 @@
<TargetFrameworks>netstandard2.0;net471</TargetFrameworks>
<OutputType>Exe</OutputType>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageOutputPath>$(OutputPath)\net471</PackageOutputPath>
<IncludeSource>true</IncludeSource>
<IncludeSymbols>true</IncludeSymbols>
<TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage</TargetsForTfmSpecificBuildOutput>
+2 -2
View File
@@ -22,14 +22,14 @@ PublisherNamespace {
CMEOptions {
value {
feed_engine {
name: "default"
name: "mdp3feed"
# udp_socket_buffer_size: 425984
# channels_per_thread: 1
spin_time: 0
}
channel {
id: "*"
feed_engine: "default"
feed_engine: "mdp3feed"
use_tcp_replay: false
}
}
+4 -3
View File
@@ -1,7 +1,8 @@
Threads {
value {
thread_group {name_rx: "mdp3feed" core: 0}
thread_group {name_rx: "oman_orders" core: 1}
thread_group {name_rx: ".*" exclude:true core:0 core:1}
# thread_group {name_rx: "mdp3feed" core: 0}
# thread_group {name_rx: "oman_orders" core: 1}
# thread_group {name_rx: ".*" exclude:true core:0 core:1}
thread_group {name_rx: ".*" }
}
}
@@ -7,6 +7,6 @@ message OrdersSoftCleanupCutoff{
message SODTime{
// utc time
optional uint32 sod_hh = 20 [default=21];
optional uint32 sod_hh = 20 [default=15];
optional uint32 sod_mm = 30 [default=30];
}
+4
View File
@@ -28,6 +28,10 @@ message ToastNotifications {
optional bool enabled = 1 [default = false];
}
message SoundNotifications {
optional bool enabled = 1 [default = true];
}
message VolumeAtPrice{
optional bool enabled = 1 [default = true];
}
@@ -5,6 +5,7 @@
#include "lib/orderman/orderman_utils/orderman_common.h"
#include "lib/orderman/orders/spreader_orders/spreader/SpreaderLegData.h" // fix this (not needed, all the headers can be fwd ref's)
#include "lib/orderman/orders/spreader_orders/spreader_states/SpreaderState.h"
#include "lib/orderman/events/SettlementUpdateEvent.h"
namespace bts {
namespace api {namespace orderman {class OrderDefinition;}}
@@ -34,6 +35,8 @@ public:
virtual void on_cancel() = 0;
// 6. on market data update (support late joiners)
virtual void on_book(const Book&,PerfTrace &) = 0;
// 15. settlement price update
virtual void on_settlement_price(const SettlementUpdateEvent&) = 0;
// 7. time event called by the infrastructure
virtual void on_time(const TimeStamp&) = 0;
// 8. when a quoter order ack from the exchange has an error
@@ -25,7 +25,11 @@ _order_services(nullptr),
_curr_timestamp(),
_last_check_termination_timestamp(),
_state_worker(nullptr),
_start_state_worker(this), _working_state_worker(this), _waiting_for_cancel_all_state_worker(this), _end_state_worker(this){
_start_state_worker(this),
_waiting_for_initial_data_state_worker(this),
_working_state_worker(this),
_waiting_for_cancel_all_state_worker(this),
_end_state_worker(this){
_transform_to_START();
}
SpreaderOrder::~SpreaderOrder () {}
@@ -108,13 +112,8 @@ void SpreaderOrder::_on_settlement_update(const SettlementUpdateEvent&
"key:{} sec_key:{} state:{} settlement:{}",
key(), settlement_event.key(),
static_cast<int>(_state_worker->state()),
settlement_event.settlement_price.price());
// this is a key->index lookup
SpreaderLegData& md_leg =
_bookkeeping_data().get_leg_data(settlement_event.key());
md_leg.update_settlement_price(settlement_event.settlement_price);
bts::PerfTrace trace;
_state_worker->on_book (md_leg.book(),trace);
settlement_event.settlement_price.price());
_state_worker->on_settlement_price(settlement_event);
}
void SpreaderOrder::_on_child_order_update(const OrderStateUpdateEvent& ord_ev){
auto trace = ord_ev.trace;
@@ -194,8 +193,12 @@ void SpreaderOrder::_transform_to_START(){
bts_assert (_state_worker == nullptr);
_switch_state (&_start_state_worker);
}
void SpreaderOrder::_transform_to_WAITING_FOR_INITIAL_DATA(){
bts_assert (_state_worker->state()==SpreaderState::START);
_switch_state (&_waiting_for_initial_data_state_worker);
}
void SpreaderOrder::_transform_to_WORKING(){
bts_assert(_state_worker->state() == SpreaderState::START);
bts_assert(_state_worker->state() == SpreaderState::WAITING_FOR_INIT_DATA);
_switch_state(&_working_state_worker);
}
void SpreaderOrder::_transform_to_WAITING_FOR_CANCEL_ALL(){
@@ -332,7 +335,7 @@ void SpreaderOrder::_compute_hedge_price_quantity(size_t filled_leg_index,
SpreaderLegData& filled_leg_data = _bookkeeping_data().get_leg_data(filled_leg_index);
SpreaderLegData& hedged_leg_data = _bookkeeping_data().get_leg_data(hedge_leg_index);
if (_bookkeeping_data().n_legs() == 2)
SpreaderUtils::compute_hedge_price_size_2_legs (_bookkeeping_data().price(),
SpreaderUtils::compute_hedge_price_size_2_legs (_bookkeeping_data().effective_price(),
filled_leg_data.leg_property_data(),
fill_price,
fill_quantity,
@@ -357,15 +360,15 @@ void SpreaderOrder::_compute_hedge_price_quantity(size_t filled_leg_index,
Quantity(hedge_quantity));
}
void SpreaderOrder::_report_state (){
if (_activated()){
SpreaderBookkeepingData& bookkeeping_data = _bookkeeping_data();
if (_activated()){
SpreaderBookkeepingData& bookkeeping_data = _bookkeeping_data();
auto& reported_state = bookkeeping_data.reported_state();
api::orderman::OrderStatus status = _get_order_status ();
if(bookkeeping_data.inited_new()){
if(bookkeeping_data.inited_new()){
Quantity filled_qty; Price avg_filled_price;
bookkeeping_data.total_fills(filled_qty, avg_filled_price);
reported_state.set_status(status);
reported_state.set_price(bookkeeping_data.price().value());
reported_state.set_price(bookkeeping_data.input_price().value());
reported_state.set_quantity(bookkeeping_data.quantity().value());
reported_state.set_filled_quantity(filled_qty.value());
reported_state.set_avg_price(avg_filled_price.value());
@@ -394,6 +397,7 @@ bts::api::orderman::OrderStatus SpreaderOrder::_get_order_status () const{
bts::api::orderman::OrderStatus::ORDER_STATUS_CANCELED :
bts::api::orderman::OrderStatus::ORDER_STATUS_COMPLETED;
case SpreaderState::START:
case SpreaderState::WAITING_FOR_INIT_DATA:
return bts::api::orderman::OrderStatus::ORDER_STATUS_INACTIVE;
default:
bts_assert(false);
@@ -407,4 +411,31 @@ void SpreaderOrder::_send_check_termination(bool force){
_state_worker->on_check_termination();
}
}
bool SpreaderOrder::_contains_net_change_leg(){
for (size_t l_idx = 0; l_idx < _bookkeeping_data().n_legs(); l_idx++){
const LegPropertyData& leg_data =
_bookkeeping_data().get_leg_data(l_idx).leg_property_data();
if(leg_data.leg_md_calc()==bts::spark::LegSpreaderParams::NET_CHANGE)
return true;
}
return false;
}
Price SpreaderOrder::_compute_effective_price (Price input_price){
double rv = 0;
if(_contains_net_change_leg()){
for (size_t l_idx = 0; l_idx < _bookkeeping_data().n_legs(); l_idx++){
const SpreaderLegData& leg_data = _bookkeeping_data().get_leg_data(l_idx);
if(leg_data.leg_property_data().leg_md_calc()==bts::spark::LegSpreaderParams::NET_CHANGE){
if (!leg_data.settlement_populated())
return Price(os::nan());
else
rv += leg_data.leg_property_data().price_multiplier() *
leg_data.settlement_price().value();
}
}
return Price(input_price.value()+rv);
}
else
return input_price;
}
}}
@@ -9,6 +9,7 @@
#include "lib/orderman/orders/spreader_orders/spreader/SpreaderBookkeepingData.h"
#include "lib/orderman/orders/spreader_orders/spreader/ISpreaderManager.h"
#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/SpreaderWaitingForCancelAllStateWorker.h"
#include "lib/orderman/orders/spreader_orders/spreader_states/SpreaderEndStateWorker.h"
@@ -29,6 +30,7 @@ class SettlementUpdateEvent;
class SpreaderOrder : public Order, public ISpreaderManager
{
friend class SpreaderStartStateWorker;
friend class SpreaderWaitingForInitialDataStateWorker;
friend class SpreaderWorkingStateWorker;
friend class SpreaderWaitingForCancelAllStateWorker;
friend class SpreaderEndStateWorker;
@@ -68,6 +70,7 @@ private:
// current state
ISpreaderStateWorker* _state_worker;
SpreaderStartStateWorker _start_state_worker;
SpreaderWaitingForInitialDataStateWorker _waiting_for_initial_data_state_worker;
SpreaderWorkingStateWorker _working_state_worker;
SpreaderWaitingForCancelAllStateWorker _waiting_for_cancel_all_state_worker;
SpreaderEndStateWorker _end_state_worker;
@@ -131,6 +134,7 @@ private:
// State Transformations ////////////////////
/////////////////////////////////////////////
void _transform_to_START();
void _transform_to_WAITING_FOR_INITIAL_DATA();
void _transform_to_WORKING();
void _transform_to_WAITING_FOR_CANCEL_ALL();
// optionally parameter to state the end reason
@@ -193,8 +197,12 @@ private:
return *_bookkeeping_data_ptr;
}
// just sets the price and qty in the bookkeeping data
void _set_price_quantity (Price price, Quantity quantity) {
_bookkeeping_data().update_order (price, quantity);
void _set_price_quantity (Price input_price,
Quantity quantity) {
Price effective_price = _compute_effective_price(input_price);
_bookkeeping_data().update_order (input_price,
effective_price,
quantity);
}
// returns the equivelant order status of the spreader order
bts::api::orderman::OrderStatus _get_order_status () const;
@@ -223,6 +231,15 @@ private:
// when there's an order update, as well as on
// a periodic bases
void _send_check_termination(bool force);
// if any leg is priced on net_change
// this teturns true
bool _contains_net_change_leg();
// computes the effective price of the spreader order
// if any of of the legs are in terms of net_change
// this function offsets the effective price by that
// (if settlements are not available returns nan)
// Otherwise effectiv_price==order_price.
Price _compute_effective_price (Price order_price);
// testing only //////////////////
// this provides direct way to inject
// data into the spreader, as well as
@@ -247,7 +264,11 @@ public:
_on_child_order_update (ord_ev);
}
void test_only_on_init_new(const bts::api::orderman::OrderDefinition& order_def, const SpreaderPreActivationOrderServices& pao_services) {_on_init_new(order_def, pao_services);}
void test_only_on_activate(Price price, Quantity quantity, SpreaderOrderServices& order_services) {_on_activate(price, quantity, order_services);}
void test_only_on_activate(Price price,
Quantity quantity,
SpreaderOrderServices& order_services) {
_on_activate(price, quantity, order_services);
}
void test_only_on_time (TimeStamp){}
};
}}
@@ -71,7 +71,11 @@ void SpreaderBookkeepingData::total_fills (Quantity& out_quantity,
leg_data.total_fills(leg_fill_qty, leg_fill_price);
double normalized_qty = std::abs(static_cast<double>(leg_fill_qty.value()) / leg_data.leg_property_data().size_multiplier());
fills = normalized_qty < fills ? normalized_qty : fills;
avg_price += leg_fill_price.value() * leg_data.leg_property_data().price_multiplier();
if(leg_data.leg_property_data().leg_md_calc()==bts::spark::LegSpreaderParams::NET_CHANGE)
avg_price += (leg_fill_price.value()-leg_data.settlement_price().value()) *
leg_data.leg_property_data().price_multiplier();
else
avg_price += leg_fill_price.value() * leg_data.leg_property_data().price_multiplier();
}
out_quantity = Quantity(fills);
out_price = Price(avg_price);
@@ -39,7 +39,8 @@ private:
// state thats sent out in report (its kept here amd modified
// vs creating a new one everytime)
bts::api::orderman::OrderState _reported_state;
Price _price;
Price _input_price;
Price _effective_price;
Quantity _quantity;
public:
SpreaderBookkeepingData (ISpreaderManager& spreader_manager,
@@ -62,7 +63,8 @@ public:
size_t n_legs() const { return _n_legs; }
bool all_legs_resolved() const {return n_legs() > 0;}
const api::orderman::OrderDefinition& order_def() const {return _order_def;}
Price price () const {return _price;}
Price input_price () const {return _input_price;}
Price effective_price () const {return _effective_price;}
Quantity quantity () const {return _quantity;}
// gets leg data from leg's sec key
SpreaderLegData& get_leg_data (SecurityKey security_key){
@@ -111,9 +113,16 @@ public:
// the size and price ratio, across all legs)
void total_fills (Quantity& out_quantity, Price& out_price) const;
// updates the price, qty of the spreader order
void update_order (Price price, Quantity quantity){
_price = price;
_quantity = quantity;
void update_order (Price input_price,
Quantity quantity){
update_order(input_price, input_price, quantity);
}
void update_order(Price input_price,
Price effective_price,
Quantity quantity){
_input_price=input_price;
_effective_price=effective_price;
_quantity=quantity;
}
bts::api::orderman::OrderState& reported_state(){
return _reported_state;
@@ -121,5 +130,8 @@ public:
bool inited_new () const{
return _inited_new;
}
bool has_effective_price() const{
return !os::is_nan(_effective_price.value());
}
};
}}
@@ -59,7 +59,8 @@ public:
SingleLegQuoter& quoter() {return _quoter;}
const SingleLegQuoter& quoter() const {return _quoter;}
const bts::orderman::Book& book () const {return _book;}
//md::Price settlement_price() const {return _settlement_price;}
Price settlement_price() const {return Price(_settlement_price.price());}
bool settlement_populated() const {return !os::is_nan(_settlement_price.price());}
SpreaderChildOrderState& order_update_message () {return _quoter_child_order_state;}
bts::orderman::OrderKey key() {return _quoter_child_order_state.order_key();}
bts::orderman::OrderKey order_key() {return _quoter_child_order_state.order_key();}
@@ -107,7 +108,7 @@ public:
SpreaderUtils::copy_book(book,
_settlement_price,
_leg_property_data.md_type(),
_leg_property_data.leg_md_calc(),
bts::spark::LegSpreaderParams::BOOK,
_book);
}
void update_settlement_price(md::IntPrice price){
@@ -115,7 +116,7 @@ public:
SpreaderUtils::copy_book(_book,
_settlement_price,
_leg_property_data.md_type(),
_leg_property_data.leg_md_calc(),
bts::spark::LegSpreaderParams::BOOK,
_book);
}
@@ -21,13 +21,14 @@ void SpreaderEndStateWorker::on_init_recovered(const bts::api::orderman::OrderRe
const SpreaderPreActivationOrderServices&){
bts_assert_msg (false, "SpreaderEndStateWorker::on_init_new is an illegal operation");
}
void SpreaderEndStateWorker::on_activate(Price price, Quantity quantity,
void SpreaderEndStateWorker::on_activate(Price price,
Quantity quantity,
SpreaderOrderServices&){
// this can only happen if the security could not be resolved
// resulting in START->END. however on_active could still
// be called
bts_assert (!_spreader->_bookkeeping_data().all_legs_resolved());
_spreader->_bookkeeping_data().update_order(price, quantity);
_spreader->_set_price_quantity(price, quantity);
}
void SpreaderEndStateWorker::on_update(Price, Quantity){
}
@@ -35,6 +36,8 @@ void SpreaderEndStateWorker::on_cancel(){
}
void SpreaderEndStateWorker::on_book(const Book&,PerfTrace&){
}
void SpreaderEndStateWorker::on_settlement_price(const SettlementUpdateEvent&){
}
void SpreaderEndStateWorker::on_time(const TimeStamp&){
}
void SpreaderEndStateWorker::on_quoter_order_error(SpreaderLegData&){
@@ -21,6 +21,7 @@ public:
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,
@@ -66,9 +66,11 @@ void SpreaderStartStateWorker::on_init_recovered(const bts::api::orderman::Order
std::string msg = "Recovered spreader orders (from last session) are cancelled";
_spreader->_transform_to_END (&msg);
}
void SpreaderStartStateWorker::on_activate(Price price, Quantity quantity, SpreaderOrderServices& order_services){
void SpreaderStartStateWorker::on_activate(Price price,
Quantity quantity,
SpreaderOrderServices& order_services){
// 1. update price, qty
_spreader->_bookkeeping_data().update_order (price, quantity);
_spreader->_set_price_quantity (price, quantity);
// 2. activate order builders
for (size_t l_idx = 0; l_idx < _spreader->_bookkeeping_data().n_legs(); l_idx++)
{
@@ -103,18 +105,8 @@ void SpreaderStartStateWorker::on_activate(Price price, Quantity quantity, Sprea
// 6. sub to time
order_services.order_services().time_change.sub([this](const bts::mercury::TimerEvent& t_event){_spreader->_on_time(t_event);});
}
// 7. init all quoters (this is when the quoters get assigned a price, qty for
// the first time) (this could have been done on the on_transition of WORKING state.
// that way, in the START state there would be no active quoters, which technically
// is happening right before transfer is being controlled to WORKING state)
for (size_t l_idx = 0; l_idx < _spreader->_bookkeeping_data_ptr->n_legs(); l_idx++)
{
SpreaderLegData& leg_data = _spreader->_bookkeeping_data().get_leg_data(l_idx);
if (leg_data.leg_property_data().is_active_quoting())
leg_data.quoter().one_time_activate(price, quantity);
}
// 8. transofrm state
_spreader->_transform_to_WORKING ();
// quoters are init'ed in the next state
_spreader->_transform_to_WAITING_FOR_INITIAL_DATA();
}
void SpreaderStartStateWorker::on_update(Price, Quantity){
bts_assert_msg (false, "SpreaderStartStateWorker::on_update is an illegal operation");
@@ -128,6 +120,10 @@ void SpreaderStartStateWorker::on_cancel(){
void SpreaderStartStateWorker::on_book(const bts::orderman::Book&,PerfTrace &){
bts_assert_msg (false, "SpreaderStartStateWorker::on_book is an illegal operation");
}
void SpreaderStartStateWorker::on_settlement_price(const SettlementUpdateEvent&){
bts_assert_msg (false, "SpreaderStartStateWorker::on_settlement_price "
"is an illegal operation");
}
void SpreaderStartStateWorker::on_time(const TimeStamp&){
bts_assert_msg (false, "SpreaderStartStateWorker::on_time is an illegal operation");
}
@@ -26,7 +26,8 @@ public:
void on_update(Price, Quantity) override;
void on_cancel() override;
void on_book(const Book&,PerfTrace &) override;
void on_time(const TimeStamp&) override;
void on_time(const TimeStamp&) override;
void on_settlement_price(const SettlementUpdateEvent&) override;
void on_quoter_order_error(SpreaderLegData& leg_data) override;
void on_quoter_order_fill(SpreaderLegData& leg_data,
PerfTrace &) override;
@@ -6,6 +6,8 @@ enum class SpreaderState
{
// pre init state
START,
// waiting for initial data such as settlements (in some case)
WAITING_FOR_INIT_DATA,
// after the first connection, the general waiting state
WORKING,
// waiting for all quoters and hedgers to be done
@@ -42,6 +42,8 @@ void SpreaderWaitingForCancelAllStateWorker::on_time(const TimeStamp& ts){
_spreader->_transform_to_END ();
}
}
void SpreaderWaitingForCancelAllStateWorker::on_settlement_price(const SettlementUpdateEvent&){
}
void SpreaderWaitingForCancelAllStateWorker::on_quoter_order_error(SpreaderLegData& leg_data){
leg_data.quoter().update_order_status (leg_data.order_update_message());
}
@@ -24,6 +24,7 @@ public:
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,
@@ -0,0 +1,109 @@
#include "SpreaderWaitingForInitialDataStateWorker.h"
#include "lib/orderman/orders/spreader_orders/SpreaderOrder.h"
namespace bts {
namespace orderman {
SpreaderWaitingForInitialDataStateWorker::SpreaderWaitingForInitialDataStateWorker (SpreaderOrder* spreader)
:
_spreader(spreader){
}
SpreaderState SpreaderWaitingForInitialDataStateWorker::state() const {
return SpreaderState::WAITING_FOR_INIT_DATA;
}
void SpreaderWaitingForInitialDataStateWorker::on_transition (){
if(!_spreader->_contains_net_change_leg()){
_go_to_working();
}
}
void SpreaderWaitingForInitialDataStateWorker::on_init_new(api::orderman::OrderDefinition const&,
const SpreaderPreActivationOrderServices&){
bts_assert_msg (false, "SpreaderWaitingForInitialDataStateWorker::"
"on_init_new is an illegal operation");
}
void SpreaderWaitingForInitialDataStateWorker::on_init_recovered(
const bts::api::orderman::OrderRecord&,
const SpreaderPreActivationOrderServices&){
bts_assert_msg (false, "SpreaderWaitingForInitialDataStateWorker::on_init_new "
"is an illegal operation");
}
void SpreaderWaitingForInitialDataStateWorker::on_activate(Price,
Quantity,
SpreaderOrderServices&){
bts_assert_msg (false, "SpreaderWaitingForInitialDataStateWorker::"
"on_activate is an illegal operation");
}
void SpreaderWaitingForInitialDataStateWorker::on_update(Price,
Quantity){
// spreader can not accept modification
// right now (for netchange spreaders this will be such
// a such a short time period that it should not matter)
LOG(OrderMan, Warn, "SpreaderWaitingForInitialDataStateWorker::"
"on_update key:{}, order change rejected",
_spreader->key());
}
void SpreaderWaitingForInitialDataStateWorker::on_cancel(){
_spreader->_transform_to_END();
}
void SpreaderWaitingForInitialDataStateWorker::on_book(const Book& book,
PerfTrace&){
SpreaderBookkeepingData& bookkeeping_data = _spreader->_bookkeeping_data();
SpreaderLegData& md_leg = bookkeeping_data.get_leg_data(book.security_key());
md_leg.update_book(book);
}
void SpreaderWaitingForInitialDataStateWorker::on_settlement_price(
const SettlementUpdateEvent& settlement_event){
// if it did not contrain a net change leg
// on transition would have moved to working
bts_assert(_spreader->_contains_net_change_leg());
SpreaderBookkeepingData& bookkeeping_data = _spreader->_bookkeeping_data();
SpreaderLegData& md_leg = bookkeeping_data.get_leg_data(settlement_event.security_key);
md_leg.update_settlement_price(settlement_event.settlement_price);
_spreader->_set_price_quantity(bookkeeping_data.input_price(),
bookkeeping_data.quantity());
if(bookkeeping_data.has_effective_price())
_go_to_working ();
}
void SpreaderWaitingForInitialDataStateWorker::on_time(const TimeStamp&){
}
void SpreaderWaitingForInitialDataStateWorker::on_quoter_order_error(SpreaderLegData&){
bts_assert_msg (false, "SpreaderWaitingForInitialDataStateWorker::"
"on_quoter_order_error is an illegal operation");
}
void SpreaderWaitingForInitialDataStateWorker::on_quoter_order_fill(SpreaderLegData&,
PerfTrace&){
bts_assert_msg (false, "SpreaderWaitingForInitialDataStateWorker::"
"on_quoter_order_fill is an illegal operation");
}
void SpreaderWaitingForInitialDataStateWorker::on_quoter_order_status_update(SpreaderLegData&){
bts_assert_msg (false, "SpreaderWaitingForInitialDataStateWorker::"
"on_quoter_order_status_update is an illegal operation");
}
void SpreaderWaitingForInitialDataStateWorker::on_hedger_order_error(SingleFillHedger&){
bts_assert_msg (false, "SpreaderWaitingForInitialDataStateWorker::"
"on_hedger_order_error is an illegal operation");
}
void SpreaderWaitingForInitialDataStateWorker::on_hedger_order_update(SingleFillHedger&){
bts_assert_msg (false, "SpreaderWaitingForInitialDataStateWorker::"
"on_hedger_order_update is an illegal operation");
}
void SpreaderWaitingForInitialDataStateWorker::on_check_termination(){
}
void SpreaderWaitingForInitialDataStateWorker::on_quoter_irrecoverable_error (){
bts_assert_msg (false, "SpreaderWaitingForInitialDataStateWorker::"
"on_quoter_irrecoverable_error is an illegal operation");
}
void SpreaderWaitingForInitialDataStateWorker::_init_quoters(){
Price effective_price = _spreader->_bookkeeping_data().effective_price();
Quantity quantity = _spreader->_bookkeeping_data().quantity();
for (size_t l_idx = 0; l_idx < _spreader->_bookkeeping_data().n_legs(); l_idx++){
SpreaderLegData& leg_data = _spreader->_bookkeeping_data().get_leg_data(l_idx);
if (leg_data.leg_property_data().is_active_quoting())
leg_data.quoter().one_time_activate(effective_price, quantity);
}
}
void SpreaderWaitingForInitialDataStateWorker::_go_to_working(){
_init_quoters();
_spreader->_transform_to_WORKING();
}
}}
@@ -0,0 +1,43 @@
#pragma once
#include "lib/orderman/orders/spreader_orders/ISpreaderStateWorker.h"
namespace bts {
namespace orderman {
class SpreaderOrder;
// START state leads to this. Here, the spreader waits for data
// that is needed to start the machinery, ex settlement prices
// if the legs are in net change mode
class SpreaderWaitingForInitialDataStateWorker : public ISpreaderStateWorker
{
private:
SpreaderOrder* const _spreader;
public:
SpreaderWaitingForInitialDataStateWorker (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 _init_quoters();
void _go_to_working();
};
}}
@@ -29,11 +29,12 @@ void SpreaderWorkingStateWorker::on_activate(Price, Quantity,
void SpreaderWorkingStateWorker::on_update(Price price, Quantity quantity){
if (_spreader->_quoters_can_accept_modification()){
_spreader->_set_price_quantity (price, quantity);
Price effective_price = _spreader->_bookkeeping_data().effective_price();
// updating all active quoters, nothing to do with the hedgers
for (size_t q_idx = 0; q_idx < _spreader->_bookkeeping_data().n_legs(); q_idx++){
SpreaderLegData& leg_data = _spreader->_bookkeeping_data().get_leg_data(q_idx);
if (leg_data.leg_property_data().is_active_quoting())
leg_data.quoter().update_order_price_quantity (price, quantity);
leg_data.quoter().update_order_price_quantity (effective_price, quantity);
}
}
}
@@ -45,7 +46,8 @@ void SpreaderWorkingStateWorker::on_book(const Book& book,PerfTrace &trace){
SpreaderBookkeepingData& bookkeeping_data = _spreader->_bookkeeping_data();
// this is a key->index lookup
SpreaderLegData& md_leg = bookkeeping_data.get_leg_data(book.security_key());
// updating md state (this is the only place where its done)
// updating md state (this and SpreaderWaitingForInitialDataStateWorker
// are the only place where its done)
md_leg.update_book(book);
// sending md to all quoters
for (size_t q_idx = 0; q_idx < bookkeeping_data.n_legs(); q_idx++){
@@ -57,6 +59,8 @@ void SpreaderWorkingStateWorker::on_book(const Book& book,PerfTrace &trace){
for (size_t h_idx = 0; h_idx < md_leg.n_hedgers(); h_idx++)
md_leg.get_hedger(h_idx).on_book(book,trace);
}
void SpreaderWorkingStateWorker::on_settlement_price(const SettlementUpdateEvent&){
}
void SpreaderWorkingStateWorker::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++){
@@ -23,6 +23,7 @@ public:
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,
@@ -464,7 +464,7 @@ void verify_basic_spreader_state (SpreaderOrder& spreader, SpreaderState state,
{
REQUIRE(spreader.test_only_func_spreader_state() == state);
SpreaderBookkeepingData& spreader_data = spreader.test_only_func_spreader_full_data ();
REQUIRE (spreader_data.price() == price);
REQUIRE (spreader_data.effective_price() == price);
REQUIRE (spreader_data.quantity() == quantity);
}
void validate_leg_property_data (const LegPropertyData& leg_property_data, size_t leg_index, const bts::api::ContractLeg& contract_leg, const bts::spark::LegSpreaderParams&, api::Side trading_side)
+4
View File
@@ -250,6 +250,7 @@ namespace http {
std::string config = "/config";
std::string files = "/files";
std::string perf_trace = "/perf_trace";
std::string docs = "/docs";
if (resource.compare(0, config.size(), config) == 0) {
return _conf + resource.substr(config.size());
@@ -260,6 +261,9 @@ namespace http {
else if (resource.compare(0, perf_trace.size(), perf_trace) == 0) {
return os::sparkd_wd() + "/data_files" + resource;
}
else if (resource.compare(0, docs.size(), docs) == 0) {
return os::sparkd_wd() + "/web" + resource;
}
return web_ui_path(os::get_install_path()) / resource;
}
@@ -64,7 +64,7 @@ const onixs::FeedEngineSettings feed_engine_settings_from_config(const CMEOption
result.socketBufferSize(settings.udp_socket_buffer_size());
auto affinity = threading::get_affinity("mdp3feed");
auto affinity = threading::get_affinity(settings.name());
for (auto& core : affinity) {
result.threadAffinity().cpus().insert(core);
}
@@ -101,14 +101,6 @@ map<string,onixs::FeedEngineSettings> create_feed_engine_settings(const std::vec
}
}
// If a channel asks for defaults ensure it exists.
if (settings.count("default") == 0) {
size_t channels_using_default = count_engine_uses(channels, "default");
if (channels_using_default > 0) {
settings["default"] = feed_engine_settings_from_config(CMEOptions::FeedEngineSettings(), channels_using_default);
}
}
return settings;
}
+2
View File
@@ -20,6 +20,8 @@ docker run \
-u $UID \
-v /home:/home \
-e DISPLAY=$DISPLAY \
--name bts \
-d \
-t bluetradingsystems/linux_docker \
/bin/bash -c "(sudo /usr/sbin/sshd) & (cd ~ && $DIR/../externals/linux/bin/unison -socket 8080) & /bin/bash --login"