Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd6d86b9b1 | ||
|
|
b12fb8c175 | ||
|
|
8d5402bd4d | ||
|
|
7433484484 | ||
|
|
7db6591d22 | ||
|
|
289f9259bb | ||
|
|
197b6e85bd | ||
|
|
afea120359 | ||
|
|
dfaeb63ded | ||
|
|
ffa1d17860 | ||
|
|
eb739b33f9 | ||
|
|
dc2b0c8efe | ||
|
|
ee69892006 | ||
|
|
bc279ea1b1 |
No files matched your search
@@ -78,7 +78,7 @@ namespace mbts.spark {
|
||||
_animation.AnimationsChanged += on_animations_changed;
|
||||
void on_animations_changed() => RaisePropertyChanged(nameof(animations));
|
||||
_dispose = Disposable.Create(
|
||||
_orders_model.on_security_orders(security.Id).OnDispatcher().Subscribe(_on_orders),
|
||||
_orders_model.on_security_root_orders(security.Id).OnDispatcher().Subscribe(_on_orders),
|
||||
_position.OnDispatcher().Subscribe(v => _animation.animate_position(v.newval > v.oldval)),
|
||||
_inside_bids.OnDispatcher().Subscribe(v => _animation.animate_working_bids_inside(v.newval)),
|
||||
_inside_asks.OnDispatcher().Subscribe(v => _animation.animate_working_asks_inside(v.newval)),
|
||||
@@ -250,9 +250,6 @@ namespace mbts.spark {
|
||||
public int position => _position;
|
||||
|
||||
public void add_order(OrderRecordImmutable o) {
|
||||
// This is a market data form - not an orders form - so just show data for root/non-child orders.
|
||||
if (o.has_parent())
|
||||
return;
|
||||
switch (o.side()) {
|
||||
case Side.Buy:
|
||||
_position += (int)o.filled();
|
||||
@@ -274,9 +271,6 @@ namespace mbts.spark {
|
||||
}
|
||||
|
||||
public void remove_order(OrderRecordImmutable o) {
|
||||
// This is a market data form - not an orders form - so just show data for root/non-child orders.
|
||||
if (o.has_parent())
|
||||
return;
|
||||
switch (o.side()) {
|
||||
case Side.Buy:
|
||||
_position -= (int)o.filled();
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using bts.api.core;
|
||||
using bts.api.orderman;
|
||||
using bts.spark;
|
||||
using mbts.collections;
|
||||
using mbts.spark.utilities;
|
||||
using mbts.utils;
|
||||
using System;
|
||||
@@ -173,6 +174,69 @@ namespace mbts.spark {
|
||||
.Select(t => t.state.Any(kv => kv.Value.is_active()))
|
||||
.StartWith(false);
|
||||
|
||||
public static IObservable<ITableUpdateTransform<OrderRecordImmutable, uint>> on_security_root_orders(this OrdersModel orders_model, uint security_key) =>
|
||||
orders_model.on_security_orders(security_key).Scan(new RootOrderData(), (rod, table) => {
|
||||
// ** using HashSet/List pairs, rather than a Dictionary, because TableUpdateTransform calls for IReadOnlyLists, while Dictionary.Values only implements IReadOnlyCollection.
|
||||
// (this way, we avoid copying both added/removed Dictionary.Values to new Lists at the end, see comment at bottom of method if this is unclear) **
|
||||
var added_root_keys = new HashSet<uint>();
|
||||
var added_roots = new List<OrderRecordImmutable>();
|
||||
var removed_root_keys = new HashSet<uint>();
|
||||
var removed_roots = new List<OrderRecordImmutable>();
|
||||
foreach (var o in table.removed) {
|
||||
if (rod.last_update.state.ContainsKey(o.Key)) {
|
||||
// order was a root, needs to be removed
|
||||
removed_roots.Add(o);
|
||||
if (table.state.TryGetValue(o.Key, out OrderRecordImmutable newval)) {
|
||||
// order was changed, if its an actual root, or its parent isn't present, the newval needs to be added
|
||||
if (!o.has_parent() || !table.state.ContainsKey(o.ParentKey)) {
|
||||
added_roots.Add(newval);
|
||||
added_root_keys.Add(o.Key);
|
||||
}
|
||||
} else {
|
||||
// order was indeed removed, not just changed - if it has a parent, remove its corresponding child-entry
|
||||
if (o.has_parent()) {
|
||||
rod.parent_to_children.remove(o.ParentKey, o.Key);
|
||||
}
|
||||
if (rod.parent_to_children.try_lookup(o.Key, out ISet<uint> children)) {
|
||||
// order has left some orphans behind, any children that haven't been removed (i.e. still exist in table.state) are now roots
|
||||
foreach (uint ck in children) {
|
||||
if (table.state.TryGetValue(ck, out OrderRecordImmutable child)) {
|
||||
added_roots.Add(child);
|
||||
added_root_keys.Add(ck);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (!table.state.ContainsKey(o.Key)) {
|
||||
// order was indeed removed, not just changed - if it has a parent, remove its corresponding child-entry
|
||||
rod.parent_to_children.remove(o.ParentKey, o.Key);
|
||||
}
|
||||
}
|
||||
foreach (var o in table.added) {
|
||||
if (added_root_keys.Contains(o.Key))
|
||||
continue;
|
||||
if (rod.parent_to_children.try_lookup(o.Key, out ISet<uint> children)) {
|
||||
// children were previously functioning as roots, need to remove them
|
||||
foreach (uint ck in children) {
|
||||
if (rod.last_update.state.TryGetValue(ck, out OrderRecordImmutable child))
|
||||
removed_roots.Add(child);
|
||||
}
|
||||
}
|
||||
if (o.has_parent()) {
|
||||
rod.parent_to_children.add(o.ParentKey, o.Key);
|
||||
if (table.state.ContainsKey(o.ParentKey)) {
|
||||
// not a root order
|
||||
continue;
|
||||
}
|
||||
}
|
||||
added_roots.Add(o);
|
||||
}
|
||||
// ** [continue comment at top of method] this call would otherwise be:
|
||||
// rod.last_update = rod.last_update.update(removed_dict.Values.ToList(), added_dict.Values.ToList(), o => o.Key) **
|
||||
rod.last_update = rod.last_update.update(removed_roots, added_roots, o => o.Key);
|
||||
return rod;
|
||||
}).Select(r => r.last_update);
|
||||
|
||||
public static async Task<OrderRecordImmutable?> order_from_key(this OrdersModel orders_model, uint order_key) {
|
||||
(var tu, var success) = await orders_model.on_orders.FirstAsyncTask(t => t.state.ContainsKey(order_key), TimeSpan.FromSeconds(3));
|
||||
if (success && tu.state.TryGetValue(order_key, out OrderRecordImmutable rec)) {
|
||||
@@ -213,5 +277,10 @@ namespace mbts.spark {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
class RootOrderData {
|
||||
public readonly SetMap<uint, uint> parent_to_children = new SetMap<uint, uint>();
|
||||
public TableUpdateTransform<OrderRecordImmutable, uint> last_update { get; set; } = new TableUpdateTransform<OrderRecordImmutable, uint>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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,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
|
||||
@@ -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);
|
||||
|
||||
+6
-1
@@ -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,
|
||||
|
||||
+6
-1
@@ -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{
|
||||
|
||||
+2
-5
@@ -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);
|
||||
|
||||
@@ -51,16 +51,21 @@ let applyUpdate (account:BTSAccount) = function
|
||||
| IsActive b -> { account with isActive = b }
|
||||
|
||||
let applyCMEUpdate (data:CMEAccountData) = function
|
||||
| CMEExchangeField.CTI v -> { data with cti = v }
|
||||
| CMEExchangeField.Origin v -> { data with origin = v }
|
||||
| CMEExchangeField.TakeupMember v -> { data with takeupMemberCode = v }
|
||||
| CMEExchangeField.ClearingAccount v -> { data with clearingAccount = v }
|
||||
| CMEExchangeField.DirectElectronicAccess v -> { data with directElectronicAccess = v }
|
||||
| CMEExchangeField.TradingCapacity v -> { data with tradingCapacity = v }
|
||||
| CMEExchangeField.LiquidityProvision v -> { data with liquidityProvision = v }
|
||||
| CMEExchangeField.CommodityDerivativeIndicator v -> { data with commodityDerivativeIndicator = v }
|
||||
| CMEExchangeField.MiscTagMapping mp -> { data with miscTags = mp }
|
||||
|
||||
let applySIMUpdate (data:SIMAccountData) = function
|
||||
| CTI v -> { data with cti = v }
|
||||
| Origin v -> { data with origin = v }
|
||||
| TakeupMember v -> { data with takeupMemberCode = v }
|
||||
| ClearingAccount v -> { data with clearingAccount = v }
|
||||
| DirectElectronicAccess v -> { data with directElectronicAccess = v }
|
||||
| TradingCapacity v -> { data with tradingCapacity = v }
|
||||
| LiquidityProvision v -> { data with liquidityProvision = v }
|
||||
| CommodityDerivativeIndicator v -> { data with commodityDerivativeIndicator = v }
|
||||
| MiscTagMapping mp -> { data with miscTags = mp }
|
||||
|
||||
| _ -> data
|
||||
|
||||
let saveAccount (admin:IAdminService) (account:BTSAccount) = promise {
|
||||
let! result = admin.update_account { completeData = account }
|
||||
@@ -250,10 +255,14 @@ let update msg (model:Model) : Model * Cmd<Msg> =
|
||||
{ model with scratch = { model.scratch with connections = { model.scratch.connections with exchangeConnectionNames = newCons }}; ConfirmModal = ("", Msg.SelectTab model.tab)}, Cmd.Empty
|
||||
//
|
||||
// Exchange data
|
||||
| UpdateCME field ->
|
||||
| UpdateCME (field:CMEExchangeField) ->
|
||||
let newCme = applyCMEUpdate model.scratch.exchangeAccountData.cmeAccountData field
|
||||
let scratch = { model.scratch with exchangeAccountData = { cmeAccountData = newCme; iceAccountData = model.scratch.exchangeAccountData.iceAccountData; simAccountData = model.scratch.exchangeAccountData.simAccountData } }
|
||||
{ model with scratch = scratch }, Cmd.Empty
|
||||
| UpdateSIM field ->
|
||||
let newSim = applySIMUpdate model.scratch.exchangeAccountData.simAccountData field
|
||||
let scratch = { model.scratch with exchangeAccountData = { cmeAccountData = model.scratch.exchangeAccountData.cmeAccountData ; iceAccountData = model.scratch.exchangeAccountData.iceAccountData; simAccountData = newSim } }
|
||||
{ model with scratch = scratch }, Cmd.Empty
|
||||
| RequestProducts ->
|
||||
model, Cmd.ofExistingPromise (requestProducts model.mdRelay) id (box>>ErrorOccured)
|
||||
| UpdateProducts data ->
|
||||
|
||||
@@ -35,6 +35,11 @@ type CMEExchangeField =
|
||||
| CommodityDerivativeIndicator of string
|
||||
| MiscTagMapping of JSMap<string>
|
||||
|
||||
type SIMExchangeField =
|
||||
| CTI of CTICode
|
||||
| Origin of CustomerOrFirm
|
||||
| ClearingAccount of string
|
||||
|
||||
type Msg =
|
||||
| UpdateAdminData of AdminData
|
||||
| NoAdminData of string
|
||||
@@ -64,6 +69,7 @@ type Msg =
|
||||
| DeleteSecurityLimit of int
|
||||
// ExchangeData
|
||||
| UpdateCME of CMEExchangeField
|
||||
| UpdateSIM of SIMExchangeField
|
||||
| RequestProducts
|
||||
| UpdateProducts of Product[]
|
||||
| RequestExpirationNames
|
||||
|
||||
@@ -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 []
|
||||
@@ -633,17 +633,24 @@ let creditLimitsView model dispatch = div [] [str "lorem ipsum"]
|
||||
|
||||
let exchangeSettings model dispatch =
|
||||
let cme = model.scratch.exchangeAccountData.cmeAccountData
|
||||
let sim = model.scratch.exchangeAccountData.simAccountData
|
||||
let send = UpdateCME>>dispatch
|
||||
let sendSim = UpdateSIM>>dispatch
|
||||
div [] [
|
||||
h2 [Class "is-size-3"] [ str "CME" ]
|
||||
Fields.enumSelect "CTI" (toHuman false CTICode.values cme.cti) (allToHuman false CTICode.values) [] (fromHuman CTICode.values>>CTI>>send)
|
||||
Fields.enumSelect "Origin" (toHuman false CustomerOrFirm.values cme.origin) (allToHuman false CustomerOrFirm.values) [] (fromHuman CustomerOrFirm.values>>Origin>>send)
|
||||
Fields.enumSelect "CTI" (toHuman false CTICode.values cme.cti) (allToHuman false CTICode.values) [] (fromHuman CTICode.values>>CMEExchangeField.CTI>>send)
|
||||
Fields.enumSelect "Origin" (toHuman false CustomerOrFirm.values cme.origin) (allToHuman false CustomerOrFirm.values) [] (fromHuman CustomerOrFirm.values>>CMEExchangeField.Origin>>send)
|
||||
//Fields.text "Takeup Member Code" cme.takeupMemberCode [] (TakeupMember>>send)
|
||||
Fields.text "Clearing Account" cme.clearingAccount [] (ClearingAccount>>send)
|
||||
Fields.text "Clearing Account" cme.clearingAccount [] (CMEExchangeField.ClearingAccount>>send)
|
||||
//Fields.text "Direct Electronic Access" cme.directElectronicAccess [] (DirectElectronicAccess>>send)
|
||||
//Fields.text "Trading Capacity" cme.tradingCapacity [] (TradingCapacity>>send)
|
||||
//Fields.text "Liquidity Provision" cme.liquidityProvision [] (LiquidityProvision>>send)
|
||||
//Fields.map "Misc Tag Mapping" cme.miscTags [] (MiscTagMapping>>send)
|
||||
h2 [Class "is-size-3"] [ str "SIM" ]
|
||||
Fields.enumSelect "CTI" (toHuman false CTICode.values sim.cti) (allToHuman false CTICode.values) [] (fromHuman CTICode.values>>SIMExchangeField.CTI>>sendSim)
|
||||
Fields.enumSelect "Origin" (toHuman false CustomerOrFirm.values sim.origin) (allToHuman false CustomerOrFirm.values) [] (fromHuman CustomerOrFirm.values>>SIMExchangeField.Origin>>sendSim)
|
||||
Fields.text "Clearing Account" sim.clearingAccount [] (SIMExchangeField.ClearingAccount>>sendSim)
|
||||
|
||||
]
|
||||
|
||||
let accountControls model (dispatch:Msg->unit) =
|
||||
|
||||
Reference in new issue
Block a user