Compare commits

...
6 Commits
18 changed files with 183 additions and 62 deletions

No files matched your search

+1
View File
@@ -22,4 +22,5 @@ node_modules
paket-files
project.lock.json
src/server/sparkd/orderman/perf_analysis/data
src/server/sparkd/orderman/perf_analysis/logs/
src/server/sparkd/orderman/perf_analysis/trace_data/
@@ -134,7 +134,9 @@ namespace bts.spark {
}
}
foreach (var (neworder, oldorder) in update.changes) {
foreach (var order in update.changes) {
var neworder = order.New;
var oldorder = order.Old;
(var security, var spec) = get_security(neworder.Def.SecurityKey);
//
// description
@@ -24,13 +24,15 @@ namespace mbts.spark
this.child_order_types = new InlineUserProperty<IReadOnlyCollection<CustomOneofCase>>(child_order_types, true);
cross_threshold = new InlineUserProperty<bts.spark.QuantityMeasure>(
new bts.spark.QuantityMeasure() { Ratio = 1.0, Absolute = 1}, false);
max_chase_ticks = new InlineUserProperty<uint>(10, false);
max_chase_ticks = new InlineUserProperty<uint>(2, false);
detach_on_toward = new InlineUserProperty<bool>(true, false);
}
public readonly InlineUserProperty<CustomOneofCase> selected_child_order_type;
public readonly InlineUserProperty<IReadOnlyCollection<CustomOneofCase>> child_order_types;
public readonly InlineUserProperty<bts.spark.QuantityMeasure> cross_threshold;
public readonly InlineUserProperty<uint> max_chase_ticks;
public readonly InlineUserProperty<bool> detach_on_toward;
}
class LeanOrderVM : OrderTypeVMBase<LeanOrderDefinition>, IHierarchicalOrderTypeVM, IDisposable
@@ -44,7 +46,8 @@ namespace mbts.spark
IDisposable _dispose, _child_order_errors_sub;
public bts.spark.QuantityMeasure cross_threshold { get; set; } = new bts.spark.QuantityMeasure() { Ratio = 1.0, Absolute = 1 };
public uint max_chase_ticks { get; set; } = 10;
public uint max_chase_ticks { get; set; } = 2;
public bool detach_on_toward { get; set; } = true;
public LeanOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source)
: this(model, security_md_source, security_md_source.Select(smd =>
@@ -77,6 +80,11 @@ namespace mbts.spark
max_chase_ticks = p.max_chase_ticks.value;
RaisePropertyChanged(nameof(max_chase_ticks));
}
if (p.detach_on_toward.force_override)
{
detach_on_toward = p.detach_on_toward.value;
RaisePropertyChanged(nameof(detach_on_toward));
}
_inline_props = p;
_validate();
})
@@ -94,6 +102,7 @@ namespace mbts.spark
var i = factory.lean_order();
i.CrossThreshold = cross_threshold;
i.MaxChaseTicks = max_chase_ticks;
i.DetachOnToward = detach_on_toward;
child_order.assign_to(i.Child);
value.Lean = i;
}
@@ -222,6 +222,8 @@
<RowDefinition Height="4" />
<RowDefinition Height="Auto"/>
<RowDefinition Height="4" />
<RowDefinition Height="Auto"/>
<RowDefinition Height="4" />
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
@@ -233,9 +235,10 @@
<uag:QuantityMeasureControl Grid.Row="1" Grid.Column="2" QuantityMeasure="{Binding cross_threshold}"/>
<TextBlock Grid.Row="3" VerticalAlignment="Center">Max Chase Ticks</TextBlock>
<c:TickUpDownUInt Grid.Row="3" Grid.Column="2" Value="{Binding max_chase_ticks}"/>
<TextBlock Grid.Row="5">Child</TextBlock>
<CheckBox Grid.Row="5" Grid.Column="2" VerticalAlignment="Center" Margin="0,0,0,0" IsChecked="{Binding detach_on_toward}">Detach on Toward</CheckBox>
<TextBlock Grid.Row="7">Child</TextBlock>
<uag:OrderDetailsPopupControl
Grid.Row="5" Grid.Column="2"
Grid.Row="7" Grid.Column="2"
IsOpen="{Binding child_order.editable_properties_open, FallbackValue=False}"
ItemsSource="{Binding child_order_types}"
SelectedItem="{Binding child_order}"
+68 -21
View File
@@ -1,4 +1,5 @@
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
@@ -53,28 +54,43 @@ namespace bts.api.core {
#endif
}
public readonly struct Change<T> {
public Change(T o, T n) {
Old = o;
New = n;
}
public readonly T Old;
public readonly T New;
public Change<T> merge(Change<T> newer) {
return new Change<T>(Old, newer.New);
}
public override string ToString() {
return $"{{{Old}=>{New}}}";
}
}
public class Update<T, TKey> where TKey : IEquatable<TKey> {
private Func<T, TKey> _key;
internal Update(
IReadOnlyCollection<T> all,
IEnumerable<T> added,
IEnumerable<(T New,T Old)> changes,
IEnumerable<Change<T>> changes,
IEnumerable<T> removed,
Func<T, TKey> key_extractor) {
this.added = added ?? new T[0];
this.removed = removed ?? new T[0];
this.changes = changes ?? new (T,T)[0];
this.changes = changes ?? new Change<T>[0];
this.all = all;
_key = key_extractor;
}
public static Update<T, TKey> empty(Func<T, TKey> key_extractor) =>
new Update<T, TKey>(new T[0], new T[0], new (T,T)[0], new T[0], key_extractor);
new Update<T, TKey>(new T[0], new T[0], new Change<T>[0], new T[0], key_extractor);
public Update<T,TKey> merge(Update<T, TKey> next) {
var comp = new RowEqualityComparer<T, TKey>(_key);
var added = this.added as HashSet<T> ?? new HashSet<T>(this.added, comp);
var changes = this.changed as HashSet<(T New,T Old)> ?? new HashSet<(T,T)>(this.changes, comp);
var changes = this.changed as ChangeDict<T,TKey> ?? new ChangeDict<T,TKey>(this.changes, _key);
var removed = this.removed as HashSet<T> ?? new HashSet<T>(this.removed, comp);
// Add
@@ -87,9 +103,7 @@ namespace bts.api.core {
added.Add(c.New);
}
else {
// Remove does not error if it was not present
changes.Remove(c);
changes.Add(c);
changes.AddOrMerge(c);
}
}
@@ -98,7 +112,7 @@ namespace bts.api.core {
if (!added.Remove(r)) {
removed.Add(r);
}
changes.Remove((r,r));
changes.Remove(_key(r));
}
return new Update<T, TKey>(
@@ -110,7 +124,7 @@ namespace bts.api.core {
public IReadOnlyCollection<T> all { get; }
public IEnumerable<T> added { get; }
public IEnumerable<(T New,T Old)> changes { get; }
public IEnumerable<Change<T>> changes { get; }
public IEnumerable<T> changed => changes.Select(c => c.New);
public IEnumerable<T> removed { get; }
@@ -127,7 +141,40 @@ namespace bts.api.core {
#endif
}
struct RowEqualityComparer<T,TKey> : IEqualityComparer<T>, IEqualityComparer<(T,T)>
class ChangeDict<T, TKey> : IEnumerable<Change<T>> {
Dictionary<TKey, Change<T>> _changes;
Func<Change<T>, TKey> _key;
public ChangeDict(IEnumerable<Change<T>> changes, Func<T, TKey> key) {
_key = x => key(x.New);
_changes = changes.ToDictionary(_key);
}
public Change<T>? AddOrMerge(Change<T> newer) {
var key = _key(newer);
if (_changes.TryGetValue(key, out Change<T> old)) {
_changes[key] = old.merge(newer);
return old;
}
_changes.Add(key, newer);
return null;
}
public void Remove(TKey key) {
_changes.Remove(key);
}
#region IEnumerable
public IEnumerator<Change<T>> GetEnumerator() {
return _changes.Values.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() {
return _changes.Values.GetEnumerator();
}
#endregion
}
struct RowEqualityComparer<T,TKey> : IEqualityComparer<T>, IEqualityComparer<Change<T>>
where TKey : IEquatable<TKey> {
readonly Func<T,TKey> _key;
@@ -139,16 +186,16 @@ namespace bts.api.core {
return _key(x).Equals(_key(y));
}
public bool Equals((T, T) x, (T, T) y) {
return Equals(x.Item1, y.Item1);
public bool Equals(Change<T> x, Change<T> y) {
return Equals(x.New, y.New);
}
public int GetHashCode(T obj) {
return _key(obj).GetHashCode();
}
public int GetHashCode((T, T) obj) {
return GetHashCode(obj.Item1);
public int GetHashCode(Change<T> c) {
return GetHashCode(c.New);
}
}
@@ -159,7 +206,7 @@ namespace bts.api.core {
internal TableUpdate(
ImmutableDictionary<TKey, T> init,
IEnumerable<T> added,
IEnumerable<(T,T)> changed,
IEnumerable<Change<T>> changed,
IEnumerable<T> removed) {
_state = init;
this.added = added;
@@ -169,7 +216,7 @@ namespace bts.api.core {
public IReadOnlyDictionary<TKey, T> state { get { return _state; } }
public IEnumerable<T> added { get; }
public IEnumerable<(T New,T Old)> changes { get; }
public IEnumerable<Change<T>> changes { get; }
public IEnumerable<T> changed => changes.Select(c => c.New);
public IEnumerable<T> removed { get; }
@@ -185,7 +232,7 @@ namespace bts.api.core {
}
internal TableUpdate<T, TKey> as_snapshot() {
return new TableUpdate<T, TKey>(_state, _state.Values.ToList(), new (T,T)[0], new T[0]);
return new TableUpdate<T, TKey>(_state, _state.Values.ToList(), new Change<T>[0], new T[0]);
}
}
@@ -208,7 +255,7 @@ namespace bts.api.core {
if (raw.is_reset) {
var removed = state.Values.ToList();
state.Clear();
return new Update<T, TKey>(new T[0], new T[0], new (T,T)[0], removed, key_extractor);
return new Update<T, TKey>(new T[0], new T[0], new Change<T>[0], removed, key_extractor);
}
else {
var removed = new List<T>(raw.removed_keys.Count);
@@ -222,11 +269,11 @@ namespace bts.api.core {
for (int x = 0; x < raw.added_items.Count; ++x) {
state[raw.added_keys[x]] = raw.added_items[x];
}
List<(T, T)> changes = new List<(T, T)>(raw.changed_items.Count);
var changes = new List<Change<T>>(raw.changed_items.Count);
for (int x = 0; x < raw.changed_items.Count; ++x) {
var old = state[raw.changed_keys[x]];
state[raw.changed_keys[x]] = raw.changed_items[x];
changes.Add((raw.changed_items[x], old));
changes.Add(new Change<T>(old, raw.changed_items[x]));
}
return new Update<T, TKey>(state.Values.ToList(), raw.added_items.ToList(), changes, removed, key_extractor);
}
@@ -235,7 +282,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>(ImmutableDictionary<TKey,T>.Empty, new T[0], new (T,T)[0], new T[0]),
new TableUpdate<T,TKey>(ImmutableDictionary<TKey,T>.Empty, new T[0], new Change<T>[0], new T[0]),
(table, update) => TableUpdate<T,TKey>.update(table,update));
// Fold updates and emit at max 1/interval
@@ -227,5 +227,15 @@ namespace mbts.api.Test {
await validate_naggle(raw);
}
[Test]
public void test_merge_begin_end_state() {
int key(string s) => s[0];
var empty = new string[0];
var a2 = new Update<string, int>(new[] { "a2" }, empty, new[] { new Change<string>("a1", "a2") }, empty, key);
var a3 = new Update<string, int>(new[] { "a3" }, empty, new[] { new Change<string>("a2", "a3") }, empty, key);
var merged = a2.merge(a3);
Assert.SequenceEqual(new[] { new Change<string>("a1", "a3") }, merged.changes);
}
}
}
+1
View File
@@ -109,6 +109,7 @@ message TickOrderDefinition {
message LeanOrderDefinition {
spark.QuantityMeasure cross_threshold = 1;
uint32 max_chase_ticks = 2;
bool detach_on_toward = 4;
CustomOrderDefinition child = 3;
}
message JoinOrderDefinition {
@@ -132,7 +132,7 @@ int SocketConnection::write(WriteVec const &vec, size_t vec_size,
"perf_event:tick_to_order s2s_us:{} fix_socket_r:{} md:{} "
"md_src:{} spreader_on_book:{} spreader_modify_order:{} "
"spreader_on_child_order_update:{} "
"order_update:{} exe_gw:{} fix_socket_w:{} md_sn:{}",
"order_update:{} exe_gw:{} fix_socket_w:{} md_sn:{} order_key:{}",
s2s.microseconds(), trace_cpy.fix_socket_r.to_uint64(),
trace_cpy.md.to_uint64(), trace_cpy.md_src.to_uint64(),
trace_cpy.spreader_on_book.to_uint64(),
@@ -140,7 +140,8 @@ int SocketConnection::write(WriteVec const &vec, size_t vec_size,
trace_cpy.spreader_on_child_order_update.to_uint64(),
trace_cpy.order_update.to_uint64(),
trace_cpy.exe_gw.to_uint64(), trace_cpy.fix_socket_w.to_uint64(),
trace_cpy.md_sn);
trace_cpy.md_sn,
trace_cpy.order_key);
_tick_to_order->observe(s2s.nanoseconds());
}
@@ -150,7 +151,7 @@ int SocketConnection::write(WriteVec const &vec, size_t vec_size,
"perf_event:fill_to_order s2s_us:{} fix_socket_r:{} md:{} md_src:{} "
"spreader_on_book:{} spreader_modify_order:{} "
"spreader_on_child_order_update:{} "
"order_update:{} exe_gw:{} fix_socket_w:{} md_sn:{}",
"order_update:{} exe_gw:{} fix_socket_w:{} md_sn:{} order_key:{}",
s2s.microseconds(), trace_cpy.fix_socket_r.to_uint64(),
trace_cpy.md.to_uint64(), trace_cpy.md_src.to_uint64(),
trace_cpy.spreader_on_book.to_uint64(),
@@ -158,7 +159,8 @@ int SocketConnection::write(WriteVec const &vec, size_t vec_size,
trace_cpy.spreader_on_child_order_update.to_uint64(),
trace_cpy.order_update.to_uint64(),
trace_cpy.exe_gw.to_uint64(), trace_cpy.fix_socket_w.to_uint64(),
trace_cpy.md_sn);
trace_cpy.md_sn,
trace.order_key);
_fill_to_order->observe(s2s.nanoseconds());
}
+1 -2
View File
@@ -76,8 +76,7 @@ string dump_security(const FixedSecurity& security) {
res << "'main_frac': " << (int)security.cme_main_fraction << ", ";
res << "'sub_fract': " << (int)security.cme_sub_fraction << ", ";
res << "'price_format': " << (int)security.cme_price_display_format << ", ";
res << "'market_segment': " << security.cme_market_segment_id << ", ";
res << "'market_segment': " << (int)security.cme_market_segment_id << ", ";
res << "'price_break': " << security.price_break << ", ";
res << "'low_tick': " << security.low_tick << ", ";
@@ -16,6 +16,7 @@ public:
utils::TimeStamp exe_gw ;
utils::TimeStamp fix_socket_w ;
utils::TimeStamp spreader_modify_order ;
uint32_t order_key = 0;
uint16_t md_sn = 0;
};
+5 -1
View File
@@ -271,7 +271,10 @@ NativeOrder::~NativeOrder() {}
void NativeOrder::on_activate(Price p, Quantity q,
bts::orderman::OrderServices &services,
PerfTrace const&trace) {
PerfTrace const&t) {
auto trace = t;
trace.order_key = key().value();
tracepoint(bts_trace, trace_order, (char *)"on_activate", 0, trace.md_sn, 0);
bts_assert(!me->services);
me->services = &services;
@@ -454,6 +457,7 @@ void NativeOrder::on_activate(Price p, Quantity q,
void NativeOrder::on_update(Price p, Quantity q, PerfTrace const &t) {
auto trace = t;
trace.order_update = utils::TimeStamp::now();
trace.order_key = key().value();
tracepoint(bts_trace, trace_order, (char *)"on_update", 0, trace.md_sn, 0);
switch (me->state.status()) {
@@ -408,14 +408,14 @@ void BookAlgo::report_state()
me->services->report_state(merged_state);
}
void BookAlgo::payup(const md::PriceSize& opposite, uint32_t cross_ticks)
void BookAlgo::payup(const md::PriceSize& opposite, const bts::orderman::BookUpdateEvent&, uint32_t cross_ticks)
{
double new_price = opposite.price() + me->tick_size * cross_ticks;
me->child.update(Price(new_price), Quantity(this_state().quantity()));
report_state();
}
void BookAlgo::paydown(const md::PriceSize& opposite, uint32_t cross_ticks)
void BookAlgo::paydown(const md::PriceSize& opposite, const bts::orderman::BookUpdateEvent&, uint32_t cross_ticks)
{
double new_price = opposite.price() - me->tick_size * cross_ticks;
me->child.update(Price(new_price), Quantity(this_state().quantity()));
@@ -42,8 +42,8 @@ protected:
virtual void transition(api::orderman::OrderStatus new_state, std::string = "");
virtual void report_state();
virtual void payup(const md::PriceSize&, uint32_t cross_ticks = 0);
virtual void paydown(const md::PriceSize&, uint32_t cross_ticks = 0);
virtual void payup(const md::PriceSize&, const bts::orderman::BookUpdateEvent&, uint32_t cross_ticks = 0);
virtual void paydown(const md::PriceSize&, const bts::orderman::BookUpdateEvent&, uint32_t cross_ticks = 0);
void detach(bts::api::orderman::OrderStatus status_after_detach = bts::api::orderman::ORDER_STATUS_CANCELED);
private:
struct PImpl;
@@ -12,12 +12,15 @@ using namespace api::orderman;
struct LeanOrder::PImpl
{
PImpl() {}
PImpl() : cross_threshold(), max_chase_ticks(0), detach_on_toward(false), opposite_at_inception(), num_chases(0)
{}
spark::QuantityMeasure cross_threshold;
uint32_t max_chase_ticks;
bool detach_on_toward;
md::PriceSize opposite_at_inception;
uint32_t num_chases;
};
@@ -34,25 +37,40 @@ void LeanOrder::setup_child(const api::orderman::OrderDefinition& this_def, cons
me->cross_threshold = lean_def.cross_threshold();
me->max_chase_ticks = lean_def.max_chase_ticks();
me->detach_on_toward = lean_def.detach_on_toward();
}
void LeanOrder::payup(const md::PriceSize& opposite, uint32_t cross_ticks)
void LeanOrder::payup(const md::PriceSize&, const bts::orderman::BookUpdateEvent& book, uint32_t cross_ticks /*= 0*/)
{
double new_price = opposite.price() + tick_size() * cross_ticks;
double new_price = me->opposite_at_inception.price() + tick_size() * cross_ticks;
double limit = me->opposite_at_inception.price() + tick_size() * me->max_chase_ticks;
if(new_price <= limit)
update_child(Price(new_price), Quantity(this_state().quantity()));
else
{
update_child(Price(limit), Quantity(this_state().quantity()));
update_child(Price(limit), Quantity(this_state().quantity()));
detach();
}
return;
}
const bts::orderman::BookSide& sellbook = book.book.side(api::Side::SIDE_SELL);
for(const auto& i : sellbook)
{
me->opposite_at_inception = i;
if(me->opposite_at_inception.price() > new_price)
break;
}
if(me->opposite_at_inception.price() <= new_price)
detach();
me->num_chases += cross_ticks+1;
if(me->num_chases >= me->max_chase_ticks)
detach();
report_state();
}
void LeanOrder::paydown(const md::PriceSize& opposite, uint32_t cross_ticks)
void LeanOrder::paydown(const md::PriceSize&, const bts::orderman::BookUpdateEvent& book, uint32_t cross_ticks /*= 0*/)
{
double new_price = opposite.price() - tick_size() * cross_ticks;
double new_price = me->opposite_at_inception.price() - tick_size() * cross_ticks;
double limit = me->opposite_at_inception.price() - tick_size() * me->max_chase_ticks;
if(new_price >= limit)
update_child(Price(new_price), Quantity(this_state().quantity()));
@@ -60,11 +78,24 @@ void LeanOrder::paydown(const md::PriceSize& opposite, uint32_t cross_ticks)
{
update_child(Price(limit), Quantity(this_state().quantity()));
detach();
}
return;
}
const bts::orderman::BookSide& buybook = book.book.side(api::Side::SIDE_BUY);
for(const auto& i : buybook)
{
me->opposite_at_inception = i;
if(me->opposite_at_inception.price() < new_price)
break;
}
if(me->opposite_at_inception.price() >= new_price)
detach();
me->num_chases += cross_ticks+1;
if(me->num_chases >= me->max_chase_ticks)
detach();
report_state();
}
void LeanOrder::on_book_update(const bts::orderman::BookUpdateEvent& book)
{
switch (this_state().status())
@@ -91,26 +122,36 @@ void LeanOrder::on_book_update(const bts::orderman::BookUpdateEvent& book)
{
const auto& opposite = book.book.side(api::Side::SIDE_SELL)[0];
if(opposite.price() < me->opposite_at_inception.price())
me->opposite_at_inception = opposite; //your lucky day, try to get luckier
{
if(me->detach_on_toward)
detach();
else
me->opposite_at_inception = opposite; //we don't want to detach so look at next level
}
else if(opposite.price() > me->opposite_at_inception.price())
payup(opposite); //you missed, payup
payup(opposite, book); //you missed, payup/join
else
{
if(opposite.size() <= thresh.value())
payup(opposite);
payup(opposite, book);
}
}
else
{
const auto& opposite = book.book.side(api::Side::SIDE_BUY)[0];
if(opposite.price() > me->opposite_at_inception.price())
me->opposite_at_inception = opposite;
{
if(me->detach_on_toward)
detach();
else
me->opposite_at_inception = opposite;
}
else if(opposite.price() < me->opposite_at_inception.price())
paydown(opposite);
paydown(opposite, book);
else
{
if(opposite.size() <= thresh.value())
paydown(opposite);
paydown(opposite, book);
}
}
}
@@ -24,8 +24,8 @@ protected:
api::orderman::OrderState&, api::orderman::OrderDefinition*) override;
void on_book_update(const bts::orderman::BookUpdateEvent&) override;
private:
void payup(const md::PriceSize& opposite, uint32_t cross_ticks = 0) override;
void paydown(const md::PriceSize& opposite, uint32_t cross_ticks = 0) override;
void payup(const md::PriceSize& opposite, const bts::orderman::BookUpdateEvent&, uint32_t cross_ticks = 0) override;
void paydown(const md::PriceSize& opposite, const bts::orderman::BookUpdateEvent&, uint32_t cross_ticks = 0) override;
private:
struct PImpl;
@@ -43,7 +43,7 @@ void TickOrder::setup_child(const api::orderman::OrderDefinition& this_def, cons
me->detach_on_toward = tick_def.detach_on_toward();
}
void TickOrder::payup(const md::PriceSize& opposite, uint32_t cross_ticks)
void TickOrder::payup(const md::PriceSize& opposite, const bts::orderman::BookUpdateEvent&, uint32_t cross_ticks)
{
double new_price = opposite.price() + tick_size() * cross_ticks;
double limit = me->opposite_at_inception.price() + tick_size() * me->max_chase_ticks;
@@ -57,7 +57,7 @@ void TickOrder::payup(const md::PriceSize& opposite, uint32_t cross_ticks)
report_state();
}
void TickOrder::paydown(const md::PriceSize& opposite, uint32_t cross_ticks)
void TickOrder::paydown(const md::PriceSize& opposite, const bts::orderman::BookUpdateEvent&, uint32_t cross_ticks)
{
double new_price = opposite.price() - tick_size() * cross_ticks;
double limit = me->opposite_at_inception.price() - tick_size() * me->max_chase_ticks;
@@ -127,11 +127,11 @@ void TickOrder::on_book_update(const bts::orderman::BookUpdateEvent& book)
me->opposite_at_inception = opposite;
}
else if(opposite.price() > me->opposite_at_inception.price())
payup(opposite, me->cross_ticks);
payup(opposite, book, me->cross_ticks);
else
{
if(opposite.size() <= thresh.value())
payup(opposite, me->cross_ticks);
payup(opposite, book, me->cross_ticks);
}
}
else
@@ -145,11 +145,11 @@ void TickOrder::on_book_update(const bts::orderman::BookUpdateEvent& book)
me->opposite_at_inception = opposite;
}
else if(opposite.price() < me->opposite_at_inception.price())
paydown(opposite, me->cross_ticks);
paydown(opposite, book, me->cross_ticks);
else
{
if(opposite.size() <= thresh.value())
paydown(opposite, me->cross_ticks);
paydown(opposite, book, me->cross_ticks);
}
}
}
@@ -24,8 +24,8 @@ protected:
api::orderman::OrderState&, api::orderman::OrderDefinition*) override;
void on_book_update(const bts::orderman::BookUpdateEvent&) override;
private:
void payup(const md::PriceSize& opposite, uint32_t cross_ticks) override;
void paydown(const md::PriceSize& opposite, uint32_t cross_ticks) override;
void payup(const md::PriceSize& opposite, const bts::orderman::BookUpdateEvent&, uint32_t cross_ticks) override;
void paydown(const md::PriceSize& opposite, const bts::orderman::BookUpdateEvent&, uint32_t cross_ticks) override;
private:
struct PImpl;
@@ -12,6 +12,7 @@ def gen_create_table(d,t):
print ".import %s trace" % t
print '''create view tick_to_order as select
event_id,
order_key,
(fix_socket_w - md) / 1000 total,
(md_src-md)/1000 md_to_md_src,
(spreader_on_book-md_src)/1000 md_src_to_spreader,