Compare commits

...
10 Commits
13 changed files with 96 additions and 77 deletions

No files matched your search

@@ -14,6 +14,9 @@ namespace mbts.ui
{
return random.NextDouble() * (maxValue - minValue) + minValue;
}
public static bool NextBool(this Random random, int truePercentage = 50) {
return random.NextDouble() < (truePercentage / 100.0);
}
}
+8 -11
View File
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Reactive.Linq;
@@ -43,9 +44,9 @@ namespace bts.api.core {
public class TableUpdate<T, TKey> where TKey : IEquatable<TKey> {
readonly Dictionary<TKey, T> _state;
ImmutableDictionary<TKey, T> _state;
internal TableUpdate(Dictionary<TKey, T> init, IReadOnlyList<T> added, IReadOnlyList<T> removed) {
internal TableUpdate(ImmutableDictionary<TKey, T> init, IReadOnlyList<T> added, IReadOnlyList<T> removed) {
_state = init;
this.added = added;
this.removed = removed;
@@ -59,14 +60,10 @@ namespace bts.api.core {
this.update(update.removed, update.added, update.key);
internal TableUpdate<T, TKey> update(IReadOnlyList<T> removed, IReadOnlyList<T> added, Func<T, TKey> key) {
var table = new TableUpdate<T, TKey>(new Dictionary<TKey, T>(_state), added, removed);
foreach (var i in removed) {
table._state.Remove(key(i));
}
foreach (var item in added) {
table._state.Add(key(item), item);
}
return table;
var builder = _state.ToBuilder();
builder.RemoveRange(removed.Select(i => key(i)));
builder.AddRange(added.Select(i => new KeyValuePair<TKey, T>(key(i), i)));
return new TableUpdate<T, TKey>(builder.ToImmutableDictionary(), added, removed);
}
internal TableUpdate<T, TKey> as_snapshot() {
@@ -102,7 +99,7 @@ namespace bts.api.core {
public static IObservable<TableUpdate<T,TKey>> Table<T,TKey>(this IObservable<Update<T,TKey>> source) where TKey : IEquatable<TKey> =>
source.Scan(
new TableUpdate<T,TKey>(new Dictionary<TKey, T>(), new List<T>(), new List<T>()),
new TableUpdate<T,TKey>(ImmutableDictionary<TKey,T>.Empty, new List<T>(), new List<T>()),
(table, update) => table.update(update));
public static IObservable<TableUpdate<T,TKey>> Cache<T, TKey>(this IObservable<TableUpdate<T, TKey>> source) where TKey : IEquatable<TKey> {
+35 -34
View File
@@ -1,34 +1,35 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<Authors>Blue Trading Systems</Authors>
<Company>Blue Trading Systems</Company>
<Product>Spark</Product>
<Description />
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Platforms>x64</Platforms>
<PlatformTarget>AnyCPU</PlatformTarget>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<WarningsAsErrors />
<Version>1.0.0</Version>
<LangVersion>7.2</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Google.Protobuf" Version="3.4.0" />
<PackageReference Include="System.Reactive" Version="3.1.1" />
</ItemGroup>
<ItemGroup>
<Proto3 Include="**/*.proto" />
<Proto3 Include="../../lib/api/*.proto" />
<Proto3 Include="../../lib/api/services/*.proto" />
<!--Proto3 Remove="../../lib/api/services/MarketDataRelay.proto" /-->
<Proto3 Include="../../lib/md/protos/co2.proto" />
<Proto3 Include="../../lib/domain_model/Security.proto" />
<Proto3 Include="../../lib/sparkproto/SparkProtos.proto" />
<Proto3 Update="../../lib/api/services/OutOfProcessURLListener.proto">
<!-- <CompileOptions>internal_access:</CompileOptions> -->
</Proto3>
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<Authors>Blue Trading Systems</Authors>
<Company>Blue Trading Systems</Company>
<Product>Spark</Product>
<Description />
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Platforms>x64</Platforms>
<PlatformTarget>AnyCPU</PlatformTarget>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<WarningsAsErrors />
<Version>1.0.0</Version>
<LangVersion>7.2</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Google.Protobuf" Version="3.4.0" />
<PackageReference Include="System.Collections.Immutable" Version="1.5.0" />
<PackageReference Include="System.Reactive" Version="3.1.1" />
</ItemGroup>
<ItemGroup>
<Proto3 Include="**/*.proto" />
<Proto3 Include="../../lib/api/*.proto" />
<Proto3 Include="../../lib/api/services/*.proto" />
<!--Proto3 Remove="../../lib/api/services/MarketDataRelay.proto" /-->
<Proto3 Include="../../lib/md/protos/co2.proto" />
<Proto3 Include="../../lib/domain_model/Security.proto" />
<Proto3 Include="../../lib/sparkproto/SparkProtos.proto" />
<Proto3 Update="../../lib/api/services/OutOfProcessURLListener.proto">
<!-- <CompileOptions>internal_access:</CompileOptions> -->
</Proto3>
</ItemGroup>
</Project>
+1 -2
View File
@@ -1,4 +1,4 @@
#ifndef NO_CPP0X
#define _DISABLE_EXTENDED_ALIGNED_STORAGE
#include "Co2TestInstrument.h"
#include "lib/md/MemorySegmentUtils.h"
@@ -50,4 +50,3 @@ MDConsumerHandle Co2TestInstrument::consumer() {
Co2TestInstrument::~Co2TestInstrument() { }
}}//namespace
#endif
+1
View File
@@ -77,6 +77,7 @@ namespace http {
_server.set_http_handler(bind(&ServerState::on_http, this, ::_1));
// Turn off logging
_server.clear_access_channels(websocketpp::log::alevel::all);
_server.clear_error_channels(websocketpp::log::alevel::all);
run();
}
@@ -203,11 +203,10 @@ void ExecutionGateway::on_exe_report(
data->side = api::Side(msg.get<fix::Side>());
if (msg.has<fix::TimeInForce>())
data->time_in_force =
api::orderman::TimeInForce(msg.get<fix::TimeInForce>());
api::orderman::TimeInForce(msg.get<fix::TimeInForce>());
else
data->time_in_force = api::orderman::TIME_IN_FORCE_UNDEFINED;
data->order_type =
api::orderman::NativeOrderType(msg.get<fix::OrdType>());
data->order_status =
@@ -218,14 +217,9 @@ void ExecutionGateway::on_exe_report(
: api::orderman::MANUAL_ORDER_INDICATOR_YES;
str_to(msg.get<fix::OrderID>(), &data->exchange_order_id);
if (msg.has<fix::Price>()) {
if (data->leg_security)
data->price = securities::decode_exchange_price(
*data->leg_security, Price(msg.get<fix::Price>()));
else
data->price = securities::decode_exchange_price(
*sec, Price(msg.get<fix::Price>()));
}
if (msg.has<fix::Price>())
data->price = securities::decode_exchange_price(
*sec, Price(msg.get<fix::Price>()));
else
data->price = Price(os::nan());
@@ -239,18 +233,19 @@ void ExecutionGateway::on_exe_report(
data->quantity = Quantity(msg.get<fix::OrderQty>());
else
data->quantity = Quantity(0);
data->filled_quantity = Quantity(msg.get<fix::CumQty>());
data->last_shares = msg.has<fix::LastShares>()
? Quantity(msg.get<fix::LastShares>())
: Quantity(0);
auto last_px_sec = data->leg_security? data->leg_security:sec;
data->last_price = msg.has<fix::LastPx>()
? securities::decode_exchange_price(
*sec, Price(msg.get<fix::LastPx>()))
*last_px_sec, Price(msg.get<fix::LastPx>()))
: Price(0);
data->avg_price = msg.has<fix::AvgPx>()
? securities::decode_exchange_price(
*sec, Price(msg.get<fix::AvgPx>()))
*last_px_sec, Price(msg.get<fix::AvgPx>()))
: Price(0);
if (msg.has<fix::ExecID>())
str_to(msg.get<fix::ExecID>(), &data->exchange_fill_id);
@@ -110,8 +110,8 @@ void SpreaderOrder::_on_child_order_update(const OrderStateUpdateEvent& ord_ev){
#endif
Quantity filled_qty = Quantity (ord_ev.state.filled_quantity());
Price last_price = Price(ord_ev.state.last_price());
LOG(OrderMan, Diag, "SpreaderOrder::_on_child_order_update key: {} sec_key: {} order_key: {} status: {} filled_qty: {} last_price: {} msg: {}", key(), sec_key, order_key, status, filled_qty, last_price, ord_ev.state.last_msg ());
Price last_price = Price(ord_ev.state.last_price()),
order_price=Price(ord_ev.state.price());
if (!SpreaderUtils::order_acknowledged(status)){
LOG(OrderMan, Diag, "SpreaderOrder::_on_child_order_update, unack'ed callback for key: {} sec_key: {} order_key: {} status: {} ignoring", key(), sec_key, order_key, status);
bts_assert(filled_qty.value() == 0);
@@ -121,8 +121,14 @@ void SpreaderOrder::_on_child_order_update(const OrderStateUpdateEvent& ord_ev){
if (leg_data_ptr != nullptr){
SpreaderLegData& leg_data = *leg_data_ptr;
ChildOrderError order_error = _get_order_error (ord_ev, leg_data.quoter().expecting_cancel_update());
LOG(OrderMan, Info, "SpreaderOrder::_on_child_order_update quoter order key: {} sec_key: {} order_key: {} status: {} filled_qty: {} last_price: {} msg: {} child_order_error: {}",
key(), sec_key, order_key, status, filled_qty, last_price, ord_ev.state.last_msg (), static_cast<int>(order_error));
LOG(OrderMan, Info, "SpreaderOrder::_on_child_order_update quoter order "
"key:{} sec_key:{} state:{} order_key:{} status:{} "
"filled_qty:{} price:{} last_price:{} "
"msg:{} child_order_error:{}",
key(), sec_key,
static_cast<int>(_state_worker->state()), order_key, status,
filled_qty, order_price, last_price,
ord_ev.state.last_msg(), static_cast<int>(order_error));
leg_data.order_update_message().on_order_update(ord_ev);
if (order_error == ChildOrderError::NONE){
if (leg_data.order_update_message().last_update_filled_quantity().value() > 0)
@@ -138,8 +144,14 @@ void SpreaderOrder::_on_child_order_update(const OrderStateUpdateEvent& ord_ev){
SingleFillHedger* hedger = _bookkeeping_data().find_hedger_from_orderkey(order_key);
if (hedger != nullptr){
ChildOrderError order_error = _get_order_error (ord_ev, hedger->expecting_cancel_update());
LOG(OrderMan, Info, "SpreaderOrder::_on_child_order_update hedger order: key: {} sec_key: {} order_key: {} status: {} filled_qty: {} last_price: {} msg: {} child_order_error: {}",
key(), sec_key, order_key, status, filled_qty, last_price, ord_ev.state.last_msg (), static_cast<int>(order_error));
LOG(OrderMan, Info, "SpreaderOrder::_on_child_order_update hedger "
"key:{} sec_key:{} state:{} order_key:{} status:{} "
"filled_qty:{} price:{} last_price:{} "
"msg:{} child_order_error:{}",
key(), sec_key,
static_cast<int>(_state_worker->state()), order_key, status,
filled_qty, order_price, last_price,
ord_ev.state.last_msg (), static_cast<int>(order_error));
hedger->order_state().on_order_update(ord_ev);
if (order_error == ChildOrderError::NONE)
_state_worker->on_hedger_order_update (*hedger);
@@ -273,6 +285,7 @@ void SpreaderOrder::_send_hedge(size_t hedge_leg_index,
void SpreaderOrder::_compute_hedge_price_quantity(size_t filled_leg_index,
Price fill_price,
double fill_quantity,
Price quote_order_price,
size_t hedge_leg_index,
Price& hedge_price,
double& hedge_quantity){
@@ -288,7 +301,7 @@ void SpreaderOrder::_compute_hedge_price_quantity(size_t filled_leg_index,
computed_hedge_price,
hedge_quantity);
else{
const QuoteLegDriver& driver_data = filled_leg_data.quoter().driver_data(fill_price, hedge_leg_index);
const QuoteLegDriver& driver_data = filled_leg_data.quoter().driver_data(quote_order_price, hedge_leg_index);
SpreaderUtils::compute_hedge_price_size_n_legs (filled_leg_data.leg_property_data(),
fill_price,
fill_quantity,
@@ -173,6 +173,7 @@ private:
void _compute_hedge_price_quantity(size_t filled_leg_index,
Price filled_price,
double filled_quantity,
Price order_price,
size_t hedged_leg_index,
Price& hedge_price,
double& hedge_quantity);
@@ -19,6 +19,7 @@ _status(src._status),
_filled_price(src._filled_price),
_filled_quantity(src._filled_quantity),
_last_filled_price(src._last_filled_price),
_last_reported_order_price(src._last_reported_order_price),
_last_filled_quantity(src._last_filled_quantity)
{ }
SpreaderChildOrderState::SpreaderChildOrderState (bts::orderman::ChildOrder& child_order,
@@ -45,6 +46,7 @@ void SpreaderChildOrderState::_init_running_values(){
_filled_price = Price(0);
_filled_quantity = Quantity (0);
_last_filled_price = Price(0);
_last_reported_order_price=Price(0);
_last_filled_quantity = Quantity(0);
_out_price = Price(0);
_out_quantity = Quantity(0);
@@ -29,6 +29,7 @@ private:
Price _filled_price;
Quantity _filled_quantity;
Price _last_filled_price;
Price _last_reported_order_price;
Quantity _last_filled_quantity;
Price _out_price;
Quantity _out_quantity;
@@ -54,9 +55,12 @@ public:
}
// if the last fill was a status change
// this will be zero
Price last_update_filled_price () const {
Price last_update_filled_price() const {
return _last_filled_price;
}
Price last_reported_order_price() const{
return _last_reported_order_price;
}
// if the last fill was a status change
// this will be zero
Quantity last_update_filled_quantity () const {
@@ -109,6 +113,7 @@ public:
_status = e.state.status();
_last_filled_quantity = Quantity(e.state.filled_quantity() - _filled_quantity.value());
_last_filled_price = Price(e.state.last_price());
_last_reported_order_price=Price(e.state.price());
SpreaderUtils::compute_average_price(_filled_price,
_filled_quantity,
_last_filled_price,
@@ -43,7 +43,12 @@ const QuoteDriverSet* QuoteDriverSetHistory::_find_driver_set(Price quote_price)
_tick_size))
if (rv==nullptr||d.quote_seq_no()>rv->quote_seq_no())
rv=&d;
return rv!=nullptr ? rv:_latest();
if (rv==nullptr){
LOG(OrderMan, Warn, "QuoteDriverSetHistory::_find_driver_set "
"could not find driver:{}",quote_price);
rv=_latest();
}
return rv;
}
const QuoteLegDriver* QuoteDriverSetHistory::find_driver(Price quote_price,
size_t leg_index) const{
@@ -92,11 +92,7 @@ void SpreaderWorkingStateWorker::on_quoter_order_fill(SpreaderLegData& leg_data,
// ii. not send a hedge on leg_2 since its already filled
// however doing the above would mess up the leg ratio's so we are preffering
// getting overfilled
SpreaderChildOrderState& order_update_message = leg_data.order_update_message();
LOG(OrderMan, Info, "SpreaderWorkingStateWorker::on_quoter_order_fill order: key: {} order_key: {} status: {} filled_qty: {} last_price: {}",
_spreader->key(), order_update_message.order_key(), order_update_message.status(),
order_update_message.last_update_filled_quantity(),
order_update_message.last_update_filled_price());
SpreaderChildOrderState& order_update_message = leg_data.order_update_message();
bts_assert (order_update_message.last_update_filled_quantity().value() > 0);
for (size_t q_idx = 0; q_idx < _spreader->_bookkeeping_data().n_legs(); q_idx++){
if (q_idx != leg_data.leg_property_data().leg_index()){
@@ -106,6 +102,7 @@ void SpreaderWorkingStateWorker::on_quoter_order_fill(SpreaderLegData& leg_data,
_spreader->_compute_hedge_price_quantity(leg_data.leg_property_data().leg_index(),
order_update_message.last_update_filled_price(),
order_update_message.last_update_filled_quantity().value(),
order_update_message.last_reported_order_price(),
q_idx,
hedge_price,
hedge_qty);
+2 -2
View File
@@ -74,7 +74,7 @@ let GetFilteredSymbolArray (model:Model) (remove:string []) =
|> Array.distinct)
match a.Length with
| 0 -> a
| _ -> [ a; [|model.AllValueDisplay|] ] |> Array.concat
| _ -> [ [|model.AllValueDisplay|]; a ] |> Array.concat
let limitFilter (positionLimit:AccountSecurityPositionLimitUnit option) (clipLimit:AccountSecurityClipLimitUnit option) allValueDisplay (array:'a []) =
match positionLimit, clipLimit with
@@ -441,7 +441,7 @@ let productLimits model dispatch =
div [ ClassName "columns" ][
h1 [ ClassName "is-size-3 column is-narrow" ][str "Position Limits" ]
div [ ClassName "column is-size-7 has-text-grey-mid is-help-text" ]
[str "This limits the net position for a product (i.e. accumulated position over all securities belonging to a product). This can be set for one product, or for all products within a security type by selecting \"All\" for symbol"]
[str "This limits the net position for a product (i.e. accumulated position over all securities belonging to a product). This can be set for one product, or for all products within a security type by selecting \"All\" for symbol. (Note that \"All\" applies the same limits to each symbol, not the combiled position of all symbols)"]
]
TableControl.createDataTable (Some headerRow) rws (Button.button "Add" "" "plus-circle" Button.Enabled addRow)
br []