Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
38bf38c62d | ||
|
|
4e08a43d0c | ||
|
|
4f912f99bd | ||
|
|
ae7e1761a7 | ||
|
|
4891eea5ba | ||
|
|
bc36db0480 | ||
|
|
cdaba74c06 | ||
|
|
b045307f30 | ||
|
|
60a7b504db | ||
|
|
0f62f14a1d | ||
|
|
87030dbb88 |
No files matched your search
@@ -1,3 +1,13 @@
|
||||
1.1.7
|
||||
- Fixed spread leg price fill
|
||||
- Fixed HO cash per point value
|
||||
|
||||
1.1.6
|
||||
- Fixed occasional crash when filtering fills
|
||||
- Fixed several cash per point multipliers
|
||||
- Colored time of sales row with aggressor side
|
||||
- Iceberg orders now cancel (rathern than error) when a child is canceled
|
||||
|
||||
1.1.0
|
||||
- Added per user self match protection, location and self match protection FIX tag settings
|
||||
- Implemented a new "Trigger Order" algo
|
||||
|
||||
@@ -6,11 +6,14 @@ using mbts.ui.controls;
|
||||
using mbts.ui.spark;
|
||||
using mbts.ui.utility;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using static bts.shell.TimeAndSalesWindowFactory;
|
||||
using static mbts.ui.controls.DIYGrid;
|
||||
|
||||
namespace mbts.spark {
|
||||
class TimeAndSalesVM : SecurityGrid<TimeAndSalesVM.Row, TradeInfo> {
|
||||
@@ -26,23 +29,32 @@ namespace mbts.spark {
|
||||
security_filter.load_state(filters.security);
|
||||
price_filter.load_state(filters.price);
|
||||
size_filter.load_state(filters.size);
|
||||
aggressor_filter.load_state(filters.aggressor_sides);
|
||||
trade_key_filter.load_state(filters.trade_key);
|
||||
security_key_filter.load_state(filters.security_key);
|
||||
}
|
||||
// Columns
|
||||
add_column(TimeAndSalesView.Columns.Security, "Security", DIYGrid.DefaultColumnWidths.Security, security_filter, DataGridFilterKnownTemplates.Regex);
|
||||
add_column(TimeAndSalesView.Columns.Time, "Time", DIYGrid.DefaultColumnWidths.Time, time_filter, DataGridFilterKnownTemplates.TimeFilter);
|
||||
add_column(TimeAndSalesView.Columns.Price, "Price", DIYGrid.DefaultColumnWidths.Price, price_filter, DataGridFilterKnownTemplates.DoubleMinMax);
|
||||
add_column(TimeAndSalesView.Columns.Size, "Size", DIYGrid.DefaultColumnWidths.Size, size_filter, DataGridFilterKnownTemplates.UIntMinMax);
|
||||
add_column(TimeAndSalesView.Columns.TradeKey, "Trade Key", DIYGrid.DefaultColumnWidths.TradeKey, trade_key_filter, DataGridFilterKnownTemplates.Regex);
|
||||
add_column(TimeAndSalesView.Columns.SecurityKey, "Security Key", DIYGrid.DefaultColumnWidths.SecurityKey, security_key_filter, DataGridFilterKnownTemplates.Regex);
|
||||
void add_column(TimeAndSalesView.Columns col_key, string header, double width, IDataGridColumnFilter filter, string filter_template) =>
|
||||
columns.Add(new DIYGrid.RenderTextColumn<Row>(r => r[col_key], filter, filter_template) { Header = header, Width = width });
|
||||
//
|
||||
add_column(TimeAndSalesView.Columns.Security, DefaultColumnHeaders.Security, DefaultColumnWidths.Security, security_filter, DataGridFilterKnownTemplates.Regex);
|
||||
add_column(TimeAndSalesView.Columns.Time, DefaultColumnHeaders.Time, DefaultColumnWidths.Time, time_filter, DataGridFilterKnownTemplates.TimeFilter);
|
||||
add_column(TimeAndSalesView.Columns.Price, DefaultColumnHeaders.Price, DefaultColumnWidths.Price, price_filter, DataGridFilterKnownTemplates.DoubleMinMax, System.Windows.HorizontalAlignment.Right);
|
||||
add_column(TimeAndSalesView.Columns.Size, DefaultColumnHeaders.Size, DefaultColumnWidths.Size, size_filter, DataGridFilterKnownTemplates.UIntMinMax, System.Windows.HorizontalAlignment.Right);
|
||||
add_column(TimeAndSalesView.Columns.Aggressor, DefaultColumnHeaders.Aggressor, DIYGrid.DefaultColumnWidths.Aggressor, aggressor_filter, DataGridFilterKnownTemplates.EnumValues);
|
||||
add_column(TimeAndSalesView.Columns.TradeKey, DefaultColumnHeaders.TradeKey, DIYGrid.DefaultColumnWidths.TradeKey, trade_key_filter, DataGridFilterKnownTemplates.Regex);
|
||||
add_column(TimeAndSalesView.Columns.SecurityKey, DefaultColumnHeaders.SecurityKey, DIYGrid.DefaultColumnWidths.SecurityKey, security_key_filter, DataGridFilterKnownTemplates.Regex);
|
||||
void add_column(TimeAndSalesView.Columns col_key, string header, double width, IDataGridColumnFilter filter, string filter_template, System.Windows.HorizontalAlignment h_alignment = System.Windows.HorizontalAlignment.Left) =>
|
||||
columns.Add(new TimeAndSalesColumn(
|
||||
r => r[col_key]
|
||||
, (r) => _get_aggressor_brush(r)
|
||||
, filter
|
||||
, filter_template
|
||||
)
|
||||
{ Header = header, Width = width, horizontal_alignment = h_alignment }
|
||||
);
|
||||
|
||||
_resources.AddRange(
|
||||
show_ladder,
|
||||
DataGridFilterHelper.hook_filters(
|
||||
rows_view, time_filter, security_filter, price_filter, size_filter, trade_key_filter, security_key_filter
|
||||
rows_view, time_filter, security_filter, price_filter, size_filter, aggressor_filter, trade_key_filter, security_key_filter
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -50,11 +62,22 @@ namespace mbts.spark {
|
||||
public ObservableCollection<DIYGrid.ColumnBase> columns { get; } = new ObservableCollection<DIYGrid.ColumnBase>();
|
||||
public DelegateCommandParamObserver<Row> show_ladder { get; }
|
||||
|
||||
private Brush _get_aggressor_brush(Row r) {
|
||||
BTSColor c;
|
||||
Brush b;
|
||||
if (r.aggressor_side == AggressorSide.Buy) c = BTSColors.MarketData.bid;
|
||||
else if (r.aggressor_side == AggressorSide.Sell) c = BTSColors.MarketData.ask;
|
||||
else c = Brushes.Transparent;
|
||||
(b = new SolidColorBrush(c) { Opacity = 0.33 }).Freeze();
|
||||
return b;
|
||||
}
|
||||
|
||||
#region Filters
|
||||
public IDataGridColumnPersistentFilter<Row, TimeFilterTuple> time_filter { get; } = new TimeFilterVM<Row>(r => r.time, nameof(Row.time));
|
||||
public IDataGridColumnPersistentFilter<Row, string> security_filter { get; }
|
||||
public IDataGridColumnPersistentFilter<Row, DoubleMinMaxState> price_filter { get; } = new DoubleMinMax<Row>(r => r.price, nameof(Row.price));
|
||||
public IDataGridColumnPersistentFilter<Row, UIntMinMaxState> size_filter { get; } = new UIntMinMax<Row>(r => r.size, nameof(Row.size));
|
||||
public IDataGridColumnPersistentFilter<Row, AggressorSide[]> aggressor_filter { get; } = DiscreteValuesFilterVM.Create<Row, AggressorSide>(EnumHelper.get_values<AggressorSide>().ToArray(), r => r.aggressor_side, nameof(Row.aggressor_side));
|
||||
public IDataGridColumnPersistentFilter<Row, string> security_key_filter { get; } = new RegexFilterVM<Row>(r => r.security_key.ToString(), nameof(Row.security_key));
|
||||
public IDataGridColumnPersistentFilter<Row, string> trade_key_filter { get; } = new RegexFilterVM<Row>(r => r.trade_key.ToString(), nameof(Row.trade_key));
|
||||
|
||||
@@ -65,7 +88,8 @@ namespace mbts.spark {
|
||||
price = price_filter.get_state(),
|
||||
size = size_filter.get_state(),
|
||||
trade_key = trade_key_filter.get_state(),
|
||||
security_key = security_key_filter.get_state()
|
||||
security_key = security_key_filter.get_state(),
|
||||
aggressor_sides = aggressor_filter.get_state()
|
||||
};
|
||||
#endregion
|
||||
|
||||
@@ -90,6 +114,7 @@ namespace mbts.spark {
|
||||
_time_text,
|
||||
_price_text,
|
||||
_size_text,
|
||||
_aggressor_text,
|
||||
_trade_key_text,
|
||||
_security_key_text;
|
||||
|
||||
@@ -98,11 +123,13 @@ namespace mbts.spark {
|
||||
time = trade.Time.lldatetime();
|
||||
price = trade.Mantissa * Math.Pow(10, trade.Exponent);
|
||||
size = trade.Size;
|
||||
aggressor_side = trade.AggressorSide;
|
||||
show_ladder = new DelegateCommand(() => parent._show_ladder_async(this).ignore());
|
||||
_security_text = security.ToString();
|
||||
_time_text = time.ToString("M/d h:mm:ss tt");
|
||||
_price_text = security.ContractSpec.format(price);
|
||||
_size_text = size.ToString();
|
||||
_aggressor_text = aggressor_side.ToString();
|
||||
_trade_key_text = _trade_key.ToString();
|
||||
_security_key_text = security_key.ToString();
|
||||
}
|
||||
@@ -113,6 +140,7 @@ namespace mbts.spark {
|
||||
public DateTime time { get; }
|
||||
public double price { get; }
|
||||
public uint size { get; }
|
||||
public AggressorSide aggressor_side { get; }
|
||||
public ICommand show_ladder { get; }
|
||||
|
||||
public string this[TimeAndSalesView.Columns col] {
|
||||
@@ -122,6 +150,7 @@ namespace mbts.spark {
|
||||
case TimeAndSalesView.Columns.Time: return _time_text;
|
||||
case TimeAndSalesView.Columns.Price: return _price_text;
|
||||
case TimeAndSalesView.Columns.Size: return _size_text;
|
||||
case TimeAndSalesView.Columns.Aggressor: return _aggressor_text;
|
||||
case TimeAndSalesView.Columns.TradeKey: return _trade_key_text;
|
||||
case TimeAndSalesView.Columns.SecurityKey: return _security_key_text;
|
||||
default: return null;
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace mbts.ui.spark {
|
||||
/// Interaction logic for TimeAndSalesView.xaml
|
||||
/// </summary>
|
||||
partial class TimeAndSalesView : UserControl {
|
||||
public enum Columns { Time, Security, Price, Size, OrderType, TradeKey, SecurityKey }
|
||||
public enum Columns { Time, Security, Price, Size, OrderType, TradeKey, SecurityKey, Aggressor }
|
||||
|
||||
public TimeAndSalesView() =>
|
||||
InitializeComponent();
|
||||
|
||||
@@ -12,6 +12,7 @@ using System.Reactive.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using static bts.shell.TimeAndSalesWindowFactory;
|
||||
using static mbts.ui.controls.DIYGrid;
|
||||
|
||||
namespace mbts.spark {
|
||||
class TimeAndSalesWindow : SparkWindow<StartupData>, ISlowWindow {
|
||||
@@ -36,7 +37,16 @@ namespace mbts.spark {
|
||||
public override string window_type => _window_type;
|
||||
public override IEnumerable<SparkCommand> Commands => _commands;
|
||||
public override UIElement Content => _view;
|
||||
public override double MinWidth => 444 + SPARK_MENU_COLLAPSED_WIDTH + LAUNCHER_BUTTON_BORDER_WIDTH;
|
||||
public override double MinWidth => DefaultColumnWidths.Security
|
||||
+ DefaultColumnWidths.Time
|
||||
+ DefaultColumnWidths.Price
|
||||
+ DefaultColumnWidths.Size
|
||||
+ DefaultColumnWidths.Aggressor
|
||||
+ DefaultColumnWidths.TradeKey
|
||||
+ DefaultColumnWidths.SecurityKey
|
||||
+ SPARK_MENU_COLLAPSED_WIDTH
|
||||
+ LAUNCHER_BUTTON_BORDER_WIDTH;
|
||||
|
||||
public override StartupData SaveState => _state = new StartupData(_state.security_criteria, _vm.value.rows_view.GetSortingCriteria(), _vm.value.get_filter_states());
|
||||
|
||||
public override void Dispose() =>
|
||||
|
||||
@@ -70,6 +70,8 @@ namespace bts.shell {
|
||||
public string trade_key;
|
||||
[ProtoMember(6)]
|
||||
public string security_key;
|
||||
[ProtoMember(7)]
|
||||
public co2.AggressorSide[] aggressor_sides;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,8 @@ namespace mbts.ui.controls {
|
||||
Time = 100,
|
||||
TimeInForce = 47,
|
||||
TradeKey = 76,
|
||||
User = 53;
|
||||
User = 53,
|
||||
Aggressor = 80;
|
||||
}
|
||||
|
||||
public static class DefaultColumnHeaders {
|
||||
@@ -40,7 +41,9 @@ namespace mbts.ui.controls {
|
||||
Size = "Qty",
|
||||
TimeInForce = "TIF",
|
||||
TradeKey = "Trade Key",
|
||||
User = "User";
|
||||
User = "User",
|
||||
Time = "Time",
|
||||
Aggressor = "Aggressor";
|
||||
}
|
||||
|
||||
internal interface IKeyedColumn<TColKey> {
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
using mbts.spark;
|
||||
using mbts.spark.filters;
|
||||
using mbts.ui.utility.text;
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace mbts.ui.controls {
|
||||
public partial class DIYGrid {
|
||||
internal class TimeAndSalesColumn : RenderTextColumn<TimeAndSalesVM.Row> {
|
||||
|
||||
readonly Func<TimeAndSalesVM.Row, string> _get_text;
|
||||
readonly Func<TimeAndSalesVM.Row, Brush> _get_brush;
|
||||
|
||||
public TimeAndSalesColumn(Func<TimeAndSalesVM.Row, string> get_text, Func<TimeAndSalesVM.Row, Brush> get_brush, IDataGridColumnFilter filter = null, string filter_template = null, GlyphContext glyph_context = null) : base(get_text, filter, filter_template, glyph_context) {
|
||||
_get_text = get_text;
|
||||
_get_brush = get_brush;
|
||||
}
|
||||
|
||||
public override void draw(TimeAndSalesVM.Row row, DrawingContext dc, ColumnGeometry position, double row_height) {
|
||||
CellRender.draw_text(dc
|
||||
, glyph_context
|
||||
, font_size
|
||||
, _get_text(row)
|
||||
, position
|
||||
, row_height
|
||||
, foreground
|
||||
, _get_brush(row)
|
||||
, horizontal_alignment
|
||||
, vertical_alignment
|
||||
, padding);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -190,17 +190,21 @@ namespace mbts.ui.controls
|
||||
}
|
||||
}
|
||||
|
||||
void item_Unselected(object sender, RoutedEventArgs e) {
|
||||
if (_selection_changing) return;
|
||||
var item = ((ListBoxItem)sender).DataContext;
|
||||
var selected_items = Selection;
|
||||
if (selected_items.Contains(item)) {
|
||||
using (_selection_change()) {
|
||||
selected_items.Remove(item);
|
||||
_update_is_all_selected();
|
||||
}
|
||||
}
|
||||
}
|
||||
void item_Unselected(object sender, RoutedEventArgs e) {
|
||||
if (!_selection_changing && sender is ListBoxItem container) {
|
||||
// the [ListBoxItem] sender may be "Disconnected" https://stackoverflow.com/questions/14282894/wpf-listbox-virtualization-creates-disconnecteditems/14358688
|
||||
var item = ItemContainerGenerator.ItemFromContainer(container);
|
||||
if (item != DependencyProperty.UnsetValue) {
|
||||
var selected_items = Selection;
|
||||
if (selected_items.Contains(item)) {
|
||||
using (_selection_change()) {
|
||||
selected_items.Remove(item);
|
||||
_update_is_all_selected();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void item_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e) {
|
||||
using (_selection_change()) ((ListBoxItem)sender).IsSelected = Selection.Contains(e.NewValue);
|
||||
@@ -368,4 +372,4 @@ namespace mbts.ui.controls
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1399
-5505
File diff suppressed because it is too large.
Load diff
@@ -115,7 +115,7 @@ void MDProducerHandle::set_status(CoconutSecurityStatus status) {
|
||||
}
|
||||
}
|
||||
|
||||
void MDProducerHandle::add_trade(TimeStamp time, const PriceSize price, LLDateTime tradetime, uint32_t volume) {
|
||||
void MDProducerHandle::add_trade(TimeStamp time, const PriceSize price, LLDateTime tradetime, co2::AggressorSide agside, uint32_t volume) {
|
||||
cdata().last_trade.store(price);
|
||||
cdata().last_trade_time = tradetime;
|
||||
cdata().total_volume = volume;
|
||||
@@ -127,6 +127,7 @@ void MDProducerHandle::add_trade(TimeStamp time, const PriceSize price, LLDateTi
|
||||
trade.set_mantissa(price.mantissa());
|
||||
trade.set_size(price.size());
|
||||
trade.set_time(tradetime);
|
||||
trade.set_aggressor_side(agside);
|
||||
if (volume > 0) trade.set_total_volume(volume);
|
||||
trade.set_key(key());
|
||||
_channel.add_trade(trade);
|
||||
|
||||
@@ -56,7 +56,7 @@ public:
|
||||
void set_status(co2::CoconutSecurityStatus status); // hot
|
||||
|
||||
// Updates trade log and last trade
|
||||
void add_trade(TimeStamp time, const PriceSize pricesize, datetime::LLDateTime date, uint32_t total_volume=0); // cold
|
||||
void add_trade(TimeStamp time, const PriceSize pricesize, datetime::LLDateTime date, co2::AggressorSide agside, uint32_t total_volume=0); // cold
|
||||
// Update last_trade without updating trade log
|
||||
void set_last_trade(TimeStamp time, const PriceSize ps, datetime::LLDateTime date, uint32_t total_volume);
|
||||
void add_rfq(TimeStamp time, const co2::QuoteRequestMessage& rfq); // cold
|
||||
|
||||
@@ -119,6 +119,12 @@ message MiscMessage {
|
||||
double session_low_offer = 12;
|
||||
double fixing_price = 13;
|
||||
}
|
||||
|
||||
enum AggressorSide {
|
||||
AGGRESSOR_SIDE_NONE = 0;
|
||||
AGGRESSOR_SIDE_BUY = 1;
|
||||
AGGRESSOR_SIDE_SELL = 2;
|
||||
}
|
||||
|
||||
message TradeMessage {
|
||||
uint32 key = 1;
|
||||
@@ -130,6 +136,7 @@ message TradeMessage {
|
||||
uint32 size = 6;
|
||||
uint32 total_volume = 7;
|
||||
bool gap = 8;
|
||||
AggressorSide aggressor_side = 9;
|
||||
}
|
||||
message QuoteRequestMessage {
|
||||
enum Side {
|
||||
|
||||
@@ -474,7 +474,8 @@ void ExchangeSimApplication::update_md(std::string const &sec_desc) {
|
||||
utils::TimeStamp::now(),
|
||||
md::PriceSize::from_double<7>(t.price.value() * price_factor,
|
||||
t.quantity.value()),
|
||||
datetime::ll_now());
|
||||
datetime::ll_now(),
|
||||
co2::AGGRESSOR_SIDE_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <vector>
|
||||
#include "lib/utils/helper_macros.h"
|
||||
#include "lib/config/protos/MarketData.pb.h"
|
||||
#include "lib/md/protos/co2.pb.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace bts::co2;
|
||||
@@ -349,11 +350,23 @@ void MDP3Listener::onBookUpdate(onixs::Handler&, const onixs::Security& sec, con
|
||||
//
|
||||
// Trades
|
||||
|
||||
void on_trade(SecurityData* data, const onixs::PRICE& price, int size, const onixs::Timestamp& onixs_date) {
|
||||
AggressorSide map_aggressor(onixs::AggressorSide::Enum agside) {
|
||||
switch(agside) {
|
||||
default:
|
||||
case onixs::AggressorSide::NoAggressor:
|
||||
return AGGRESSOR_SIDE_NONE;
|
||||
case onixs::AggressorSide::Buy:
|
||||
return AGGRESSOR_SIDE_BUY;
|
||||
case onixs::AggressorSide::Sell:
|
||||
return AGGRESSOR_SIDE_SELL;
|
||||
}
|
||||
}
|
||||
|
||||
void on_trade(SecurityData* data, const onixs::PRICE& price, int size, AggressorSide agside, const onixs::Timestamp& onixs_date) {
|
||||
auto ts = utils::TimeStamp::now();
|
||||
PriceSize ps = pricesize_of_price_size(price, data->handle.security().display_factor, size);
|
||||
auto date = ll_of_timestamp(onixs_date);
|
||||
data->handle.add_trade(ts, ps, date, data->electronic_volume + size);
|
||||
data->handle.add_trade(ts, ps, date, agside, data->electronic_volume + size);
|
||||
}
|
||||
|
||||
void MDP3Listener::onTrade(onixs::Handler&, const onixs::Security& sec, const onixs::RecoveryEntryArgs& arg) {
|
||||
@@ -364,7 +377,7 @@ void MDP3Listener::onTrade(onixs::Handler&, const onixs::Security& sec, const on
|
||||
arg.entry().entrySize(size);
|
||||
onixs::PRICE price;
|
||||
arg.entry().entryPx(price);
|
||||
on_trade(data, price, size, arg.message().transactTime());
|
||||
on_trade(data, price, size, AGGRESSOR_SIDE_NONE, arg.message().transactTime());
|
||||
}
|
||||
}
|
||||
void MDP3Listener::onTrade(onixs::Handler&, const onixs::Security& sec, const onixs::TradeSummaryArgs& arg) {
|
||||
@@ -373,7 +386,9 @@ void MDP3Listener::onTrade(onixs::Handler&, const onixs::Security& sec, const on
|
||||
if (data != NULL) {
|
||||
auto size = arg.entry().entrySize();
|
||||
onixs::PRICE price = arg.entry().entryPx();
|
||||
on_trade(data, price, size, arg.message().transactTime());
|
||||
onixs::AggressorSide::Enum agside = onixs::AggressorSide::NoAggressor;
|
||||
arg.entry().aggressorSide(agside);
|
||||
on_trade(data, price, size, map_aggressor(agside), arg.message().transactTime());
|
||||
}
|
||||
}
|
||||
void MDP3Listener::onTrade(onixs::Handler&, const onixs::Security& sec, const onixs::TradeArgs& arg) {
|
||||
@@ -383,7 +398,9 @@ void MDP3Listener::onTrade(onixs::Handler&, const onixs::Security& sec, const on
|
||||
if (data != nullptr) {
|
||||
int size = arg.entry().entrySize();
|
||||
onixs::PRICE price = arg.entry().entryPx();
|
||||
on_trade(data, price, size, arg.message().transactTime());
|
||||
onixs::AggressorSide::Enum agside = onixs::AggressorSide::NoAggressor;
|
||||
arg.entry().aggressorSide(agside);
|
||||
on_trade(data, price, size, map_aggressor(agside), arg.message().transactTime());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,9 +218,14 @@ 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>())
|
||||
data->price = securities::decode_exchange_price(
|
||||
*sec, Price(msg.get<fix::Price>()));
|
||||
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>()));
|
||||
}
|
||||
else
|
||||
data->price = Price(os::nan());
|
||||
|
||||
|
||||
@@ -271,9 +271,17 @@ void IcebergOrder::on_child_order_update(OrderStateUpdateEvent const &ev) {
|
||||
break;
|
||||
}
|
||||
|
||||
case ORDER_STATUS_CANCELED:
|
||||
LOG(OrderMan, Info,
|
||||
"Unexpected cancel of child {} in Iceberg Order {}. Canceling "
|
||||
"parent",
|
||||
ev.key.value(),
|
||||
key().value());
|
||||
transition(ORDER_STATUS_CANCELED);
|
||||
break;
|
||||
|
||||
case ORDER_STATUS_DISCONNECTED:
|
||||
case ORDER_STATUS_REJECTED_BY_SPARK:
|
||||
case ORDER_STATUS_CANCELED:
|
||||
case ORDER_STATUS_ERROR:
|
||||
me->child.clear();
|
||||
transition(ORDER_STATUS_ERROR, "Unexpected child order state");
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
$known_good = @{
|
||||
"6A" = 1000
|
||||
"6B" = 625
|
||||
"6D" = 1000
|
||||
"6E" = 1250
|
||||
"6J" = 1250
|
||||
"CL" = 1000
|
||||
"EMD" = 100
|
||||
"ES" = 50
|
||||
"GC" = 100
|
||||
"GE" = 2500
|
||||
"HE" = 400
|
||||
"HG" = 5000
|
||||
"HO" = 42000
|
||||
"LE" = 400
|
||||
"M6E" = 125
|
||||
"NG" = 100
|
||||
"NQ" = 20
|
||||
"QM" = 500
|
||||
"RB" = 42000
|
||||
"RTY" = 50
|
||||
"SI" = 5000
|
||||
"VX" = 1000
|
||||
"YI" = 10
|
||||
"YM" = 5
|
||||
"ZB" = 1000
|
||||
"ZC" = 50
|
||||
"ZF" = 1000
|
||||
"ZL" = 600
|
||||
"ZM" = 100
|
||||
"ZN" = 1000
|
||||
"ZQ" = 4167
|
||||
"ZS" = 50
|
||||
"ZT" = 2000
|
||||
"ZW" = 50
|
||||
}
|
||||
@@ -1,43 +1,9 @@
|
||||
$known_good = @{
|
||||
"6A" = 1000
|
||||
"6B" = 625
|
||||
"6D" = 1000
|
||||
"6E" = 1250
|
||||
"6J" = 1250
|
||||
"M6E" = 125
|
||||
"NQ" = 20
|
||||
"ES" = 50
|
||||
"YM" = 5
|
||||
"RTY" = 50
|
||||
"VX" = 1000
|
||||
"EMD" = 100
|
||||
"GE" = 2500
|
||||
"ZB" = 1000
|
||||
"ZN" = 1000
|
||||
"ZF" = 1000
|
||||
"ZT" = 2000
|
||||
"ZQ" = 4167
|
||||
"SI" = 50
|
||||
"YI" = 10
|
||||
"GC" = 100
|
||||
"HG" = 250
|
||||
"CL" = 1000
|
||||
"NG" = 100
|
||||
"HO" = 420
|
||||
"QM" = 500
|
||||
"RB" = 420
|
||||
"ZC" = 50
|
||||
"ZS" = 50
|
||||
"ZW" = 50
|
||||
"LE" = 400
|
||||
"HE" = 400
|
||||
"ZM" = 100
|
||||
"ZL" = 600
|
||||
}
|
||||
# Dot sourcing the reqs file will make
|
||||
. .\Generate-Cpps-reqs.ps1
|
||||
|
||||
$cme_file_url = "ftp://ftp.cmegroup.com/pub/fprf/csv/cmeg.fut.prf.csv"
|
||||
$csv_save_path = ".\cmeg.fut.prf.csv"
|
||||
$output_file = ".\cpp_out.txt"
|
||||
$output_file = ".\cpp_config.conf"
|
||||
|
||||
# turn off console update progress while downloading
|
||||
$CurrentProgressPref = $ProgressPreference;
|
||||
@@ -47,11 +13,23 @@ $ProgressPreference = $CurrentProgressPref
|
||||
|
||||
$a = Import-Csv $csv_save_path
|
||||
$b = $a | select Sym, Mult | Group Sym | Sort Name
|
||||
|
||||
@"
|
||||
# Generated by automated script. DO NOT EDIT!
|
||||
# source: tools/cpp_helper/generate-cpps.ps1
|
||||
"@ | out-file -Encoding ascii $output_file
|
||||
"CppConfig`n{`n`tvalue`n`t{" | out-file -Encoding ascii $output_file -Append
|
||||
$b | % {
|
||||
if ($known_good.ContainsKey($_.Group[0].Sym)) {
|
||||
$cpp = $known_good[$_.Group[0].Sym]
|
||||
} else {
|
||||
$cpp = $_.Group[0].Mult
|
||||
}
|
||||
"cpp_entry {{ `n`tkey: `"{0}`"`n`tvalue: {1}`n}}" -f $_.Group[0].Sym, $cpp } `
|
||||
| out-file -Encoding ascii $output_file
|
||||
"`t`tcpp_entry {{ key: `"{0}`" value: {1} }}" -f $_.Group[0].Sym, $cpp } `
|
||||
| out-file -Encoding ascii $output_file -Append
|
||||
"`t}`n}" | out-file -Encoding ascii $output_file -Append
|
||||
Remove-Item $csv_save_path -Force
|
||||
|
||||
# You can now copy the output file to defaults assuming all looks good
|
||||
# Copy-Item .\cpp_config.conf ..\..\src\lib\config\defaults\ -Force
|
||||
# Remove-Item cpp-config.conf
|
||||
Reference in new issue
Block a user