Compare commits

..
14 Commits
Author SHA1 Message Date
Eric Harding 5379e39816 SP-142 Terrible meat hack 2019-10-07 16:36:18 -04:00
Eric Harding f62df97f1d OnixS instructions don't work. Wait to start the handlers until the market is open. 2019-09-03 10:30:57 -04:00
Eric Harding 3a3394d783 Add sunday_pre_open flag to md config for HE/LE startup. 2019-08-19 10:15:13 -04:00
Kevin Darby 632a86f670 Merge branch 'prod' of bitbucket.org:bluetradesys/spark 2019-08-15 09:35:33 -04:00
Taha Afzal cdbda8250f 'Fixing' the test (the test is broken, fill really fix it in the subsequent push) 2019-08-14 22:14:54 -04:00
John Colvin 43fd07dcfa Merged in SOM-ticks (pull request #320)
SPARK-1715 Handle fractional numerator tick sizes

Approved-by: Kevin Darby <kevin.darby@bluetradesys.com>
2019-08-14 20:43:00 +00:00
John Colvin efcb4f471c fix config toggle for som ticks 2019-08-14 15:40:23 -05:00
John Colvin d2f2e03e64 [SPARK-1715] config toggle for som ticks fix 2019-08-14 15:31:30 -05:00
John Colvin cfeba74900 SPARK-1715 Handle fractional numerator tick sizes 2019-08-14 14:50:42 -05:00
Jake Norbut 41bc4f7950 re-generated conf with SOM and latest from CME ftp 2019-08-14 11:51:07 -05:00
Jake Norbut 963bd15b35 adding SOM manual list; CME does not publish SOM data in their ftp 2019-08-14 11:50:24 -05:00
Kevin Darby b080d4a9c4 Merged in master (pull request #318)
Spark 2.8

Approved-by: Kevin Darby <kevin.darby@bluetradesys.com>
2019-08-13 19:19:47 +00:00
pfisher 282e10cba3 fixed update.txt test 2019-08-13 12:04:11 -04:00
Kevin Darby fa1b436fb3 added sticky button release notes 2019-08-09 10:53:02 -04:00
115 changed files with 1415 additions and 4813 deletions

No files matched your search

+1
View File
@@ -16,6 +16,7 @@ insert_anchor_links = "right"
selected by default
- Increased width of login panel to better show login error messages
- Added optional 'Maker/Taker' pricing to Spreader algo
- Algo buttons in ladder can now be made to deactivate after launching an algo or remain 'sticky'
### Internal changes
- Made it easier to generate simple UI's for new order types
### API Changes
@@ -26,7 +26,6 @@ namespace mbts.spark {
readonly ObservableFilterCollection<OrderRecordImmutable> _working_orders, _working_bids, _working_asks;
readonly string _security_text, _security_key_text;
readonly Property<double> _bid_price, _ask_price, _last_price, _day_change, _settlement, _session_high, _session_low;
readonly Property<bool> _last_price_from_spread;
readonly CellProperty<int> _position;
readonly CellProperty<uint> _last_size;
readonly CellProperty<ulong> _volume;
@@ -54,7 +53,6 @@ namespace mbts.spark {
_day_change = backing(nameof(day_change), double.NaN);
_session_low = backing(nameof(session_low), double.NaN);
_session_high = backing(nameof(session_high), double.NaN);
_last_price_from_spread = backing(nameof(last_price_from_spread), false);
_settlement = backing(nameof(settlement), double.NaN);
_volume = new CellProperty<ulong>(this, nameof(volume), 0);
_inside_bids = new CellProperty<bool>(this, nameof(inside_bids));
@@ -105,7 +103,6 @@ namespace mbts.spark {
public bool inside_asks => _inside_asks.value;
public int position => _position.value;
public double last_price => _last_price.Value;
public bool last_price_from_spread => _last_price_from_spread.Value;
public uint last_size => _last_size.value;
public double bid_price => _bid_price.Value;
public uint bid_direct_size => _bid_direct_size.Value;
@@ -164,17 +161,15 @@ namespace mbts.spark {
_inside_bids.on_next_distinct(_bid_price.Value >= _working_best_bid.value, ref dirty);
_inside_asks.on_next_distinct(_ask_price.Value <= _working_best_ask.value, ref dirty);
}
if (md.md.get_last_trade(ref _last_ref, out NativePriceSize ps, out DateTime ts, out ulong v, out bool from_spread)) {
if (md.md.get_last_trade(ref _last_ref, out NativePriceSize ps, out DateTime ts, out ulong v)) {
_last_price.set(ps.price);
_last_price_from_spread.set(from_spread);
_last_size.on_next_distinct(ps.size, ref dirty);
_volume.on_next_distinct(v, ref dirty);
}
dirty |= _settlement.set_new(md.md.settlement_price);
dirty |= _session_low.set_new(md.md.session_low);
dirty |= _session_high.set_new(md.md.session_high);
dirty |= _day_change.set_new(last_price - settlement);
_volume.on_next_distinct(md.md.total_volume, ref dirty);
_settlement.set(md.md.settlement_price);
_session_low.set(md.md.session_low);
_session_high.set(md.md.session_high);
_day_change.set(last_price - settlement);
if (dirty)
invalidated?.Invoke();
@@ -39,8 +39,7 @@ namespace mbts.spark {
IMultiValueConverter price_converter = new ui.spark.converters.TickDisplayConverter();
add_col(Columns.Security, "Security", r => r.security.ToString(), nameof(Row.security), DefaultColumnWidths.Security, security_filter, DataGridFilterKnownTemplates.Regex);
add_col(Columns.Volume, "Volume", r => r.volume.ToString(), nameof(Row.volume), DefaultColumnWidths.Volume, volume_filter, DataGridFilterKnownTemplates.ULongMinMax);
add_col(Columns.LastSpd, "Spd", r => r.last_price_from_spread ? "S" : "", nameof(Row.last_price_from_spread), DefaultColumnWidths.Side, last_price_from_spread_filter, DataGridFilterKnownTemplates.Regex);
add_col(Columns.Last, "Last", r => r.format_price(r.last_price), nameof(Row.last_price), DefaultColumnWidths.Price, last_price_filter, DataGridFilterKnownTemplates.DoubleMinMax);
add_col(Columns.Last, "Last", r => r.format_price(r.last_price), nameof(Row.last_price), DefaultColumnWidths.Price, last_price_filter, DataGridFilterKnownTemplates.DoubleMinMax);
add_col(Columns.LastSize, merged_size_col_header, r => r.last_size.ToString(), nameof(Row.last_size), DefaultColumnWidths.Size, last_size_filter, DataGridFilterKnownTemplates.UIntMinMax, h_alignment: System.Windows.HorizontalAlignment.Right);
add_col(Columns.Position, "Pos", r => r.position.ToString(), nameof(Row.position), DefaultColumnWidths.Size, position_filter, DataGridFilterKnownTemplates.IntMinMax, true, h_alignment: System.Windows.HorizontalAlignment.Right);
add_hl_working_orders_col(Columns.WorkingBids, working_col_header, nameof(Row.working_bids_text), nameof(Row.working_best_bid), nameof(Row.working_bids_click), working_bid_volume_filter, BTSColors.MarketData.bid, System.Windows.HorizontalAlignment.Right);
@@ -146,7 +145,6 @@ namespace mbts.spark {
ask_direct_size_filter.load_state(filters.ask_direct_size);
ask_implied_size_filter.load_state(filters.ask_implied_size);
last_price_filter.load_state(filters.last_price);
last_price_from_spread_filter.load_state(filters.last_price_from_spread);
last_size_filter.load_state(filters.last_size);
day_change_filter.load_state(filters.day_change);
settlement_filter.load_state(filters.settlement);
@@ -163,7 +161,7 @@ namespace mbts.spark {
}), DataGridFilterHelper.hook_filters(rows_view, security_filter,
bid_price_filter, bid_merged_size_filter, bid_direct_size_filter, bid_implied_size_filter,
ask_price_filter, ask_merged_size_filter, ask_direct_size_filter, ask_implied_size_filter,
last_price_filter, last_price_from_spread_filter, last_size_filter, day_change_filter, settlement_filter,
last_price_filter, last_size_filter, day_change_filter, settlement_filter,
session_low_filter, session_high_filter, position_filter, working_bid_volume_filter, working_ask_volume_filter, volume_filter, security_key_filter),
settings_manager.subscribe_current().OnDispatcher().Subscribe(grid_settings_manager),
WorkLoop.Start("MarketView", _refresh)
@@ -226,7 +224,6 @@ namespace mbts.spark {
public IDataGridColumnPersistentFilter<Row, UIntMinMaxState> ask_direct_size_filter { get; } = new UIntMinMax<Row>(r => r.ask_direct_size, nameof(Row.ask_direct_size));
public IDataGridColumnPersistentFilter<Row, UIntMinMaxState> ask_implied_size_filter { get; } = new UIntMinMax<Row>(r => r.ask_implied_size, nameof(Row.ask_implied_size));
public IDataGridColumnPersistentFilter<Row, DoubleMinMaxState> last_price_filter { get; } = new DoubleMinMax<Row>(r => r.last_price, nameof(Row.last_price));
public IDataGridColumnPersistentFilter<Row, string> last_price_from_spread_filter { get; } = new RegexFilterVM<Row>(r => r.last_price_from_spread.ToString(), nameof(Row.last_price_from_spread));
public IDataGridColumnPersistentFilter<Row, UIntMinMaxState> last_size_filter { get; } = new UIntMinMax<Row>(r => r.last_size, nameof(Row.last_size));
public IDataGridColumnPersistentFilter<Row, DoubleMinMaxState> day_change_filter { get; } = new DoubleMinMax<Row>(r => r.day_change, nameof(Row.day_change));
public IDataGridColumnPersistentFilter<Row, DoubleMinMaxState> settlement_filter { get; } = new DoubleMinMax<Row>(r => r.settlement, nameof(Row.settlement));
@@ -258,7 +255,6 @@ namespace mbts.spark {
ask_direct_size = ask_direct_size_filter.get_state(),
ask_implied_size = ask_implied_size_filter.get_state(),
last_price = last_price_filter.get_state(),
last_price_from_spread = last_price_from_spread_filter.get_state(),
last_size = last_size_filter.get_state(),
day_change = day_change_filter.get_state(),
settlement = settlement_filter.get_state(),
@@ -8,7 +8,7 @@ namespace mbts.ui.spark {
/// Interaction logic for MarketSheetsView.xaml
/// </summary>
partial class MarketViewView : UserControl {
public enum Columns { Security, Volume, Last, LastSpd, LastSize, Position, WorkingBids, Bid, BidMergedSize, BidDirectSize, BidImpliedSize, Ask, AskMergedSize, AskDirectSize, AskImpliedSize, WorkingAsks, Settlement, DayChange, SessionLow, SessionHigh, SecurityKey,
public enum Columns { Security, Volume, Last, LastSize, Position, WorkingBids, Bid, BidMergedSize, BidDirectSize, BidImpliedSize, Ask, AskMergedSize, AskDirectSize, AskImpliedSize, WorkingAsks, Settlement, DayChange, SessionLow, SessionHigh, SecurityKey,
MarketDescription, ClearedAlias, ProductDescription, HubAlias, StripName, MicCode
}
@@ -80,7 +80,6 @@ namespace bts.shell {
public static GridColumnSettings security => new GridColumnSettings(col_id(Columns.Security), DefaultColumnHeaders.Security, width: DefaultColumnWidths.Security);
public static GridColumnSettings volume => new GridColumnSettings(col_id(Columns.Volume), DefaultColumnHeaders.Volume, width: DefaultColumnWidths.Volume);
public static GridColumnSettings last => new GridColumnSettings(col_id(Columns.Last), DefaultColumnHeaders.Last, width: DefaultColumnWidths.Price);
public static GridColumnSettings last_from_spread => new GridColumnSettings(col_id(Columns.LastSpd), DefaultColumnHeaders.S, width: DefaultColumnWidths.Price, is_visible: false);
public static GridColumnSettings last_size => new GridColumnSettings(col_id(Columns.LastSize), DefaultColumnHeaders.Size, width: DefaultColumnWidths.Size, horizontal_alignment: System.Windows.HorizontalAlignment.Right);
public static GridColumnSettings position => new GridColumnSettings(col_id(Columns.Position), DefaultColumnHeaders.Pos, width: DefaultColumnWidths.Size, horizontal_alignment: System.Windows.HorizontalAlignment.Right);
public static GridColumnSettings working_bids => new GridColumnSettings(col_id(Columns.WorkingBids), DefaultColumnHeaders.Working, font_color_override: BTSColors.MarketData.bid, width: DefaultColumnWidths.Working, horizontal_alignment: System.Windows.HorizontalAlignment.Right);
@@ -118,7 +117,6 @@ namespace bts.shell {
yield return security;
yield return volume;
yield return last;
yield return last_from_spread;
yield return last_size;
yield return position;
yield return working_bids;
@@ -202,8 +200,6 @@ namespace bts.shell {
[ProtoMember(25)]
public string strip_name;
[ProtoMember(26)]
public string last_price_from_spread;
[ProtoMember(27)]
public string mic_code;
}
}
@@ -87,7 +87,6 @@ namespace mbts.spark {
add_col(Columns.Size, DefaultColumnHeaders.Size, r => r.size.ToString(), new DoubleMinMax<FillTuple>(r => r.fill.LastShares), DataGridFilterKnownTemplates.UIntMinMax, DefaultColumnWidths.Size);
add_col(Columns.Price, DefaultColumnHeaders.Price, r => r.format_price(r.price), new DoubleMinMax<FillTuple>(r => r.fill.LastPrice), DataGridFilterKnownTemplates.DoubleMinMax, DefaultColumnWidths.Price);
add_col(Columns.FillKind, DefaultColumnHeaders.FillKind, r => r.fill_kind.ToString(), dv_filter(EnumHelper.get_values<FillKind>().ToArray(), r => r.fill.FillKind), DataGridFilterKnownTemplates.DiscreteValues, DefaultColumnWidths.FillKind);
add_col(Columns.FillStatus, DefaultColumnHeaders.FillStatus, r => r.fill_status.ToString(), dv_filter(EnumHelper.get_values<FillStatus>().ToArray(), r => r.fill.FillStatus), DataGridFilterKnownTemplates.DiscreteValues, DefaultColumnWidths.FillKind);
add_col(Columns.FillKey, DefaultColumnHeaders.FillKey, r => r.fill_key.ToString(), new RegexFilterVM<FillTuple>(r => r.fill.FillKey), DataGridFilterKnownTemplates.Regex, DefaultColumnWidths.FillKey);
add_col(Columns.OrderKey, DefaultColumnHeaders.OrderKey, r => r.order_key.ToString(), new RegexFilterVM<FillTuple>(r => r.fill.OrderKey.ToString()), DataGridFilterKnownTemplates.Regex, DefaultColumnWidths.OrderKey);
add_col(Columns.SecurityKey, DefaultColumnHeaders.SecurityKey, r => r.security_key.ToString(), new RegexFilterVM<FillTuple>(r => r.fill.SecurityKey.ToString()), DataGridFilterKnownTemplates.Regex, DefaultColumnWidths.SecurityKey);
@@ -189,7 +188,6 @@ namespace mbts.spark {
case Columns.Exchange: return wrap_default(ft => ft.security.exchange_or_default());
case Columns.FillKey: return wrap(ft => ft.fill.FillKey);
case Columns.FillKind: return wrap_default(ft => ft.fill.FillKind);
case Columns.FillStatus: return wrap_default(ft => ft.fill.FillStatus);
case Columns.FillTime: return wrap(ft => ft.fill.Timestamp.to_local_time());
case Columns.OrderKey: return wrap(ft => ft.fill.OrderKey);
case Columns.OrderType: return wrap_default(ft => ft.order?.order_type() ?? OrderType.None);
@@ -251,7 +249,6 @@ namespace mbts.spark {
public double price => _fill.LastPrice;
public double size => _fill.LastShares;
public FillKind fill_kind => _fill.FillKind;
public FillStatus fill_status => _fill.FillStatus;
public string fill_key => _fill.FillKey;
public string order_key => _order.Key.ToString();
@@ -20,7 +20,6 @@ namespace mbts.ui.spark {
Price,
Size,
FillKind,
FillStatus,
FillKey,
OrderKey,
SecurityKey
@@ -67,8 +67,5 @@ namespace bts.shell {
set: (us, gs) => us.with(provided_fills_gridsettings: gs));
return new FillsWindow(this, _bus, _orders_model, state, settings_manager);
}
[ProtoMember(15)]
[DIYGridColumnID(nameof(Columns.FillStatus))]
public Fill.Types.FillStatus[] fill_status { get; set; }
}
}
@@ -70,10 +70,6 @@ namespace bts.shell.fills {
[ProtoMember(15)]
[DIYGridColumnID(nameof(Columns.Symbol))]
public string[] symbol { get; set; }
[ProtoMember(16)]
[DIYGridColumnID(nameof(Columns.FillStatus))]
public Fill.Types.FillStatus[] fill_status { get; set; }
}
static class FillsFilterStatesExtensions {
@@ -95,7 +91,6 @@ namespace bts.shell.fills {
pb.add_discrete_values(fs.side, ft => ft.fill.Side);
pb.add_discrete_values(fs.fill_kind, ft => ft.fill.FillKind);
pb.add_discrete_values(fs.symbol, ft => ft.security?.Symbol ?? string.Empty);
pb.add_discrete_values(fs.fill_status, ft => ft.fill.FillStatus);
// numeric
pb.add_numeric(fs.size, ft => ft.fill.LastShares);
pb.add_numeric(fs.price, ft => ft.fill.LastPrice);
@@ -96,7 +96,6 @@ namespace mbts.ui.controls {
Aggressor = "Aggressor",
Volume = "Volume",
Last = "Last",
S = "S",
Pos = "Pos",
Working = "Working",
Bid = "Bid",
@@ -106,7 +105,6 @@ namespace mbts.ui.controls {
SessionLow = "Low",
SessionHigh = "High",
FillKind = "Fill Kind",
FillStatus = "Fill Status",
Name = "Name",
Description = "Description",
N_Legs = "# Legs",
+17 -1
View File
@@ -197,6 +197,7 @@ namespace mbts.spark {
static class TickStore {
public static readonly RegionalTickFactors default_rtf = new RegionalTickFactors(new TickFactors(1000, 1), new TickFactors(1000, 1), double.MaxValue);
static readonly ConcurrentDictionary<SpecKey, RegionalTickFactors> _exchange_ticks = new ConcurrentDictionary<SpecKey, RegionalTickFactors>();
static readonly bool _som_ticks_fix_enabled = config.Configuration.get<bts.config.toggles.SOMTicksFix>().enabled;
public static RegionalTickFactors get(ContractSpecification spec) =>
_exchange_ticks.GetOrAdd(new SpecKey(spec), _create_rtf);
@@ -249,8 +250,23 @@ namespace mbts.spark {
var tf = _try_create_tf(tick_size, tick_base);
if (tf != null && display_digits_override > 0) {
int display_digit_diff = (int)display_digits_override - tf.display_digits();
if (display_digit_diff != 0)
if (_som_ticks_fix_enabled) {
// we can always add display_digits (i.e. dislpay_digit_diff > 0), of course the ticks can be expressed precisely with extra 0s.
// but if we are going to remove display_digits (i.e display_digit_diff < 0), we must make sure the tick_unit is large enough to be expressed precisely with that many fewer digits
// - "-display_digit_diff <= Math.Ceiling(Math.Log10(tf.tick_unit))" will tell us if the digits can be removed without compromising precision
// - unfortunately, we cannot rely on the exchange's ContractSpec for this, there is 1 known case where the data they give us is incorrect
// SOM spreads ContractSpec (from the exchange):
// LowTick: 0.0025 (aka 1/400, or 2/800)
// MainFraction: 8
// SubFraction: 0
// PriceDisplayFormat: 1
// - as you can see, this cannot possibly be formatted with 1 display digit, it ticks in increments of 1/400
// - in practice, to maintain the '8' base, we format this in increments of 2/800 (e.g. 1-000, 1-002, 1-004, and so on up to 1-778, 2-000)
if (display_digit_diff > 0 || (display_digit_diff < 0 && -display_digit_diff <= Math.Ceiling(Math.Log10(tf.tick_unit))))
tf = _inflate_to_base(tf, tf.tick_base * Math.Pow(10, display_digit_diff));
} else if (display_digit_diff != 0) {
tf = _inflate_to_base(tf, tf.tick_base * Math.Pow(10, display_digit_diff));
}
}
return tf;
}
+1 -8
View File
@@ -133,12 +133,6 @@ namespace mbts.co2 {
total_volume = _cold->total_volume;
return (_cold->last_trade.load_if_new(ref time, out ps));
}
public bool get_last_trade(ref ulong time, out NativePriceSize ps, out DateTime timestamp, out ulong total_volume, out bool from_spread) {
timestamp = _cold->last_trade_time;
total_volume = _cold->total_volume;
from_spread = (_cold->from_spread != 0);
return (_cold->last_trade.load_if_new(ref time, out ps));
}
public ulong misc_timestamp { get { return _cold->misc_timestamp; } }
public ulong total_volume { get { return _cold->total_volume; } }
@@ -265,7 +259,7 @@ namespace mbts.co2 {
// Last trade
public AtomicPriceSize last_trade;
public ulong total_volume;
public utils.LLDateTime last_trade_time;
public utils.LLDateTime last_trade_time;
//// Settlement
public UInt64 misc_timestamp;
@@ -286,7 +280,6 @@ namespace mbts.co2 {
public double session_low_offer;
public double fixing_price;
public int from_spread;
public int deleted;
// FixedSecurity will not be directly addressable. Instead the security is available through the callback
public Int64 security_size;
+1 -2
View File
@@ -142,8 +142,7 @@ namespace mbts.co2.tests
Assert.IsTrue(entry.session_low_offer == 5.5);
Assert.IsTrue(entry.fixing_price == 6.6);
Assert.IsTrue(entry.from_spread == 0);
Assert.IsTrue(entry.deleted == 1);
Assert.IsTrue(entry.deleted == 1);
}
[Test]
-2
View File
@@ -85,8 +85,6 @@ namespace bts.tests.utils {
if(timeout == null) {
timeout = TimeSpan.FromMinutes(2);
}
Console.WriteLine("Please Wait... this is going to take some time...");
await Task.Delay(180000);
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
@@ -11,6 +11,7 @@
-->
<connectivityConfiguration>
<!-- TCP Connection Information -->
<tcp>
<server name="default">
<ip>63.247.113.163</ip>
@@ -18,7 +19,7 @@
<userName>bluetrd-ps</userName>
<password>Starts123</password>
<getStripInfoMessages>N</getStripInfoMessages>
<strategyPreference>New</strategyPreference>
<strategyPreference>Legacy</strategyPreference>
<localNetworkInterface></localNetworkInterface>
</server>
<server name="endex">
@@ -27,7 +28,7 @@
<userName>Value from ICE Support</userName>
<password>Value from ICE Support</password>
<getStripInfoMessages>N</getStripInfoMessages>
<strategyPreference>New</strategyPreference>
<strategyPreference>Legacy</strategyPreference>
<localNetworkInterface></localNetworkInterface>
</server>
<server name="liffe-eu">
@@ -36,7 +37,7 @@
<userName>bluetrdl-ps</userName>
<password>Starts123</password>
<getStripInfoMessages>N</getStripInfoMessages>
<strategyPreference>New</strategyPreference>
<strategyPreference>Legacy</strategyPreference>
<localNetworkInterface></localNetworkInterface>
</server>
<settings>
@@ -17,10 +17,10 @@
<server name="default">
<ip>63.247.113.214</ip>
<port>3000</port>
<userName>bt_ps</userName>
<password>Starts123</password>
<userName>Value from ICE Support</userName>
<password>Value from ICE Support</password>
<getStripInfoMessages>N</getStripInfoMessages>
<strategyPreference>New</strategyPreference>
<strategyPreference>Legacy</strategyPreference>
<localNetworkInterface></localNetworkInterface>
</server>
<settings>
+1 -1
View File
@@ -1 +1 @@
set(sources api/apicore.proto;api/apigateway.proto;api/apioptions.proto;api/core/ApiClientInterop.cpp;api/core/ApiServerInterop.cpp;api/public/ApiServer.cpp;api/public/ClientChannel.cpp;api/public/QuickbusClientChannel.cpp;api/public/ServerChannel.cpp;api/public/ServiceContext.cpp;api/service_helpers/AdminServiceUtils.cpp;api/service_helpers/AlgoServiceUtils.cpp;api/services/AdminService.proto;api/services/AlgoDefinitionService.proto;api/services/AlgoService.proto;api/services/ApiUnitTestService.proto;api/services/AuthService.proto;api/services/ErrorReportService.proto;api/services/HelloService.proto;api/services/MBOService.proto;api/services/MarginService.proto;api/services/MarketDataAuxiliaryService.proto;api/services/MarketDataRelay.proto;api/services/OrderService.proto;api/services/OutOfProcessURLListener.proto;api/services/PersistenceService.proto;api/services/PositionService.proto;api/services/ShellDiagnosticService.proto;api/services/ShellLatencyService.proto;api/services/SyntheticSecurityService.proto;api/test/ApiTests.cpp;api/test/HelloServiceServer.cpp;config/ConfigCheck.cpp;config/ConfigDownloader.cpp;config/ConfigErrorCollector.cpp;config/ConfigLog.cpp;config/ConfigPropertyEvaluator.cpp;config/ConfigValueQueue.cpp;config/ConfigurationException.cpp;config/ConfigurationState.cpp;config/PreprocessInputStream.cpp;config/config.cpp;config/defaults/MarketData.conf;config/defaults/Ports.conf;config/defaults/Symbols.conf;config/defaults/cme_reference_data.conf;config/defaults/edge.conf;config/defaults/jetfix.conf;config/defaults/keycode.conf;config/defaults/logging.conf;config/defaults/orderman_cfg.conf;config/defaults/orders_fills_cleanup.conf;config/defaults/span.conf;config/defaults/spreader.conf;config/defaults/testkeys.conf;config/defaults/threads.conf;config/defaults/toggles.conf;config/extensions/extensions.proto;config/invalid/invalid.proto;config/protos/ExchangeSimCfg.proto;config/protos/MarketData.proto;config/protos/Ports.proto;config/protos/Symbols.proto;config/protos/UI.proto;config/protos/cme_reference_data.proto;config/protos/jetfix.proto;config/protos/keycode.proto;config/protos/logging.proto;config/protos/mercury_cfg.proto;config/protos/orderman_cfg.proto;config/protos/orders_fills_cleanup.proto;config/protos/perflog_cfg.proto;config/protos/quickbus_cfg.proto;config/protos/span.proto;config/protos/spreader.proto;config/protos/system.proto;config/protos/testkeys.proto;config/protos/threads.proto;config/protos/toggles.proto;config/tests/HTTPServer.cpp;config/tests/config_ref_tests.cpp;config/tests/config_tests.cpp;config/text_format/text_format.cpp;domain_model/Security.cpp;domain_model/Security.proto;domain_model/SecurityTests.cpp;domain_model/tests/domain_tests.cpp;expression/BooleanGrammar.cpp;expression/ExpressionEvaluator.cpp;expression/ParserExceptions.cpp;expression/Value.cpp;expression/tests/expression_parser_tests.cpp;logging/LoggerHub.cpp;logging/Sink.cpp;logging/logging.cpp;logging/tests/logging_tests.cpp;md/Diag/MDPeriodicDumper.cpp;md/Diag/ShmDumper.cpp;md/MBOProcessor.cpp;md/MBOServiceServer.cpp;md/MDClient.cpp;md/MDConsumer.cpp;md/MDConsumerHandle.cpp;md/MDConsumerInterop.cpp;md/MDProducer.cpp;md/MDProducerHandle.cpp;md/MemorySegmentUtils.cpp;md/PlatformLoader.cpp;md/PriceSize.cpp;md/SecurityCache.cpp;md/SecurityDB.cpp;md/SecurityIDRecorder.cpp;md/SecurityOracle.cpp;md/SettlementRecorder.cpp;md/Shm/FixedSecurity.cpp;md/SyntheticSecurityService.cpp;md/cme/MDP3Utils.cpp;md/common.cpp;md/ice/ICEUtils.cpp;md/protos/co2.proto;md/relay/QueryServer.cpp;md/relay/RelayClient.cpp;md/relay/RelayRecorder.cpp;md/test/Co2ManagedTestHelper.cpp;md/test/Co2TestInstrument.cpp;md/test/mbo_tests.cpp;md/test/md2_tests.cpp;md/test/md_test_utils.cpp;md/test/synthetic_book_merge_tests.cpp;os/os.cpp;os/tests/os_tests.cpp;quickbus/core/LocalNode.cpp;quickbus/core/Quickbus.cpp;quickbus/core/SubscriptionID.cpp;quickbus/core/TableID.cpp;quickbus/message_model/Update.cpp;quickbus/message_model/merge_updates.cpp;quickbus/network/QBConnection.cpp;quickbus/network/QBConnectionManager.cpp;quickbus/network/endpoint_description.cpp;quickbus/network/quickbus_msgs.proto;quickbus/pubsub/TablePublisher.cpp;quickbus/pubsub/TableSubscriber.cpp;quickbus/pubsub/tests/qb_pubsub_tests.cpp;quickbus/routing/INode.cpp;quickbus/routing/NodeID.cpp;quickbus/routing/Router.cpp;quickbus/rpc/RPCClient.cpp;quickbus/rpc/RPCServer.cpp;quickbus/rpc/RPCSessionID.cpp;quickbus/rpc/rpc_utils.cpp;quickbus/rpc/tests/qb_rpc_tests.cpp;quickbus/tests/quickbus_tests.cpp;sparkproto/SparkProtos.proto;testing/catch_test_runner.cpp;utils/AuthSessionManager.cpp;utils/AuthToken.cpp;utils/Dispatcher.cpp;utils/GrowableSPSCQueue.cpp;utils/HTTPStream.cpp;utils/PBUtils.cpp;utils/Puid.cpp;utils/SecureLogon.cpp;utils/SharedMemory.cpp;utils/Sqlite_utils.cpp;utils/Uuid.cpp;utils/crypto/CipherType.cpp;utils/crypto/CryptoInit.cpp;utils/crypto/Digest.cpp;utils/crypto/KeyCodeHelper.cpp;utils/crypto/PasswordCallback.cpp;utils/crypto/PrivateKey.cpp;utils/cryptoLine truncated
set(sources api/apicore.proto;api/apigateway.proto;api/apioptions.proto;api/core/ApiClientInterop.cpp;api/core/ApiServerInterop.cpp;api/public/ApiServer.cpp;api/public/ClientChannel.cpp;api/public/QuickbusClientChannel.cpp;api/public/ServerChannel.cpp;api/public/ServiceContext.cpp;api/service_helpers/AdminServiceUtils.cpp;api/service_helpers/AlgoServiceUtils.cpp;api/services/AdminService.proto;api/services/AlgoDefinitionService.proto;api/services/AlgoService.proto;api/services/ApiUnitTestService.proto;api/services/AuthService.proto;api/services/ErrorReportService.proto;api/services/HelloService.proto;api/services/MBOService.proto;api/services/MarginService.proto;api/services/MarketDataAuxiliaryService.proto;api/services/MarketDataRelay.proto;api/services/OrderService.proto;api/services/OutOfProcessURLListener.proto;api/services/PersistenceService.proto;api/services/PositionService.proto;api/services/ShellDiagnosticService.proto;api/services/ShellLatencyService.proto;api/services/SyntheticSecurityService.proto;api/test/ApiTests.cpp;api/test/HelloServiceServer.cpp;config/ConfigCheck.cpp;config/ConfigDownloader.cpp;config/ConfigErrorCollector.cpp;config/ConfigLog.cpp;config/ConfigPropertyEvaluator.cpp;config/ConfigValueQueue.cpp;config/ConfigurationException.cpp;config/ConfigurationState.cpp;config/PreprocessInputStream.cpp;config/config.cpp;config/defaults/MarketData.conf;config/defaults/Ports.conf;config/defaults/Symbols.conf;config/defaults/cme_reference_data.conf;config/defaults/edge.conf;config/defaults/jetfix.conf;config/defaults/keycode.conf;config/defaults/logging.conf;config/defaults/orderman_cfg.conf;config/defaults/orders_fills_cleanup.conf;config/defaults/span.conf;config/defaults/spreader.conf;config/defaults/testkeys.conf;config/defaults/threads.conf;config/defaults/toggles.conf;config/extensions/extensions.proto;config/invalid/invalid.proto;config/protos/ExchangeSimCfg.proto;config/protos/MarketData.proto;config/protos/Ports.proto;config/protos/Symbols.proto;config/protos/UI.proto;config/protos/cme_reference_data.proto;config/protos/jetfix.proto;config/protos/keycode.proto;config/protos/logging.proto;config/protos/mercury_cfg.proto;config/protos/orderman_cfg.proto;config/protos/orders_fills_cleanup.proto;config/protos/perflog_cfg.proto;config/protos/quickbus_cfg.proto;config/protos/span.proto;config/protos/spreader.proto;config/protos/system.proto;config/protos/testkeys.proto;config/protos/threads.proto;config/protos/toggles.proto;config/tests/HTTPServer.cpp;config/tests/config_ref_tests.cpp;config/tests/config_tests.cpp;config/text_format/text_format.cpp;domain_model/Security.cpp;domain_model/Security.proto;domain_model/SecurityTests.cpp;domain_model/tests/domain_tests.cpp;expression/BooleanGrammar.cpp;expression/ExpressionEvaluator.cpp;expression/ParserExceptions.cpp;expression/Value.cpp;expression/tests/expression_parser_tests.cpp;logging/LoggerHub.cpp;logging/Sink.cpp;logging/logging.cpp;logging/tests/logging_tests.cpp;md/Diag/MDPeriodicDumper.cpp;md/Diag/ShmDumper.cpp;md/MBOProcessor.cpp;md/MBOServiceServer.cpp;md/MDClient.cpp;md/MDConsumer.cpp;md/MDConsumerHandle.cpp;md/MDConsumerInterop.cpp;md/MDProducer.cpp;md/MDProducerHandle.cpp;md/MemorySegmentUtils.cpp;md/PlatformLoader.cpp;md/PriceSize.cpp;md/SecurityCache.cpp;md/SecurityDB.cpp;md/SecurityIDRecorder.cpp;md/SecurityOracle.cpp;md/SettlementRecorder.cpp;md/Shm/FixedSecurity.cpp;md/SyntheticSecurityService.cpp;md/cme/MDP3Utils.cpp;md/common.cpp;md/ice/ICEUtils.cpp;md/protos/co2.proto;md/relay/QueryServer.cpp;md/relay/RelayClient.cpp;md/relay/RelayRecorder.cpp;md/test/Co2ManagedTestHelper.cpp;md/test/Co2TestInstrument.cpp;md/test/mbo_tests.cpp;md/test/md2_tests.cpp;md/test/md_test_utils.cpp;md/test/synthetic_book_merge_tests.cpp;os/os.cpp;os/tests/os_tests.cpp;quickbus/core/LocalNode.cpp;quickbus/core/Quickbus.cpp;quickbus/core/SubscriptionID.cpp;quickbus/core/TableID.cpp;quickbus/message_model/Update.cpp;quickbus/message_model/merge_updates.cpp;quickbus/network/QBConnection.cpp;quickbus/network/QBConnectionManager.cpp;quickbus/network/endpoint_description.cpp;quickbus/network/quickbus_msgs.proto;quickbus/pubsub/TablePublisher.cpp;quickbus/pubsub/TableSubscriber.cpp;quickbus/pubsub/tests/qb_pubsub_tests.cpp;quickbus/routing/INode.cpp;quickbus/routing/NodeID.cpp;quickbus/routing/Router.cpp;quickbus/rpc/RPCClient.cpp;quickbus/rpc/RPCServer.cpp;quickbus/rpc/RPCSessionID.cpp;quickbus/rpc/rpc_utils.cpp;quickbus/rpc/tests/qb_rpc_tests.cpp;quickbus/tests/quickbus_tests.cpp;sparkproto/SparkProtos.proto;testing/catch_test_runner.cpp;utils/AuthSessionManager.cpp;utils/AuthToken.cpp;utils/Dispatcher.cpp;utils/GrowableSPSCQueue.cpp;utils/HTTPStream.cpp;utils/PBUtils.cpp;utils/Puid.cpp;utils/SecureLogon.cpp;utils/SharedMemory.cpp;utils/Sqlite_utils.cpp;utils/Uuid.cpp;utils/crypto/CipherType.cpp;utils/crypto/CryptoInit.cpp;utils/crypto/Digest.cpp;utils/crypto/KeyCodeHelper.cpp;utils/crypto/PasswordCallback.cpp;utils/crypto/PrivateKey.cpp;utils/cryptoLine truncated
+24 -252
View File
@@ -42,15 +42,12 @@ bool AdminServiceUtils::has_exchange(const ExchangeConnection& conn,
break;
case api::Venue::VENUE_UNSET:
case api::Venue::VENUE_SIM:
case api::Venue::VENUE_SIMICE:
rv = conn.has_sim_connection();
break;
case api::Venue::VENUE_ICE:
rv = conn.has_ice_connection();
break;
case api::Venue::VENUE_BTS:
case api::Venue::VENUE_CBOE:
case api::Venue::VENUE_CBOECFE:
case api::Venue::VENUE_ICE:
case api::Venue::Venue_INT_MIN_SENTINEL_DO_NOT_USE_:
case api::Venue::Venue_INT_MAX_SENTINEL_DO_NOT_USE_:
rv = false;
@@ -87,23 +84,6 @@ AdminServiceUtils::resolve_cme_connection(const bts::api::admin::AdminData& data
return nullptr;
}
const bts::api::admin::ExchangeConnection*
AdminServiceUtils::resolve_ice_connection(const bts::api::admin::AdminData& data,
const bts::api::admin::BTSAccount& account,
const bts::api::Security&)
{
if(account.has_connections())
{
for (const std::string& conn_name : account.connections().exchange_connection_names())
{
const bts::api::admin::ExchangeConnection* conn = find_connection(data, conn_name);
if (conn!=nullptr && conn->has_ice_connection())
return conn;
}
}
return nullptr;
}
const bts::api::admin::ExchangeConnection*
AdminServiceUtils::resolve_sim_connection(const bts::api::admin::AdminData& data,
const bts::api::admin::BTSAccount& account,
@@ -132,22 +112,14 @@ AdminServiceUtils::resolve_connection(const bts::api::admin::AdminData& data,
rv = resolve_sim_connection(data, account, sec);
break;
}
case api::Venue::VENUE_ICE:
{
rv = resolve_ice_connection(data, account, sec);
auto deployment_type = boost::to_lower_copy(config::get<config::DeploymentType>().type());
if (rv == nullptr && (deployment_type == "dev" || deployment_type == "demo"))
rv = resolve_sim_connection(data, account, sec);
break;
}
case api::Venue::VENUE_UNSET:
case api::Venue::VENUE_BTS:
case api::Venue::VENUE_SIM:
case api::Venue::VENUE_SIMICE:
rv = resolve_sim_connection(data, account, sec);
break;
case api::Venue::VENUE_CBOE:
case api::Venue::VENUE_CBOECFE:
case api::Venue::VENUE_ICE:
case api::Venue::Venue_INT_MIN_SENTINEL_DO_NOT_USE_:
case api::Venue::Venue_INT_MAX_SENTINEL_DO_NOT_USE_:
rv = nullptr;
@@ -184,15 +156,9 @@ void AdminServiceUtils::fill_connections_from_config(bts::api::admin::AdminData&
case config::JetFIX::Connection::CBOE:
break;
case config::JetFIX::Connection::SIM:
case config::JetFIX::Connection::SIMICE:
connection.mutable_sim_connection();
add_connection(admin_data,connection);
break;
case config::JetFIX::Connection::ICE:
connection.mutable_ice_connection()->set_sender_compid(c.sender_compid());
add_connection(admin_data,connection);
break;
}
}
for(int i=0;i<admin_data.accounts_size();i++)
@@ -274,18 +240,6 @@ const bts::api::admin::CMEAccountData* AdminServiceUtils::get_account_cme_data(c
return nullptr;
}
const bts::api::admin::ICEAccountData* AdminServiceUtils::get_account_ice_data(const bts::api::admin::BTSAccount& account,
const bts::api::admin::AdminData& data){
if (account.has_exchange_account_data() && account.exchange_account_data().has_ice_account_data())
return &(account.exchange_account_data().ice_account_data());
else if (has_id(account.parent_account_id())){
const bts::api::admin::BTSAccount* parent_account = find_account(data, account.parent_account_id());
if (parent_account != nullptr)
return get_account_ice_data (*parent_account, data);
}
return nullptr;
}
const bts::api::admin::SIMAccountData* AdminServiceUtils::get_account_sim_data(const bts::api::admin::BTSAccount& account,
const bts::api::admin::AdminData& data){
if (account.has_exchange_account_data() && account.exchange_account_data().has_sim_account_data())
@@ -321,16 +275,7 @@ std::string AdminServiceUtils::find_account_exchange_account (const bts::api::ad
rv = cme_account_data->clearing_account();
break;
}
case api::Venue::VENUE_ICE:
{
auto ice_account_data = get_account_ice_data(account, data);
if (ice_account_data != nullptr)
rv = ice_account_data->clearing_account();
break;
}
case api::Venue::VENUE_SIM:
case api::Venue::VENUE_SIMICE:
{
case api::Venue::VENUE_SIM: {
auto sim_account_data = get_account_sim_data(account, data);
if (sim_account_data != nullptr)
rv = sim_account_data->clearing_account();
@@ -339,7 +284,8 @@ std::string AdminServiceUtils::find_account_exchange_account (const bts::api::ad
case api::Venue::VENUE_UNSET:
case api::Venue::VENUE_BTS:
case api::Venue::VENUE_CBOE:
case api::Venue::VENUE_CBOECFE:
case api::Venue::VENUE_CBOECFE:
case api::Venue::VENUE_ICE:
case api::Venue::Venue_INT_MIN_SENTINEL_DO_NOT_USE_:
case api::Venue::Venue_INT_MAX_SENTINEL_DO_NOT_USE_:
out_result.set_is_success(false); out_result.set_error_text("Exchange not supported");
@@ -439,46 +385,6 @@ bts::api::orderman::RoutingRecord AdminServiceUtils::get_routing_record(const bt
return rv;
}
switch (sec.exchange()) {
case api::Venue::VENUE_ICE:
{
const bts::api::admin::ICEUserData* ice_user_data = get_user_ice_data(*user_ptr, data);
if(ice_user_data==nullptr)
{
out_result.set_is_success(false);
out_result.set_error_text("Could not find ICE data for user");
return rv;
}
const bts::api::admin::ICEAccountData* ice_account_data = get_account_ice_data(*account_ptr, data);
if(ice_account_data==nullptr)
{
out_result.set_is_success(false);
out_result.set_error_text("Could not find ICE data for account");
return rv;
}
// check for data corectness
if (ice_user_data->operator_id().length() == 0)
{
out_result.set_is_success(false);
out_result.set_error_text("Operator ID is not set");
return rv;
}
rv.set_session(conn_ptr->name());
rv.set_sender_compid(conn_ptr->ice_connection().sender_compid());
rv.set_account(ice_account_data->clearing_account());
rv.set_operator_id(ice_user_data->operator_id());
rv.set_cti_code(ice_account_data->cti());
rv.set_customer_or_firm(ice_account_data->origin());
rv.set_clearing_firm(ice_account_data->clearing_firm());
rv.set_customer_account_ref_id(ice_account_data->customer_account_ref_id());
rv.set_account_code(ice_account_data->account_code());
rv.set_company_id(std::to_string(ice_user_data->company_id()));
rv.set_authorized_trader(ice_user_data->authorized_trader());
rv.set_authorized_group(ice_user_data->authorized_group());
rv.set_cust_order_handing_inst(ice_user_data->cust_order_handing_inst());
return rv;
}
case bts::api::Venue::VENUE_GLBX: {
const bts::api::admin::CMEUserData* cme_user_data = get_user_cme_data(*user_ptr, data);
if(cme_user_data==nullptr){
@@ -529,9 +435,7 @@ bts::api::orderman::RoutingRecord AdminServiceUtils::get_routing_record(const bt
rv.set_customer_or_firm(cme_account_data->origin());
return rv;
}
case api::Venue::VENUE_SIM:
case api::Venue::VENUE_SIMICE:
{
case api::Venue::VENUE_SIM: {
const bts::api::admin::SIMUserData* sim_user_data = get_user_sim_data(*user_ptr, data);
if(sim_user_data==nullptr){
out_result.set_is_success(false);
@@ -577,7 +481,8 @@ bts::api::orderman::RoutingRecord AdminServiceUtils::get_routing_record(const bt
case api::Venue::VENUE_UNSET:
case api::Venue::VENUE_BTS:
case api::Venue::VENUE_CBOE:
case api::Venue::VENUE_CBOECFE:
case api::Venue::VENUE_CBOECFE:
case api::Venue::VENUE_ICE:
case api::Venue::Venue_INT_MIN_SENTINEL_DO_NOT_USE_:
case api::Venue::Venue_INT_MAX_SENTINEL_DO_NOT_USE_:
out_result.set_is_success(false);
@@ -724,18 +629,6 @@ const bts::api::admin::CMEUserData* AdminServiceUtils::get_group_cme_data(const
return nullptr;
}
const bts::api::admin::ICEUserData* AdminServiceUtils::get_group_ice_data(const bts::api::admin::BTSUserGroup& group,
const bts::api::admin::AdminData& data){
if (group.has_user_data() && group.user_data().has_exchange_user_data() && group.user_data().exchange_user_data().has_ice_data())
return &(group.user_data().exchange_user_data().ice_data());
else if (has_id(group.parent_group_id())){
const bts::api::admin::BTSUserGroup* parent_group = find_group(data, group.parent_group_id());
if (parent_group != nullptr)
return get_group_ice_data(*parent_group, data);
}
return nullptr;
}
const bts::api::admin::SIMUserData* AdminServiceUtils::get_group_sim_data(const bts::api::admin::BTSUserGroup& group,
const bts::api::admin::AdminData& data){
if (group.has_user_data() && group.user_data().has_exchange_user_data() && group.user_data().exchange_user_data().has_sim_data())
@@ -866,18 +759,6 @@ const bts::api::admin::CMEUserData* AdminServiceUtils::get_user_cme_data(const b
return nullptr;
}
const bts::api::admin::ICEUserData* AdminServiceUtils::get_user_ice_data(const bts::api::admin::BTSUser& user,
const bts::api::admin::AdminData& data){
if (user.has_user_data() && user.user_data().has_exchange_user_data() && user.user_data().exchange_user_data().has_ice_data())
return &(user.user_data().exchange_user_data().ice_data());
else{
const bts::api::admin::BTSUserGroup* parent_group = find_group(data, user.parent_group_id());
if (parent_group != nullptr)
return get_group_ice_data(*parent_group, data);
}
return nullptr;
}
const bts::api::admin::SIMUserData* AdminServiceUtils::get_user_sim_data(const bts::api::admin::BTSUser& user,
const bts::api::admin::AdminData& data){
if (user.has_user_data() && user.user_data().has_exchange_user_data() && user.user_data().exchange_user_data().has_sim_data())
@@ -905,16 +786,7 @@ std::string AdminServiceUtils::find_user_exchange_id (const bts::api::admin::Adm
rv = cme_user_data->operator_id();
break;
}
case api::Venue::VENUE_ICE:
{
auto ice_user_data = get_user_ice_data(user, data);
if (ice_user_data != nullptr)
rv = ice_user_data->operator_id();
break;
}
case api::Venue::VENUE_SIM:
case api::Venue::VENUE_SIMICE:
{
case api::Venue::VENUE_SIM: {
auto sim_user_data = get_user_sim_data(user, data);
if (sim_user_data != nullptr)
rv = sim_user_data->operator_id();
@@ -924,38 +796,8 @@ std::string AdminServiceUtils::find_user_exchange_id (const bts::api::admin::Adm
case api::Venue::VENUE_UNSET:
case api::Venue::VENUE_BTS:
case api::Venue::VENUE_CBOE:
case api::Venue::VENUE_CBOECFE:
case api::Venue::Venue_INT_MIN_SENTINEL_DO_NOT_USE_:
case api::Venue::Venue_INT_MAX_SENTINEL_DO_NOT_USE_:
out_result.set_is_success(false); out_result.set_error_text("Exchange not supported");
break;
}
return rv;
}
std::string AdminServiceUtils::find_user_company_id (const bts::api::admin::AdminData& data,
const bts::api::admin::BTSUser& user,
api::Venue exchange,
bts::api::admin::AdminServiceOperationResult& out_result)
{
out_result.set_is_success(true);
std::string rv = "";
switch(exchange)
{
case api::Venue::VENUE_CBOECFE:
case api::Venue::VENUE_ICE:
{
auto ice_user_data = get_user_ice_data(user, data);
if (ice_user_data != nullptr)
rv = std::to_string(ice_user_data->company_id());
break;
}
case api::Venue::VENUE_SIM:
case api::Venue::VENUE_SIMICE:
case api::Venue::VENUE_GLBX:
case api::Venue::VENUE_UNSET:
case api::Venue::VENUE_BTS:
case api::Venue::VENUE_CBOE:
case api::Venue::VENUE_CBOECFE:
case api::Venue::Venue_INT_MIN_SENTINEL_DO_NOT_USE_:
case api::Venue::Venue_INT_MAX_SENTINEL_DO_NOT_USE_:
out_result.set_is_success(false); out_result.set_error_text("Exchange not supported");
@@ -963,7 +805,6 @@ std::string AdminServiceUtils::find_user_company_id (const bts::api::admin::Admi
}
return rv;
}
std::pair<const bts::api::admin::BTSAccount*, const bts::api::admin::BTSUser*>
AdminServiceUtils::find_user_account_matches (const bts::api::admin::AdminData& admin_data,
const std::string& connection, const std::string& exchange_account,
@@ -974,22 +815,14 @@ AdminServiceUtils::find_user_account_matches (const bts::api::admin::AdminData&
auto user_ptrs = users(admin_data, false);
for(const bts::api::admin::BTSAccount* account_ptr : account_ptrs){
if (account_has_connection(*account_ptr, connection)){
if (boost::algorithm::iequals(exchange_account, find_account_exchange_account(admin_data,*account_ptr,exchange,find_account_result)) &&
find_account_result.is_success())
{
for(const bts::api::admin::BTSUser* user_ptr : user_ptrs)
{
if (boost::algorithm::iequals(exchange_user,find_user_exchange_id(admin_data,*user_ptr,exchange,find_user_result)) &&
if (boost::algorithm::iequals(exchange_account,
find_account_exchange_account(admin_data,*account_ptr,exchange,find_account_result)) &&
find_account_result.is_success()){
for(const bts::api::admin::BTSUser* user_ptr : user_ptrs){
if (boost::algorithm::iequals(exchange_user,
find_user_exchange_id(admin_data,*user_ptr,exchange,find_user_result)) &&
find_user_result.is_success())
return std::pair<const bts::api::admin::BTSAccount*, const bts::api::admin::BTSUser*>(account_ptr,user_ptr);
//This code eventually gets called by get_reverse_routing_record(...)
//At the ice, they send back the login level tag50 in exec reports which doesn't match any user level tag50s in the exchange_user
//so instead we look for the CompanyID (or client_id, tag 109) field here. If this field matches we have a good bet that
//the user we find is enough to fulfill the routing record enough to cancel or modify orphaned orders, etc
if (boost::algorithm::iequals(exchange_user,find_user_company_id(admin_data,*user_ptr,exchange,find_user_result)) &&
find_user_result.is_success())
return std::pair<const bts::api::admin::BTSAccount*, const bts::api::admin::BTSUser*>(account_ptr,user_ptr);
}
}
}
@@ -1212,6 +1045,13 @@ void AdminServiceUtils::set_user_exchange_data(bts::api::admin::BTSUser* user,
if (!user->user_data().has_exchange_user_data())
user->mutable_user_data()->mutable_exchange_user_data()->CopyFrom(exchange_user_data);
}
void AdminServiceUtils::set_user_md_entitlement_data(bts::api::admin::BTSUser* user,
const bts::api::admin::ExchangeUserMarketDataEntitlementData& exchange_user_md_entitelemnt_data){
if (!user->has_user_data())
user->mutable_user_data();
if (!user->user_data().has_exchange_md_entitlement_data())
user->mutable_user_data()->mutable_exchange_md_entitlement_data()->CopyFrom(exchange_user_md_entitelemnt_data);
}
void AdminServiceUtils::clear_user_accounts (bts::api::admin::BTSUser* user){
if(user->has_user_data() && user->user_data().has_account_permissions())
user->mutable_user_data()->clear_account_permissions();
@@ -1456,7 +1296,6 @@ void AdminServiceUtils::bootstrap_data (bts::api::admin::AdminData& data){
auto account_1 = create_account(data, parent_account->id(), std::string("ACC A1"), std::string("description"), true, account_result); account_1->set_is_active(true);
auto account_2 = create_account(data, parent_account->id(), std::string("ACC A2"), std::string("description"), true, account_result); account_2->set_is_active(true);
auto account_3 = create_account(data, parent_account->id(), std::string("ACC A3"), std::string("description"), true, account_result); account_3->set_is_active(true);
auto account_4 = create_account(data, parent_account->id(), std::string("BLUETST"), std::string("description"), true, account_result); account_4->set_is_active(true);
create_account(data, parent_account->id(), std::string("ACC A4"), std::string("description"), true, account_result);
// add group
auto def_group = create_group(data, 0, std::string("default"), result);
@@ -1468,6 +1307,7 @@ void AdminServiceUtils::bootstrap_data (bts::api::admin::AdminData& data){
auto user_3 = create_user(data, def_group->id(), std::string("bts_3"), std::string("bts_3"), empty, empty, false, license_data, license_entitlements, user_result); user_3->set_is_active(true);
//associate users
bts::api::admin::UserAccountPermissionUnit permission_unit;
permission_unit.mutable_trading_permission()->set_submit_market_orders(true);
permission_unit.mutable_trading_permission()->set_has_permissions(true);
permission_unit.mutable_admin_permission()->set_has_permissions(true);
bts::api::admin::UserAccountPermissions account_permissions;
@@ -1475,7 +1315,6 @@ void AdminServiceUtils::bootstrap_data (bts::api::admin::AdminData& data){
account_permissions.mutable_account_permissions()->insert(google::protobuf::MapPair<uint32_t, bts::api::admin::UserAccountPermissionUnit>(account_1->id(), permission_unit));
account_permissions.mutable_account_permissions()->insert(google::protobuf::MapPair<uint32_t, bts::api::admin::UserAccountPermissionUnit>(account_2->id(), permission_unit));
account_permissions.mutable_account_permissions()->insert(google::protobuf::MapPair<uint32_t, bts::api::admin::UserAccountPermissionUnit>(account_3->id(), permission_unit));
account_permissions.mutable_account_permissions()->insert(google::protobuf::MapPair<uint32_t, bts::api::admin::UserAccountPermissionUnit>(account_4->id(), permission_unit));
set_user_accounts(user_1, account_permissions);
set_user_accounts(user_2, account_permissions);
set_user_accounts(user_3, account_permissions);
@@ -1485,12 +1324,6 @@ void AdminServiceUtils::bootstrap_data (bts::api::admin::AdminData& data){
exchange_account_data.mutable_cme_account_data()->set_cti(bts::api::orderman::CTICode::CTI_CODE_CTI_CODE1);
exchange_account_data.mutable_cme_account_data()->set_origin(bts::api::orderman::CustomerOrFirm::CUSTOMER_OR_FIRM_FIRM);
exchange_account_data.mutable_cme_account_data()->set_clearing_account(parent_account->name());
exchange_account_data.mutable_ice_account_data()->set_cti(bts::api::orderman::CTICode::CTI_CODE_UNDEFINED);
exchange_account_data.mutable_ice_account_data()->set_origin(bts::api::orderman::CustomerOrFirm::CUSTOMER_OR_FIRM_FIRM);
exchange_account_data.mutable_ice_account_data()->set_clearing_account(parent_account->name());
exchange_account_data.mutable_ice_account_data()->set_clearing_firm("649");
exchange_account_data.mutable_sim_account_data()->set_cti(bts::api::orderman::CTICode::CTI_CODE_CTI_CODE1);
exchange_account_data.mutable_sim_account_data()->set_origin(bts::api::orderman::CustomerOrFirm::CUSTOMER_OR_FIRM_FIRM);
exchange_account_data.mutable_sim_account_data()->set_clearing_account(parent_account->name());
@@ -1498,87 +1331,33 @@ void AdminServiceUtils::bootstrap_data (bts::api::admin::AdminData& data){
exchange_account_data.mutable_cme_account_data()->set_clearing_account(account_1->name());
exchange_account_data.mutable_ice_account_data()->set_clearing_account(account_1->name());
exchange_account_data.mutable_sim_account_data()->set_clearing_account(account_1->name());
set_account_exchange_data(account_1, exchange_account_data);
exchange_account_data.mutable_cme_account_data()->set_clearing_account(account_2->name());
exchange_account_data.mutable_ice_account_data()->set_clearing_account(account_2->name());
exchange_account_data.mutable_sim_account_data()->set_clearing_account(account_2->name());
set_account_exchange_data(account_2, exchange_account_data);
exchange_account_data.mutable_cme_account_data()->set_clearing_account(account_3->name());
exchange_account_data.mutable_ice_account_data()->set_clearing_account(account_3->name());
exchange_account_data.mutable_sim_account_data()->set_clearing_account(account_3->name());
set_account_exchange_data(account_3, exchange_account_data);
exchange_account_data.mutable_ice_account_data()->set_clearing_account(account_4->name());
set_account_exchange_data(account_4, exchange_account_data);
// add cme and sim user data
bts::api::admin::ExchangeUserData exchange_user_data;
exchange_user_data.mutable_cme_data()->set_operator_id("op_id_" + user_1->name());
exchange_user_data.mutable_cme_data()->set_location("us,nc");
exchange_user_data.mutable_ice_data()->set_operator_id("op_id_" + user_1->name());
exchange_user_data.mutable_ice_data()->set_company_id(51251);
exchange_user_data.mutable_ice_data()->set_authorized_trader("bluetrd-fx");
exchange_user_data.mutable_ice_data()->set_authorized_group("Group");
exchange_user_data.mutable_ice_data()->set_password("Starts123");
exchange_user_data.mutable_ice_data()->set_mifid_direct_electronic_access(-1);
exchange_user_data.mutable_ice_data()->set_mifid_trading_capacity(-1);
exchange_user_data.mutable_ice_data()->set_mifid_liquidity_provision(-1);
exchange_user_data.mutable_ice_data()->set_mifid_commodity_deriv_indicator(-1);
exchange_user_data.mutable_ice_data()->set_mifid_investment_decision(-1);
exchange_user_data.mutable_ice_data()->set_mifid_execution_decision(-1);
exchange_user_data.mutable_ice_data()->set_mifid_client_id_code(-1);
exchange_user_data.mutable_ice_data()->set_mifid_id(1);
exchange_user_data.mutable_sim_data()->set_operator_id("op_id_" + user_1->name());
exchange_user_data.mutable_sim_data()->set_location("us,nc");
set_user_exchange_data(user_1, exchange_user_data);
exchange_user_data.mutable_cme_data()->set_operator_id("op_id_" + user_2->name());
exchange_user_data.mutable_cme_data()->set_location("us,nc");
exchange_user_data.mutable_ice_data()->set_operator_id("op_id_" + user_2->name());
exchange_user_data.mutable_ice_data()->set_company_id(51251);
exchange_user_data.mutable_ice_data()->set_authorized_trader("bluetrd-fx");
exchange_user_data.mutable_ice_data()->set_authorized_group("Group");
exchange_user_data.mutable_ice_data()->set_password("Starts123");
exchange_user_data.mutable_ice_data()->set_mifid_direct_electronic_access(-1);
exchange_user_data.mutable_ice_data()->set_mifid_trading_capacity(-1);
exchange_user_data.mutable_ice_data()->set_mifid_liquidity_provision(-1);
exchange_user_data.mutable_ice_data()->set_mifid_commodity_deriv_indicator(-1);
exchange_user_data.mutable_ice_data()->set_mifid_investment_decision(-1);
exchange_user_data.mutable_ice_data()->set_mifid_execution_decision(-1);
exchange_user_data.mutable_ice_data()->set_mifid_client_id_code(-1);
exchange_user_data.mutable_ice_data()->set_mifid_id(1);
exchange_user_data.mutable_sim_data()->set_operator_id("op_id_" + user_2->name());
exchange_user_data.mutable_sim_data()->set_location("us,nc");
set_user_exchange_data(user_2, exchange_user_data);
exchange_user_data.mutable_cme_data()->set_operator_id("op_id_" + user_3->name());
exchange_user_data.mutable_cme_data()->set_location("us,nc");
exchange_user_data.mutable_ice_data()->set_operator_id("op_id_" + user_3->name());
exchange_user_data.mutable_ice_data()->set_company_id(51251);
exchange_user_data.mutable_ice_data()->set_authorized_trader("bluetrd-fx");
exchange_user_data.mutable_ice_data()->set_authorized_group("Group");
exchange_user_data.mutable_ice_data()->set_password("Starts123");
exchange_user_data.mutable_ice_data()->set_mifid_direct_electronic_access(-1);
exchange_user_data.mutable_ice_data()->set_mifid_trading_capacity(-1);
exchange_user_data.mutable_ice_data()->set_mifid_liquidity_provision(-1);
exchange_user_data.mutable_ice_data()->set_mifid_commodity_deriv_indicator(-1);
exchange_user_data.mutable_ice_data()->set_mifid_investment_decision(-1);
exchange_user_data.mutable_ice_data()->set_mifid_execution_decision(-1);
exchange_user_data.mutable_ice_data()->set_mifid_client_id_code(-1);
exchange_user_data.mutable_ice_data()->set_mifid_id(1);
exchange_user_data.mutable_sim_data()->set_operator_id("op_id_" + user_3->name());
exchange_user_data.mutable_sim_data()->set_location("us,nc");
set_user_exchange_data(user_3, exchange_user_data);
@@ -1620,13 +1399,6 @@ void AdminServiceUtils::bootstrap_data (bts::api::admin::AdminData& data){
add_security_clip_sizes_to_account(account_1, api::Venue::VENUE_GLBX, api::SecurityType::SECURITYTYPE_SPREAD,100);
add_security_clip_sizes_to_account(account_1, api::Venue::VENUE_SIM, api::SecurityType::SECURITYTYPE_FUTURE,100);
add_security_clip_sizes_to_account(account_1, api::Venue::VENUE_SIM, api::SecurityType::SECURITYTYPE_SPREAD,100);
//ICE limits
add_product_position_limits(account_4, api::Venue::VENUE_ICE, api::SecurityType::SECURITYTYPE_FUTURE,50000);
add_product_position_limits(account_4, api::Venue::VENUE_ICE, api::SecurityType::SECURITYTYPE_SPREAD,50000);
add_security_clip_sizes_to_account(account_4, api::Venue::VENUE_ICE, api::SecurityType::SECURITYTYPE_FUTURE,50);
add_security_clip_sizes_to_account(account_4, api::Venue::VENUE_ICE, api::SecurityType::SECURITYTYPE_SPREAD,50);
}
bool AdminServiceUtils::has_id (uint32_t id){return id>0;}
bool AdminServiceUtils::is_symbol_set (const std::string& symbol){
@@ -35,10 +35,6 @@ public:
const AdminData& data,
const BTSAccount& account,
const api::Security& sec);
static const ExchangeConnection* resolve_ice_connection(
const AdminData& data,
const BTSAccount& account,
const api::Security& sec);
static const ExchangeConnection* resolve_sim_connection(
const AdminData& data,
const BTSAccount& account,
@@ -89,8 +85,6 @@ public:
// if needed)
static const CMEAccountData* get_account_cme_data(const BTSAccount& account,
const AdminData& data);
static const ICEAccountData* get_account_ice_data(const BTSAccount& account,
const AdminData& data);
static const SIMAccountData* get_account_sim_data(const BTSAccount& account,
const AdminData& data);
// returns true if an account has a connection
@@ -162,8 +156,6 @@ public:
// travels up the group tree until it finds a populated cme data
static const CMEUserData* get_group_cme_data(const BTSUserGroup& group,
const AdminData& data);
static const ICEUserData* get_group_ice_data(const BTSUserGroup& group,
const AdminData& data);
static const SIMUserData* get_group_sim_data(const BTSUserGroup& group,
const AdminData& data);
static const UserAccountPermissions* const get_group_user_permissions (
@@ -198,8 +190,6 @@ public:
static uint32_t find_max_user_id (const AdminData& data);
static const CMEUserData* get_user_cme_data(const BTSUser& user,
const AdminData& data);
static const ICEUserData* get_user_ice_data(const BTSUser& user,
const AdminData& data);
static const SIMUserData* get_user_sim_data(const BTSUser& user,
const AdminData& data);
// finds the "exchange user" (ex: "operator_id" at CME or "authorized_trader"
@@ -209,12 +199,6 @@ public:
const BTSUser& user,
api::Venue exchange,
AdminServiceOperationResult& out_result);
static std::string find_user_company_id (
const AdminData& data,
const BTSUser& user,
api::Venue exchange,
AdminServiceOperationResult& out_result);
static std::pair<const BTSAccount*, const BTSUser*>
find_user_account_matches (const AdminData& admin_data,
const std::string& connection,
@@ -280,6 +264,8 @@ public:
static void set_user_exchange_data(
BTSUser* user,
const ExchangeUserData& exchange_user_data);
static void set_user_md_entitlement_data(BTSUser* user,
const ExchangeUserMarketDataEntitlementData&);
static void clear_user_accounts (BTSUser* user);
static void set_user_accounts (BTSUser* user,
const UserAccountPermissions& user_account_permissions);
+92 -100
View File
@@ -55,12 +55,11 @@ message BTSUser{
string name = 30;
string password = 40;
string full_name = 42;
string company = 44;
string company = 44;
bool is_active = 50;
bool can_create = 55;
LicenseData license_data = 60;
LicenseEntitlements license_entitlements = 70;
LicenseData license_data = 60; //unused
LicenseEntitlements license_entitlements = 70; //unused
BTSUserDerivableData user_data = 80;
}
@@ -77,7 +76,7 @@ message BTSUserDerivableData{
// b. else its overridden at the user level
UserAccountPermissions account_permissions = 70;
ExchangeUserData exchange_user_data = 80;
reserved 90; reserved "exchange_md_entitlement_data"; //ExchangeUserMarketDataEntitlementData exchange_md_entitlement_data = 90;
ExchangeUserMarketDataEntitlementData exchange_md_entitlement_data = 90;
}
message LicenseData{
@@ -92,22 +91,21 @@ message LicenseEntitlements{
bool spreader = 30;
}
// message AlgoTradingPermissionsUnit{
// bool submit_iceberg_orders = 10; //unused
// bool submit_time_box_orders = 20; //unused
// bool submit_spreader_orders = 30; //unused
// }
message AlgoTradingPermissionsUnit{
bool submit_iceberg_orders = 10; //unused
bool submit_time_box_orders = 20; //unused
bool submit_spreader_orders = 30; //unused
}
message TradingPermissionUnit{
reserved 10; reserved "submit_market_orders"; //bool submit_market_orders = 10; //unused
reserved 20; reserved "submit_gtc_orders"; //bool submit_gtc_orders = 20; //unused
reserved 30; reserved "algo_trading_permission"; //AlgoTradingPermissionsUnit algo_trading_permission = 30; //unused
bool has_permissions = 5;
bool submit_market_orders = 10; //unused
bool submit_gtc_orders = 20; //unused
AlgoTradingPermissionsUnit algo_trading_permission = 30; //unused
}
message AdminPermissionUnit{
// TODO: needs to be more ellaborate (account writing,
// TODO: needs to be more ellaborate (account writing,
// reading etc, routing etc)
bool has_permissions = 10;
bool has_md_permissions = 20;
@@ -121,15 +119,15 @@ message UserAccountPermissionUnit{
message UserAccountPermissions{
//uint32 = account_id
map<uint32, UserAccountPermissionUnit> account_permissions = 10;
map<uint32, UserAccountPermissionUnit> account_permissions = 10;
}
// // unused now
// message UserSecurityTradingLimit{
// SecurityScope security = 10;
// uint32 clip_size = 20;
// bool can_trade = 30;
// }
// unused now
message UserSecurityTradingLimit{
SecurityScope security = 10;
uint32 clip_size = 20;
bool can_trade = 30;
}
/************************************************************************/
/********************************BTS Account*****************************/
@@ -154,7 +152,7 @@ message BTSAccount{
AccountLossLimit account_loss_limit = 130;
}
message RiskLimitEnforcement{
message RiskLimitEnforcement{
bool product_limit_in_net_terms = 10;
}
@@ -205,22 +203,23 @@ message AccountLossLimit{
message CMEMicData{
api.CMEMics mic=10;
bool enabled=20;
// there are other things here
// there are other things here
}
message ICEMicData{
api.ICEMics mic=10;
api.CMEMics mic=10;
bool enabled=20;
}
message ExchangeUserMarketDataEntitlementData{
CMEUserMarketDataEntitlementData cme_data = 10;
ICEUserMarketDataEntitlementData ice_data = 20;
}
message ExchangeUserData{
CMEUserData cme_data = 10;
ICEUserData ice_data = 20;
SIMUserData sim_data = 30;
enum AdminDisplay { All = 0; MD = 1; Routing = 2; None = 100; }
AdminDisplay admin_display_flag = 120;
}
message ExchangeAccountData{
@@ -229,6 +228,9 @@ message ExchangeAccountData{
SIMAccountData sim_account_data = 30;
}
message MarketDataEntitlement{
bool can_view = 10;
}
message ExchangeConnection{
uint32 id = 10;
@@ -271,19 +273,19 @@ message CMEMSGWConnection{
uint32 market_segment_id = 60;
}
message CMEAccountData {
reserved 30; reserved "takeup_member_code"; //string takeup_member_code = 30;
reserved 50; reserved "direct_electronic_access"; //string direct_electronic_access = 50;
reserved 60; reserved "trading_capacity"; //string trading_capacity = 60;
reserved 70; reserved "liquidity_provision"; //string liquidity_provision = 70;
reserved 80; reserved "commodity_derivative_indicator"; //string commodity_derivative_indicator = 80;
reserved 90; reserved "investment_decision_id"; //string investment_decision_id = 90;
reserved 100; reserved "execution_decision_id"; //string execution_decision_id = 100;
reserved 110; reserved "client_id"; //string client_id = 110;
message CMEAccountData{
// should perhaps be an enum
api.orderman.CTICode cti = 10;
api.orderman.CustomerOrFirm origin = 20;
string takeup_member_code = 30;
string clearing_account = 40;
string direct_electronic_access = 50;
string trading_capacity = 60;
string liquidity_provision = 70;
string commodity_derivative_indicator = 80;
string investment_decision_id = 90;
string execution_decision_id = 100;
string client_id = 110;
map<string, string> misc_tags = 120;
}
@@ -306,22 +308,21 @@ enum DisplayDesignation
}
message CMEUserData{
reserved 20; reserved "ats_operator_id"; //string ats_operator_id = 20;
reserved 40; reserved "text_a"; //string text_a = 40;
reserved 50; reserved "text_b"; //string text_b = 50;
reserved 80; reserved "max_order_rate_per_connection"; //string max_order_rate_per_connection = 80;
//enum AdminDisplay { All = 0; MD = 1; Routing = 2; None = 100; }
reserved 120; reserved "admin_display_flag"; //AdminDisplay admin_display_flag = 120;
repeated CMEMicData md_permissions = 1000;
string operator_id = 10;
string ats_operator_id = 20;
string smp_id = 30;
string text_a = 40;
string text_b = 50;
map<string, string> misc_tags = 60;
string smp_instruction = 70;
string max_order_rate_per_connection = 80;
string location = 90;
ProfessionalDesignation pro_nonpro = 100;
DisplayDesignation display_nondisplay = 110;
enum AdminDisplay { All = 0; MD = 1; Routing = 2; None = 100; }
AdminDisplay admin_display_flag = 120;
repeated CMEMicData md_permissions = 1000;
}
message SIMUserData {
@@ -329,67 +330,58 @@ message SIMUserData {
string location = 90;
}
message CMEUserMarketDataEntitlementData{
MarketDataEntitlement cbot_entitlement = 10;
MarketDataEntitlement cme_entitlement = 20;
MarketDataEntitlement nymex_entitlement = 30;
MarketDataEntitlement bmandf_entitlement = 40;
MarketDataEntitlement comex_entitlement = 50;
MarketDataEntitlement cme_europe_entitlement = 60;
}
/********************************ICE Data*********************************/
message ICEConnection {
string sender_compid = 10;
message ICEConnection{
string authorized_member_id = 10;
string sender_company_id = 20;
string sender_sub_id = 30;
string session_id = 40;
string session_password = 50;
string host_ip = 60;
string port = 70;
string default_routing_trader = 80;
string routing_trader_password = 90;
int32 max_order_rate = 100;
}
message ICEAccountData {
reserved 10; reserved "nybit_house"; //string nybit_house = 10;
reserved 20; reserved "wce_house"; //int32 wce_house = 20;
reserved 30; reserved "clearing_account_override"; //string clearing_account_override = 30;
reserved 40; reserved "direct_electronic_access"; //bool direct_electronic_access = 40;
reserved 50; reserved "trading_capacity"; //string trading_capacity = 50;
reserved 60; reserved "liquidity_provision"; //bool liquidity_provision = 60;
reserved 70; reserved "commodity_derivative_indicator"; //bool commodity_derivative_indicator = 70;
reserved 80; reserved "investment_decision_id"; //string investment_decision_id = 80;
reserved 90; reserved "execution_decision_id"; //string execution_decision_id = 90;
reserved 100; reserved "client_id"; //string client_id = 100;
reserved 110; reserved "mfid_id"; //string mfid_id = 110;
api.orderman.CTICode cti = 3;
api.orderman.CustomerOrFirm origin = 5;
string clearing_firm = 200;
string clearing_account = 210;
string customer_account_ref_id = 220;
string account_code = 230;
map<string, string> misc_tags = 500;
message ICEAccountData{
string nybit_house = 10;
int32 wce_house = 20;
string clearing_account_override = 30;
bool direct_electronic_access = 40;
string trading_capacity = 50;
bool liquidity_provision = 60;
bool commodity_derivative_indicator = 70;
string investment_decision_id = 80;
string execution_decision_id = 90;
string client_id = 100;
string mfid_id = 110;
}
message ICEUserData {
reserved 20; reserved "memo_field"; //string memo_field = 20;
reserved 30; reserved "text_b"; //string text_b = 30;
reserved 40; reserved "max_order_rate"; //uint32 max_order_rate = 40;
message ICEUserData{
string authorized_trader = 10;
string memo_field = 20;
string text_b = 30;
uint32 max_order_rate = 40;
}
int32 company_id = 3; //tag 109 clientid
string operator_id = 5; //tag 50
string authorized_trader = 10; //tag 553 user_name
string authorized_group = 15; //tag 553 user_name
string password = 21; //tag 96 raw data
string cust_order_handing_inst = 25;
//mifid
int32 mifid_direct_electronic_access = 500;
int32 mifid_trading_capacity = 510;
int32 mifid_liquidity_provision = 520;
int32 mifid_commodity_deriv_indicator = 530;
int64 mifid_investment_decision = 540;
int64 mifid_execution_decision = 550;
int64 mifid_client_id_code = 560;
int64 mifid_id = 570;
map<string, string> misc_tags = 60;
ProfessionalDesignation pro_nonpro = 100;
DisplayDesignation display_nondisplay = 110;
repeated ICEMicData md_permissions = 1000;
message ICEUserMarketDataEntitlementData{
}
///////////////////////////////////////////////////////////
// Order Auxiliary Service ////////////////////////////////
message OrdersSummaryUnit{
message OrdersSummaryUnit{
string account = 10;
string user = 20;
uint32 total_orders = 30;
@@ -400,11 +392,11 @@ message OrdersSummary{
}
message OrderSummaryRequest{
}
// top level orders that have account
// top level orders that have account
// and user that are present here, will
// be cancelled. wild cards are not
// supported.
message OrderCancelRequest{
message OrderCancelRequest{
repeated string accounts = 10;
repeated string users = 20;
}
@@ -440,7 +432,7 @@ message AccountCreateAPIArgument{
string creator_user = 40;
}
message AccountUpdateAPIArgument{
BTSAccount complete_data=10;
BTSAccount complete_data=10;
}
message UserCreateAPIArgument{
uint32 parent_group_id = 20;
@@ -484,7 +476,7 @@ service AdminService {
// users
rpc create_user(UserCreateAPIArgument) returns (AdminServiceCreateEntityResult);
rpc update_user(UserUpdateAPIArgument) returns (AdminServiceOperationResult);
rpc delete_user(IDAPIArgument) returns (AdminServiceOperationResult);
rpc delete_user(IDAPIArgument) returns (AdminServiceOperationResult);
// subscription
rpc admin_data(bts.api.VoidMessage) returns (stream AdminData);
rpc get_admin_data(bts.api.VoidMessage) returns (AdminData);
-17
View File
@@ -309,13 +309,6 @@ message Fill {
FILL_KIND_SOD = 2;
}
FillKind fill_kind = 10;
enum FillStatus {
FILL_STATUS_ACTIVE = 0;
FILL_STATUS_CORRECTED = 1;
FILL_STATUS_BUSTED = 2;
}
FillStatus fill_status = 20;
}
enum OrderSubType {
@@ -333,16 +326,6 @@ message RoutingRecord {
string smp_id = 6 ;
SelfMatchPreventionInstruction smp_instruction = 7;
string location = 8;
string sender_compid = 15;
string clearing_firm = 20;
string customer_account_ref_id = 25;
string account_code = 30;
string company_id = 45;
string authorized_trader = 50;
string authorized_group = 60;
string cust_order_handing_inst = 70;
string order_server_id = 200;
}
message NativeOrderState {
-2
View File
@@ -23,7 +23,6 @@
#include <map>
#include <tuple>
#define URDL_HEADER_ONLY 1
#define URDL_DISALE_SSL 1
#include <urdl/url.hpp>
@@ -906,4 +905,3 @@ std::string get_fallback(const proto::Message& message)
}
}}}//end namespaces
+11 -32
View File
@@ -37,6 +37,12 @@ CMEOptions {
# channels_per_thread: 1
spin_time: 0
}
channel {
id: "316"
feed_engine: "mdp3feed"
use_tcp_replay: false
sunday_pre_open: true
}
channel {
id: "*"
feed_engine: "mdp3feed"
@@ -63,41 +69,14 @@ ICEOptions {
channel {
name: "oil" #these names are arbitrary and are for debugging
market_type: 5 #ICE Futures Brent, IPE Brent Futures
uds_market_type: 5
market_type: 9 #ICE Futures WTI, ICE WTI Crude Futures
uds_market_type: 9
##market_type: 13 #ICE Heating Oil Futures
##uds_market_type: 13
##market_type: 15 #ICE NYH (RBOB) Gasoline Futures
##uds_market_type: 15
##market_type: 21 #ICE Futures US Agricultures, Coffee C
##uds_market_type: 21
##market_type: 23 #ICE Futures US Agricultures, FCOJ A
##uds_market_type: 23
market_type: 26 #ICE Futures US Financials DX
uds_market_type: 26
uds_market_type: 11 #ICE WTI-Brent spreads
##uds_market_type: 14 #ICE Heating Oil/WTI Futures Crack
##uds_market_type: 16 #ICE NYH (RBOB) Gasoline/WTI Futures Crack
##uds_market_type: 58 #ICE Futures UI Heating Oil / Brent
##uds_market_type: 59 #ICE NYH (RBOB) Gasoline/Brent Futures Crack
# market_type: 44 #ICE Henry Hub
# uds_market_type: 44
# market_type: 1 #ICE Financial Power
# uds_market_type: 1
market_type: 9 #ICE Futures WTI, ICE WTI Crude Futures
#udp_buffer_size: 33554432 #32mb
#onixs_log_mode: Debug
}
# channel {
# name: "juice"
# market_type: 26 #ICE Futures US Agricultures, FCOJ A
# }
channel {
name: "juice"
market_type: 23 #ICE Futures US Agricultures, FCOJ A
}
ice_config_file: "ConnectivityConfiguration.APITest.xml"
#ice_config_file: "ConnectivityConfiguration.PerfTest.xml"
}
}
+1 -2
View File
@@ -3,8 +3,7 @@ Ports {
value {
config_port: 8000
qbus_port: 8001
glbx_sim_fix_port: 8002
ice_sim_fix_port: 8003
exchange_sim_fix_port: 8002
replicator_port: 8080
}
}
+4 -16
View File
@@ -19,6 +19,7 @@ SymbolList {
symbol: "FOB"
symbol: "GC"
symbol: "GE"
symbol: "GLI"
symbol: "HE"
symbol: "HG"
symbol: "HO"
@@ -65,18 +66,9 @@ SymbolLists
list
{
key: "ICE"
symbol: "BRN"
symbol: "WBS"
symbol: "OJ"
symbol: "KC"
symbol: "UHO"
symbol: "UHU"
symbol: "DX"
symbol: "HEN"
symbol: "HIS"
symbol: "HNG"
symbol: "*"
# symbol: "BRN"
# symbol: "WBS"
# symbol: "OJ"
}
list
{
@@ -120,9 +112,5 @@ Symbols {
future: @SymbolLists.list[ICE].symbol
spread: @SymbolLists.list[ICE].symbol
}
simice {
future: @SymbolLists.list[ICE].symbol
spread: @SymbolLists.list[ICE].symbol
}
}
}
+129 -53
View File
@@ -90,8 +90,6 @@ CppConfig
cpp_entry { key: "8D" value: 1000 }
cpp_entry { key: "8W" value: 1000 }
cpp_entry { key: "8XN" value: 2500 }
cpp_entry { key: "8ZN" value: 2500 }
cpp_entry { key: "9FN" value: 2500 }
cpp_entry { key: "9Q" value: 1000 }
cpp_entry { key: "A0D" value: 100 }
cpp_entry { key: "A0F" value: 100 }
@@ -163,6 +161,7 @@ CppConfig
cpp_entry { key: "AAW" value: 42000 }
cpp_entry { key: "AB3" value: 80 }
cpp_entry { key: "AB7" value: 1000 }
cpp_entry { key: "ABF" value: 100 }
cpp_entry { key: "ABH" value: 42000 }
cpp_entry { key: "ABI" value: 1000 }
cpp_entry { key: "ABS" value: 1000 }
@@ -170,6 +169,7 @@ CppConfig
cpp_entry { key: "ABX" value: 1000 }
cpp_entry { key: "ABY" value: 1000 }
cpp_entry { key: "AC0" value: 42000 }
cpp_entry { key: "ACB" value: 1000 }
cpp_entry { key: "ACD" value: 200000 }
cpp_entry { key: "ACM" value: 1000 }
cpp_entry { key: "ACT" value: 1000 }
@@ -183,7 +183,7 @@ CppConfig
cpp_entry { key: "AE5" value: 1000 }
cpp_entry { key: "AE8" value: 5 }
cpp_entry { key: "AE9" value: 80 }
cpp_entry { key: "AEJ" value: 960 }
cpp_entry { key: "AEB" value: 1000 }
cpp_entry { key: "AEP" value: 25 }
cpp_entry { key: "AET" value: 1000 }
cpp_entry { key: "AEZ" value: 42000 }
@@ -222,7 +222,6 @@ CppConfig
cpp_entry { key: "AJB" value: 1000 }
cpp_entry { key: "AJJ" value: 5 }
cpp_entry { key: "AJL" value: 42000 }
cpp_entry { key: "AJP" value: 960 }
cpp_entry { key: "AJR" value: 1000 }
cpp_entry { key: "AJS" value: 42000 }
cpp_entry { key: "AJU" value: 42000 }
@@ -346,7 +345,6 @@ CppConfig
cpp_entry { key: "BCF" value: 50 }
cpp_entry { key: "BCH" value: 50 }
cpp_entry { key: "BDB" value: 1000 }
cpp_entry { key: "BDI" value: 100 }
cpp_entry { key: "BDS" value: 1000 }
cpp_entry { key: "BFR" value: 100 }
cpp_entry { key: "BG" value: 1000 }
@@ -357,13 +355,12 @@ CppConfig
cpp_entry { key: "BOO" value: 6350 }
cpp_entry { key: "BOS" value: 250 }
cpp_entry { key: "BR7" value: 1000 }
cpp_entry { key: "BSW" value: 136 }
cpp_entry { key: "BSF" value: 25 }
cpp_entry { key: "BTC" value: 5 }
cpp_entry { key: "BTT" value: 50 }
cpp_entry { key: "BUB" value: 1000 }
cpp_entry { key: "BUC" value: 42000 }
cpp_entry { key: "BUS" value: 20 }
cpp_entry { key: "BUW" value: 20 }
cpp_entry { key: "BWF" value: 50 }
cpp_entry { key: "BWH" value: 50 }
cpp_entry { key: "BZ" value: 1000 }
@@ -394,6 +391,7 @@ CppConfig
cpp_entry { key: "CFB" value: 1000 }
cpp_entry { key: "CFC" value: 1000 }
cpp_entry { key: "CGB" value: 42000 }
cpp_entry { key: "CHB" value: 1000 }
cpp_entry { key: "CHI" value: 250 }
cpp_entry { key: "CHL" value: 100000 }
cpp_entry { key: "CHP" value: 50000000 }
@@ -406,9 +404,11 @@ CppConfig
cpp_entry { key: "CL" value: 1000 }
cpp_entry { key: "CL1" value: 1000 }
cpp_entry { key: "CL2" value: 1000 }
cpp_entry { key: "CLD" value: 1000 }
cpp_entry { key: "CLL" value: 1000 }
cpp_entry { key: "CLS" value: 1000 }
cpp_entry { key: "CLT" value: 1000 }
cpp_entry { key: "CMB" value: 1000 }
cpp_entry { key: "CMF" value: 1000 }
cpp_entry { key: "CNH" value: 100000 }
cpp_entry { key: "COL" value: 80 }
@@ -431,7 +431,6 @@ CppConfig
cpp_entry { key: "CUS" value: 250 }
cpp_entry { key: "CY" value: 1000 }
cpp_entry { key: "CZK" value: 4000000 }
cpp_entry { key: "CZN" value: 2500 }
cpp_entry { key: "D0" value: 20 }
cpp_entry { key: "D0X" value: 20 }
cpp_entry { key: "D0Z" value: 20 }
@@ -461,9 +460,9 @@ CppConfig
cpp_entry { key: "DDO" value: 1000 }
cpp_entry { key: "DEB" value: 744 }
cpp_entry { key: "DEN" value: 250 }
cpp_entry { key: "DEP" value: 252 }
cpp_entry { key: "DEP" value: 264 }
cpp_entry { key: "DFL" value: 100 }
cpp_entry { key: "DFT" value: 100 }
cpp_entry { key: "DFN" value: 100 }
cpp_entry { key: "DG2" value: 100 }
cpp_entry { key: "DG3" value: 100 }
cpp_entry { key: "DGH" value: 1000 }
@@ -472,7 +471,6 @@ CppConfig
cpp_entry { key: "DGT" value: 100 }
cpp_entry { key: "DHA" value: 80 }
cpp_entry { key: "DHI" value: 1000 }
cpp_entry { key: "DIH" value: 2500 }
cpp_entry { key: "DJR" value: 100 }
cpp_entry { key: "DKR" value: 1000 }
cpp_entry { key: "DMB" value: 100 }
@@ -503,7 +501,6 @@ CppConfig
cpp_entry { key: "EAC" value: 80 }
cpp_entry { key: "EAD" value: 125000 }
cpp_entry { key: "EAE" value: 5 }
cpp_entry { key: "EAF" value: 1000 }
cpp_entry { key: "EAW" value: 80 }
cpp_entry { key: "EBE" value: 1000 }
cpp_entry { key: "ECD" value: 125000 }
@@ -542,7 +539,6 @@ CppConfig
cpp_entry { key: "EST" value: 50 }
cpp_entry { key: "ETT" value: 100 }
cpp_entry { key: "EUB" value: 80 }
cpp_entry { key: "EUL" value: 1000 }
cpp_entry { key: "EURADC" value: 1 }
cpp_entry { key: "EURBPC" value: 1 }
cpp_entry { key: "EURBPN" value: 1 }
@@ -668,17 +664,24 @@ CppConfig
cpp_entry { key: "H4X" value: 20 }
cpp_entry { key: "H4Z" value: 20 }
cpp_entry { key: "H5" value: 20 }
cpp_entry { key: "H5B" value: 1000 }
cpp_entry { key: "H5F" value: 1000 }
cpp_entry { key: "H5G" value: 1000 }
cpp_entry { key: "H5L" value: 80 }
cpp_entry { key: "H5X" value: 20 }
cpp_entry { key: "H5Z" value: 20 }
cpp_entry { key: "HB" value: 2500 }
cpp_entry { key: "HBC" value: 1000 }
cpp_entry { key: "HBR" value: 1000 }
cpp_entry { key: "HCL" value: 1000 }
cpp_entry { key: "HDB" value: 1000 }
cpp_entry { key: "HE" value: 400 }
cpp_entry { key: "HET" value: 400 }
cpp_entry { key: "HG" value: 25000 }
cpp_entry { key: "HG0" value: 25000 }
cpp_entry { key: "HGB" value: 1000 }
cpp_entry { key: "HGF" value: 25000 }
cpp_entry { key: "HGK" value: 25000 }
cpp_entry { key: "HGS" value: 25000 }
cpp_entry { key: "HGT" value: 25000 }
cpp_entry { key: "HH" value: 10000 }
@@ -703,11 +706,16 @@ CppConfig
cpp_entry { key: "HQX" value: 20 }
cpp_entry { key: "HQZ" value: 20 }
cpp_entry { key: "HRC" value: 20 }
cpp_entry { key: "HRP" value: 20 }
cpp_entry { key: "HS" value: 20 }
cpp_entry { key: "HSX" value: 20 }
cpp_entry { key: "HSZ" value: 20 }
cpp_entry { key: "HTA" value: 1000 }
cpp_entry { key: "HTB" value: 1000 }
cpp_entry { key: "HTC" value: 1000 }
cpp_entry { key: "HTE" value: 1000 }
cpp_entry { key: "HTI" value: 1000 }
cpp_entry { key: "HTM" value: 1000 }
cpp_entry { key: "HTT" value: 1000 }
cpp_entry { key: "HUF" value: 30000000 }
cpp_entry { key: "HWA" value: 80 }
@@ -719,7 +727,6 @@ CppConfig
cpp_entry { key: "ICI" value: 1000 }
cpp_entry { key: "IDL" value: 5 }
cpp_entry { key: "IH" value: 50 }
cpp_entry { key: "ILB" value: 1750 }
cpp_entry { key: "ILS" value: 1000000 }
cpp_entry { key: "IN" value: 2500 }
cpp_entry { key: "IP" value: 50 }
@@ -727,11 +734,12 @@ CppConfig
cpp_entry { key: "IPT" value: 10 }
cpp_entry { key: "IS" value: 50 }
cpp_entry { key: "ITB" value: 744 }
cpp_entry { key: "ITP" value: 252 }
cpp_entry { key: "ITP" value: 264 }
cpp_entry { key: "IW" value: 50 }
cpp_entry { key: "J4L" value: 80 }
cpp_entry { key: "J7" value: 6250000 }
cpp_entry { key: "JA" value: 1000 }
cpp_entry { key: "JCC" value: 1000 }
cpp_entry { key: "JDL" value: 80 }
cpp_entry { key: "JE" value: 42000 }
cpp_entry { key: "JET" value: 42000 }
@@ -740,7 +748,7 @@ CppConfig
cpp_entry { key: "JKB" value: 10000 }
cpp_entry { key: "JKF" value: 10000 }
cpp_entry { key: "JKM" value: 10000 }
cpp_entry { key: "JML" value: 200 }
cpp_entry { key: "JML" value: 480 }
cpp_entry { key: "JNC" value: 1000 }
cpp_entry { key: "JNG" value: 10000 }
cpp_entry { key: "JNL" value: 80 }
@@ -809,6 +817,9 @@ CppConfig
cpp_entry { key: "LSW" value: 1000 }
cpp_entry { key: "LT" value: 42000 }
cpp_entry { key: "LWB" value: 1000 }
cpp_entry { key: "M1B" value: 10 }
cpp_entry { key: "M2K" value: 5 }
cpp_entry { key: "M35" value: 10 }
cpp_entry { key: "M5F" value: 10 }
cpp_entry { key: "M6A" value: 10000 }
cpp_entry { key: "M6B" value: 6250 }
@@ -839,10 +850,11 @@ CppConfig
cpp_entry { key: "MEB" value: 100 }
cpp_entry { key: "MEE" value: 100 }
cpp_entry { key: "MEF" value: 10 }
cpp_entry { key: "MEL" value: 840 }
cpp_entry { key: "MEO" value: 100 }
cpp_entry { key: "MES" value: 5 }
cpp_entry { key: "MEW" value: 100 }
cpp_entry { key: "MFB" value: 1000 }
cpp_entry { key: "MFC" value: 100 }
cpp_entry { key: "MFD" value: 100 }
cpp_entry { key: "MFF" value: 1000 }
cpp_entry { key: "MFP" value: 100 }
@@ -879,6 +891,7 @@ CppConfig
cpp_entry { key: "MNE" value: 100 }
cpp_entry { key: "MNG" value: 2500 }
cpp_entry { key: "MNH" value: 10000 }
cpp_entry { key: "MNQ" value: 2 }
cpp_entry { key: "MNS" value: 635 }
cpp_entry { key: "MNT" value: 80 }
cpp_entry { key: "MO" value: 1000 }
@@ -910,6 +923,7 @@ CppConfig
cpp_entry { key: "MXB" value: 35000 }
cpp_entry { key: "MXL" value: 5 }
cpp_entry { key: "MXR" value: 35000 }
cpp_entry { key: "MYM" value: 0.5 }
cpp_entry { key: "N1B" value: 1000 }
cpp_entry { key: "N1R" value: 10 }
cpp_entry { key: "N1T" value: 10 }
@@ -927,7 +941,6 @@ CppConfig
cpp_entry { key: "NCF" value: 100 }
cpp_entry { key: "NCO" value: 5 }
cpp_entry { key: "NCP" value: 100 }
cpp_entry { key: "NEN" value: 2500 }
cpp_entry { key: "NEO" value: 5 }
cpp_entry { key: "NEP" value: 80 }
cpp_entry { key: "NFC" value: 1000 }
@@ -941,10 +954,14 @@ CppConfig
cpp_entry { key: "NHN" value: 2500 }
cpp_entry { key: "NHO" value: 5 }
cpp_entry { key: "NHP" value: 80 }
cpp_entry { key: "NIM" value: 500 }
cpp_entry { key: "NIT" value: 500 }
cpp_entry { key: "NIY" value: 500 }
cpp_entry { key: "NJ" value: 2500 }
cpp_entry { key: "NKD" value: 5 }
cpp_entry { key: "NKM" value: 5 }
cpp_entry { key: "NKN" value: 2500 }
cpp_entry { key: "NKT" value: 5 }
cpp_entry { key: "NL" value: 2500 }
cpp_entry { key: "NLS" value: 42000 }
cpp_entry { key: "NMO" value: 5 }
@@ -984,7 +1001,7 @@ CppConfig
cpp_entry { key: "NYR" value: 42000 }
cpp_entry { key: "NYT" value: 1000 }
cpp_entry { key: "NZDUSC" value: 1 }
cpp_entry { key: "NZN" value: 2500 }
cpp_entry { key: "NZDUSD" value: 1 }
cpp_entry { key: "OAD" value: 1 }
cpp_entry { key: "ODO" value: 1000 }
cpp_entry { key: "OFF" value: 5 }
@@ -1000,6 +1017,7 @@ CppConfig
cpp_entry { key: "OVL" value: 5 }
cpp_entry { key: "PA" value: 100 }
cpp_entry { key: "PAL" value: 80 }
cpp_entry { key: "PAM" value: 10 }
cpp_entry { key: "PAT" value: 100 }
cpp_entry { key: "PBO" value: 5 }
cpp_entry { key: "PBP" value: 80 }
@@ -1020,7 +1038,6 @@ CppConfig
cpp_entry { key: "PHF" value: 5 }
cpp_entry { key: "PHO" value: 5 }
cpp_entry { key: "PHP" value: 80 }
cpp_entry { key: "PIO" value: 500 }
cpp_entry { key: "PJY" value: 125000 }
cpp_entry { key: "PKP" value: 80 }
cpp_entry { key: "PL" value: 50 }
@@ -1082,6 +1099,8 @@ CppConfig
cpp_entry { key: "R2T" value: 10 }
cpp_entry { key: "R2V" value: 50 }
cpp_entry { key: "R53" value: 1000 }
cpp_entry { key: "R5B" value: 1000 }
cpp_entry { key: "R5E" value: 1000 }
cpp_entry { key: "R5F" value: 1000 }
cpp_entry { key: "R5M" value: 100 }
cpp_entry { key: "R5O" value: 10 }
@@ -1091,6 +1110,7 @@ CppConfig
cpp_entry { key: "RBF" value: 100 }
cpp_entry { key: "RBG" value: 42000 }
cpp_entry { key: "RBL" value: 42000 }
cpp_entry { key: "RBM" value: 100 }
cpp_entry { key: "RBS" value: 42000 }
cpp_entry { key: "RBT" value: 42000 }
cpp_entry { key: "REX" value: 100 }
@@ -1119,13 +1139,15 @@ CppConfig
cpp_entry { key: "RYA" value: 42000 }
cpp_entry { key: "S1U" value: 1000 }
cpp_entry { key: "S53" value: 1000 }
cpp_entry { key: "S5B" value: 1000 }
cpp_entry { key: "S5F" value: 1000 }
cpp_entry { key: "S5M" value: 100 }
cpp_entry { key: "S5O" value: 10 }
cpp_entry { key: "SBM" value: 100 }
cpp_entry { key: "SBT" value: 50 }
cpp_entry { key: "SD" value: 1000 }
cpp_entry { key: "SDA" value: 250 }
cpp_entry { key: "SDD" value: 1600 }
cpp_entry { key: "SDD" value: 1760 }
cpp_entry { key: "SDG" value: 250 }
cpp_entry { key: "SDI" value: 1000 }
cpp_entry { key: "SDM" value: 100 }
@@ -1157,12 +1179,14 @@ CppConfig
cpp_entry { key: "SMT" value: 100 }
cpp_entry { key: "SMU" value: 1000 }
cpp_entry { key: "SMW" value: 100 }
cpp_entry { key: "SOM" value: 500 }
cpp_entry { key: "SON" value: 2500 }
cpp_entry { key: "SP" value: 250 }
cpp_entry { key: "SR1" value: 4167 }
cpp_entry { key: "SR3" value: 2500 }
cpp_entry { key: "SR5" value: 1000 }
cpp_entry { key: "SRT" value: 1600 }
cpp_entry { key: "SRB" value: 1000 }
cpp_entry { key: "SRT" value: 1760 }
cpp_entry { key: "SSI" value: 1000 }
cpp_entry { key: "SSP" value: 5000 }
cpp_entry { key: "SSW" value: 1000 }
@@ -1173,25 +1197,31 @@ CppConfig
cpp_entry { key: "STY" value: 1000 }
cpp_entry { key: "SU" value: 250 }
cpp_entry { key: "SUT" value: 250 }
cpp_entry { key: "T02" value: 800 }
cpp_entry { key: "T03" value: 800 }
cpp_entry { key: "T04" value: 800 }
cpp_entry { key: "T06" value: 800 }
cpp_entry { key: "T07" value: 800 }
cpp_entry { key: "T08" value: 800 }
cpp_entry { key: "T09" value: 800 }
cpp_entry { key: "T12" value: 800 }
cpp_entry { key: "T13" value: 800 }
cpp_entry { key: "T14" value: 800 }
cpp_entry { key: "T17" value: 800 }
cpp_entry { key: "T18" value: 800 }
cpp_entry { key: "T15" value: 800 }
cpp_entry { key: "T16" value: 800 }
cpp_entry { key: "T19" value: 800 }
cpp_entry { key: "T1U" value: 1000 }
cpp_entry { key: "T20" value: 800 }
cpp_entry { key: "T21" value: 800 }
cpp_entry { key: "T24" value: 800 }
cpp_entry { key: "T22" value: 800 }
cpp_entry { key: "T23" value: 800 }
cpp_entry { key: "T26" value: 800 }
cpp_entry { key: "T27" value: 800 }
cpp_entry { key: "T28" value: 800 }
cpp_entry { key: "T29" value: 800 }
cpp_entry { key: "T2B" value: 1000 }
cpp_entry { key: "T2D" value: 1000 }
cpp_entry { key: "T2M" value: 100 }
cpp_entry { key: "T31" value: 800 }
cpp_entry { key: "T30" value: 800 }
cpp_entry { key: "T3B" value: 1000 }
cpp_entry { key: "T3L" value: 80 }
cpp_entry { key: "T4B" value: 1000 }
@@ -1207,6 +1237,7 @@ CppConfig
cpp_entry { key: "TC" value: 2500 }
cpp_entry { key: "TC6" value: 1000 }
cpp_entry { key: "TC9" value: 1000 }
cpp_entry { key: "TCS" value: 1000 }
cpp_entry { key: "TD3" value: 1000 }
cpp_entry { key: "TD8" value: 1000 }
cpp_entry { key: "TEX" value: 1000 }
@@ -1216,6 +1247,7 @@ CppConfig
cpp_entry { key: "THB" value: 1000 }
cpp_entry { key: "THD" value: 10000 }
cpp_entry { key: "TIC" value: 500 }
cpp_entry { key: "TIL" value: 1000 }
cpp_entry { key: "TIO" value: 500 }
cpp_entry { key: "TK" value: 1000 }
cpp_entry { key: "TKB" value: 1000 }
@@ -1252,7 +1284,6 @@ CppConfig
cpp_entry { key: "TUT" value: 1000 }
cpp_entry { key: "TUX" value: 1000 }
cpp_entry { key: "TW" value: 1000 }
cpp_entry { key: "TXN" value: 2500 }
cpp_entry { key: "TYT" value: 1000 }
cpp_entry { key: "TYX" value: 1000 }
cpp_entry { key: "TZ6" value: 2500 }
@@ -1262,10 +1293,12 @@ CppConfig
cpp_entry { key: "UB" value: 1000 }
cpp_entry { key: "UCM" value: 100 }
cpp_entry { key: "UDL" value: 80 }
cpp_entry { key: "UFB" value: 100 }
cpp_entry { key: "UFE" value: 100 }
cpp_entry { key: "UFG" value: 100 }
cpp_entry { key: "UFN" value: 100 }
cpp_entry { key: "UFU" value: 100 }
cpp_entry { key: "UFZ" value: 100 }
cpp_entry { key: "UFV" value: 100 }
cpp_entry { key: "UGG" value: 42000 }
cpp_entry { key: "UKG" value: 310 }
cpp_entry { key: "ULB" value: 42000 }
@@ -1276,10 +1309,12 @@ CppConfig
cpp_entry { key: "UNB" value: 1000 }
cpp_entry { key: "UNS" value: 1000 }
cpp_entry { key: "UR" value: 1000 }
cpp_entry { key: "USC" value: 1000 }
cpp_entry { key: "USDBRL" value: 1 }
cpp_entry { key: "USDCAC" value: 1 }
cpp_entry { key: "USDCAD" value: 1 }
cpp_entry { key: "USDCAN" value: 1 }
cpp_entry { key: "USDCHF" value: 10 }
cpp_entry { key: "USDCKC" value: 1 }
cpp_entry { key: "USDCLP" value: 1 }
cpp_entry { key: "USDCNY" value: 1 }
@@ -1309,6 +1344,7 @@ CppConfig
cpp_entry { key: "USDTLC" value: 1 }
cpp_entry { key: "USDTWD" value: 1 }
cpp_entry { key: "USDZRC" value: 1 }
cpp_entry { key: "USE" value: 1000 }
cpp_entry { key: "UV" value: 1000 }
cpp_entry { key: "UX" value: 250 }
cpp_entry { key: "V3L" value: 5 }
@@ -1338,6 +1374,7 @@ CppConfig
cpp_entry { key: "WTA" value: 1000 }
cpp_entry { key: "WTD" value: 1000 }
cpp_entry { key: "WTI" value: 1000 }
cpp_entry { key: "WTL" value: 1000 }
cpp_entry { key: "WTS" value: 1000 }
cpp_entry { key: "WTT" value: 1000 }
cpp_entry { key: "X0" value: 1000 }
@@ -1390,6 +1427,7 @@ CppConfig
cpp_entry { key: "YWE" value: 80 }
cpp_entry { key: "YWF" value: 5 }
cpp_entry { key: "YWK" value: 5 }
cpp_entry { key: "Z00000" value: 1000 }
cpp_entry { key: "Z1B" value: 100 }
cpp_entry { key: "Z3N" value: 2000 }
cpp_entry { key: "Z4" value: 1000 }
@@ -1507,8 +1545,6 @@ CmeSymbolMics
cme_mic { key: "8D" value: NYMEX }
cme_mic { key: "8W" value: NYMEX }
cme_mic { key: "8XN" value: NYMEX }
cme_mic { key: "8ZN" value: NYMEX }
cme_mic { key: "9FN" value: NYMEX }
cme_mic { key: "9Q" value: NYMEX }
cme_mic { key: "A0D" value: NYMEX }
cme_mic { key: "A0F" value: NYMEX }
@@ -1580,6 +1616,7 @@ CmeSymbolMics
cme_mic { key: "AAW" value: NYMEX }
cme_mic { key: "AB3" value: NYMEX }
cme_mic { key: "AB7" value: NYMEX }
cme_mic { key: "ABF" value: NYMEX }
cme_mic { key: "ABH" value: NYMEX }
cme_mic { key: "ABI" value: NYMEX }
cme_mic { key: "ABS" value: NYMEX }
@@ -1587,6 +1624,7 @@ CmeSymbolMics
cme_mic { key: "ABX" value: NYMEX }
cme_mic { key: "ABY" value: NYMEX }
cme_mic { key: "AC0" value: NYMEX }
cme_mic { key: "ACB" value: NYMEX }
cme_mic { key: "ACD" value: CME }
cme_mic { key: "ACM" value: NYMEX }
cme_mic { key: "ACT" value: NYMEX }
@@ -1600,7 +1638,7 @@ CmeSymbolMics
cme_mic { key: "AE5" value: NYMEX }
cme_mic { key: "AE8" value: NYMEX }
cme_mic { key: "AE9" value: NYMEX }
cme_mic { key: "AEJ" value: NYMEX }
cme_mic { key: "AEB" value: NYMEX }
cme_mic { key: "AEP" value: COMEX }
cme_mic { key: "AET" value: NYMEX }
cme_mic { key: "AEZ" value: NYMEX }
@@ -1639,7 +1677,6 @@ CmeSymbolMics
cme_mic { key: "AJB" value: NYMEX }
cme_mic { key: "AJJ" value: NYMEX }
cme_mic { key: "AJL" value: NYMEX }
cme_mic { key: "AJP" value: NYMEX }
cme_mic { key: "AJR" value: NYMEX }
cme_mic { key: "AJS" value: NYMEX }
cme_mic { key: "AJU" value: NYMEX }
@@ -1763,7 +1800,6 @@ CmeSymbolMics
cme_mic { key: "BCF" value: CBT }
cme_mic { key: "BCH" value: CBT }
cme_mic { key: "BDB" value: NYMEX }
cme_mic { key: "BDI" value: CME }
cme_mic { key: "BDS" value: DME }
cme_mic { key: "BFR" value: NYMEX }
cme_mic { key: "BG" value: NYMEX }
@@ -1774,13 +1810,12 @@ CmeSymbolMics
cme_mic { key: "BOO" value: NYMEX }
cme_mic { key: "BOS" value: CME }
cme_mic { key: "BR7" value: NYMEX }
cme_mic { key: "BSW" value: CBT }
cme_mic { key: "BSF" value: CBT }
cme_mic { key: "BTC" value: CME }
cme_mic { key: "BTT" value: CME }
cme_mic { key: "BUB" value: CBT }
cme_mic { key: "BUC" value: NYMEX }
cme_mic { key: "BUS" value: NYMEX }
cme_mic { key: "BUW" value: NYMSW }
cme_mic { key: "BWF" value: CBT }
cme_mic { key: "BWH" value: CBT }
cme_mic { key: "BZ" value: NYMEX }
@@ -1811,6 +1846,7 @@ CmeSymbolMics
cme_mic { key: "CFB" value: NYMEX }
cme_mic { key: "CFC" value: NYMEX }
cme_mic { key: "CGB" value: NYMEX }
cme_mic { key: "CHB" value: NYMEX }
cme_mic { key: "CHI" value: CME }
cme_mic { key: "CHL" value: CME }
cme_mic { key: "CHP" value: CME }
@@ -1823,9 +1859,11 @@ CmeSymbolMics
cme_mic { key: "CL" value: NYMEX }
cme_mic { key: "CL1" value: NYMEX }
cme_mic { key: "CL2" value: NYMEX }
cme_mic { key: "CLD" value: NYMEX }
cme_mic { key: "CLL" value: NYMEX }
cme_mic { key: "CLS" value: NYMEX }
cme_mic { key: "CLT" value: NYMEX }
cme_mic { key: "CMB" value: NYMEX }
cme_mic { key: "CMF" value: NYMEX }
cme_mic { key: "CNH" value: CME }
cme_mic { key: "COL" value: NYMEX }
@@ -1848,7 +1886,6 @@ CmeSymbolMics
cme_mic { key: "CUS" value: CME }
cme_mic { key: "CY" value: NYMEX }
cme_mic { key: "CZK" value: CME }
cme_mic { key: "CZN" value: NYMEX }
cme_mic { key: "D0" value: CME }
cme_mic { key: "D0X" value: CME }
cme_mic { key: "D0Z" value: CME }
@@ -1880,7 +1917,7 @@ CmeSymbolMics
cme_mic { key: "DEN" value: CME }
cme_mic { key: "DEP" value: NYMEX }
cme_mic { key: "DFL" value: CBT }
cme_mic { key: "DFT" value: CBT }
cme_mic { key: "DFN" value: CBT }
cme_mic { key: "DG2" value: CBT }
cme_mic { key: "DG3" value: CBT }
cme_mic { key: "DGH" value: DME }
@@ -1889,7 +1926,6 @@ CmeSymbolMics
cme_mic { key: "DGT" value: CBT }
cme_mic { key: "DHA" value: NYMEX }
cme_mic { key: "DHI" value: DME }
cme_mic { key: "DIH" value: NYMEX }
cme_mic { key: "DJR" value: CBT }
cme_mic { key: "DKR" value: DME }
cme_mic { key: "DMB" value: DME }
@@ -1920,7 +1956,6 @@ CmeSymbolMics
cme_mic { key: "EAC" value: NYMEX }
cme_mic { key: "EAD" value: CME }
cme_mic { key: "EAE" value: NYMEX }
cme_mic { key: "EAF" value: NYMEX }
cme_mic { key: "EAW" value: NYMEX }
cme_mic { key: "EBE" value: NYMEX }
cme_mic { key: "ECD" value: CME }
@@ -1959,7 +1994,6 @@ CmeSymbolMics
cme_mic { key: "EST" value: CME }
cme_mic { key: "ETT" value: CME }
cme_mic { key: "EUB" value: NYMEX }
cme_mic { key: "EUL" value: NYMEX }
cme_mic { key: "EURADC" value: CME }
cme_mic { key: "EURBPC" value: CME }
cme_mic { key: "EURBPN" value: CME }
@@ -2085,17 +2119,24 @@ CmeSymbolMics
cme_mic { key: "H4X" value: CME }
cme_mic { key: "H4Z" value: CME }
cme_mic { key: "H5" value: CME }
cme_mic { key: "H5B" value: NYMEX }
cme_mic { key: "H5F" value: NYMEX }
cme_mic { key: "H5G" value: NYMEX }
cme_mic { key: "H5L" value: NYMEX }
cme_mic { key: "H5X" value: CME }
cme_mic { key: "H5Z" value: CME }
cme_mic { key: "HB" value: NYMEX }
cme_mic { key: "HBC" value: NYMEX }
cme_mic { key: "HBR" value: NYMEX }
cme_mic { key: "HCL" value: NYMEX }
cme_mic { key: "HDB" value: NYMEX }
cme_mic { key: "HE" value: CME }
cme_mic { key: "HET" value: CME }
cme_mic { key: "HG" value: COMEX }
cme_mic { key: "HG0" value: COMEX }
cme_mic { key: "HGB" value: NYMEX }
cme_mic { key: "HGF" value: COMEX }
cme_mic { key: "HGK" value: COMEX }
cme_mic { key: "HGS" value: COMEX }
cme_mic { key: "HGT" value: COMEX }
cme_mic { key: "HH" value: NYMEX }
@@ -2120,11 +2161,16 @@ CmeSymbolMics
cme_mic { key: "HQX" value: CME }
cme_mic { key: "HQZ" value: CME }
cme_mic { key: "HRC" value: NYMEX }
cme_mic { key: "HRP" value: COMEX }
cme_mic { key: "HS" value: CME }
cme_mic { key: "HSX" value: CME }
cme_mic { key: "HSZ" value: CME }
cme_mic { key: "HTA" value: NYMEX }
cme_mic { key: "HTB" value: NYMEX }
cme_mic { key: "HTC" value: NYMEX }
cme_mic { key: "HTE" value: NYMEX }
cme_mic { key: "HTI" value: NYMEX }
cme_mic { key: "HTM" value: NYMEX }
cme_mic { key: "HTT" value: NYMEX }
cme_mic { key: "HUF" value: CME }
cme_mic { key: "HWA" value: NYMEX }
@@ -2136,7 +2182,6 @@ CmeSymbolMics
cme_mic { key: "ICI" value: NYMEX }
cme_mic { key: "IDL" value: NYMEX }
cme_mic { key: "IH" value: MGE }
cme_mic { key: "ILB" value: NYMEX }
cme_mic { key: "ILS" value: CME }
cme_mic { key: "IN" value: NYMEX }
cme_mic { key: "IP" value: MGE }
@@ -2149,6 +2194,7 @@ CmeSymbolMics
cme_mic { key: "J4L" value: NYMEX }
cme_mic { key: "J7" value: CME }
cme_mic { key: "JA" value: NYMEX }
cme_mic { key: "JCC" value: NYMEX }
cme_mic { key: "JDL" value: NYMEX }
cme_mic { key: "JE" value: NYMEX }
cme_mic { key: "JET" value: NYMEX }
@@ -2226,6 +2272,9 @@ CmeSymbolMics
cme_mic { key: "LSW" value: NYMEX }
cme_mic { key: "LT" value: NYMEX }
cme_mic { key: "LWB" value: NYMEX }
cme_mic { key: "M1B" value: NYMEX }
cme_mic { key: "M2K" value: CME }
cme_mic { key: "M35" value: NYMEX }
cme_mic { key: "M5F" value: NYMEX }
cme_mic { key: "M6A" value: CME }
cme_mic { key: "M6B" value: CME }
@@ -2256,10 +2305,11 @@ CmeSymbolMics
cme_mic { key: "MEB" value: NYMEX }
cme_mic { key: "MEE" value: NYMEX }
cme_mic { key: "MEF" value: NYMEX }
cme_mic { key: "MEL" value: NYMEX }
cme_mic { key: "MEO" value: NYMEX }
cme_mic { key: "MES" value: CME }
cme_mic { key: "MEW" value: NYMEX }
cme_mic { key: "MFB" value: NYMEX }
cme_mic { key: "MFC" value: CBT }
cme_mic { key: "MFD" value: NYMEX }
cme_mic { key: "MFF" value: NYMEX }
cme_mic { key: "MFP" value: NYMEX }
@@ -2296,6 +2346,7 @@ CmeSymbolMics
cme_mic { key: "MNE" value: NYMEX }
cme_mic { key: "MNG" value: NYMEX }
cme_mic { key: "MNH" value: CME }
cme_mic { key: "MNQ" value: CME }
cme_mic { key: "MNS" value: NYMEX }
cme_mic { key: "MNT" value: NYMEX }
cme_mic { key: "MO" value: NYMEX }
@@ -2327,6 +2378,7 @@ CmeSymbolMics
cme_mic { key: "MXB" value: NYMEX }
cme_mic { key: "MXL" value: NYMEX }
cme_mic { key: "MXR" value: NYMEX }
cme_mic { key: "MYM" value: CBT }
cme_mic { key: "N1B" value: NYMEX }
cme_mic { key: "N1R" value: CME }
cme_mic { key: "N1T" value: CME }
@@ -2344,7 +2396,6 @@ CmeSymbolMics
cme_mic { key: "NCF" value: NYMEX }
cme_mic { key: "NCO" value: NYMEX }
cme_mic { key: "NCP" value: NYMEX }
cme_mic { key: "NEN" value: NYMEX }
cme_mic { key: "NEO" value: NYMEX }
cme_mic { key: "NEP" value: NYMEX }
cme_mic { key: "NFC" value: NYMEX }
@@ -2358,10 +2409,14 @@ CmeSymbolMics
cme_mic { key: "NHN" value: NYMEX }
cme_mic { key: "NHO" value: NYMEX }
cme_mic { key: "NHP" value: NYMEX }
cme_mic { key: "NIM" value: CME }
cme_mic { key: "NIT" value: CME }
cme_mic { key: "NIY" value: CME }
cme_mic { key: "NJ" value: NYMEX }
cme_mic { key: "NKD" value: CME }
cme_mic { key: "NKM" value: CME }
cme_mic { key: "NKN" value: NYMEX }
cme_mic { key: "NKT" value: CME }
cme_mic { key: "NL" value: NYMEX }
cme_mic { key: "NLS" value: NYMEX }
cme_mic { key: "NMO" value: NYMEX }
@@ -2401,7 +2456,7 @@ CmeSymbolMics
cme_mic { key: "NYR" value: NYMEX }
cme_mic { key: "NYT" value: NYMEX }
cme_mic { key: "NZDUSC" value: CME }
cme_mic { key: "NZN" value: NYMEX }
cme_mic { key: "NZDUSD" value: FXS }
cme_mic { key: "OAD" value: NYMEX }
cme_mic { key: "ODO" value: DME }
cme_mic { key: "OFF" value: NYMEX }
@@ -2417,6 +2472,7 @@ CmeSymbolMics
cme_mic { key: "OVL" value: NYMEX }
cme_mic { key: "PA" value: NYMEX }
cme_mic { key: "PAL" value: NYMEX }
cme_mic { key: "PAM" value: NYMEX }
cme_mic { key: "PAT" value: NYMEX }
cme_mic { key: "PBO" value: NYMEX }
cme_mic { key: "PBP" value: NYMEX }
@@ -2437,7 +2493,6 @@ CmeSymbolMics
cme_mic { key: "PHF" value: NYMEX }
cme_mic { key: "PHO" value: NYMEX }
cme_mic { key: "PHP" value: NYMEX }
cme_mic { key: "PIO" value: NYMEX }
cme_mic { key: "PJY" value: CME }
cme_mic { key: "PKP" value: NYMEX }
cme_mic { key: "PL" value: NYMEX }
@@ -2499,6 +2554,8 @@ CmeSymbolMics
cme_mic { key: "R2T" value: CME }
cme_mic { key: "R2V" value: CME }
cme_mic { key: "R53" value: NYMEX }
cme_mic { key: "R5B" value: NYMEX }
cme_mic { key: "R5E" value: NYMEX }
cme_mic { key: "R5F" value: NYMEX }
cme_mic { key: "R5M" value: NYMEX }
cme_mic { key: "R5O" value: NYMEX }
@@ -2508,6 +2565,7 @@ CmeSymbolMics
cme_mic { key: "RBF" value: NYMEX }
cme_mic { key: "RBG" value: NYMEX }
cme_mic { key: "RBL" value: NYMEX }
cme_mic { key: "RBM" value: NYMEX }
cme_mic { key: "RBS" value: NYMEX }
cme_mic { key: "RBT" value: NYMEX }
cme_mic { key: "REX" value: CBT }
@@ -2536,9 +2594,11 @@ CmeSymbolMics
cme_mic { key: "RYA" value: NYMEX }
cme_mic { key: "S1U" value: CBT }
cme_mic { key: "S53" value: NYMEX }
cme_mic { key: "S5B" value: NYMEX }
cme_mic { key: "S5F" value: NYMEX }
cme_mic { key: "S5M" value: NYMEX }
cme_mic { key: "S5O" value: NYMEX }
cme_mic { key: "SBM" value: NYMEX }
cme_mic { key: "SBT" value: CBT }
cme_mic { key: "SD" value: NYMEX }
cme_mic { key: "SDA" value: CME }
@@ -2574,11 +2634,13 @@ CmeSymbolMics
cme_mic { key: "SMT" value: CME }
cme_mic { key: "SMU" value: NYMEX }
cme_mic { key: "SMW" value: NYMEX }
cme_mic { key: "SOM" value: CBT }
cme_mic { key: "SON" value: CME }
cme_mic { key: "SP" value: CME }
cme_mic { key: "SR1" value: CME }
cme_mic { key: "SR3" value: CME }
cme_mic { key: "SR5" value: NYMEX }
cme_mic { key: "SRB" value: NYMEX }
cme_mic { key: "SRT" value: NYMEX }
cme_mic { key: "SSI" value: NYMEX }
cme_mic { key: "SSP" value: COMEX }
@@ -2590,25 +2652,31 @@ CmeSymbolMics
cme_mic { key: "STY" value: NYMEX }
cme_mic { key: "SU" value: CME }
cme_mic { key: "SUT" value: CME }
cme_mic { key: "T02" value: NYMEX }
cme_mic { key: "T03" value: NYMEX }
cme_mic { key: "T04" value: NYMEX }
cme_mic { key: "T06" value: NYMEX }
cme_mic { key: "T07" value: NYMEX }
cme_mic { key: "T08" value: NYMEX }
cme_mic { key: "T09" value: NYMEX }
cme_mic { key: "T12" value: NYMEX }
cme_mic { key: "T13" value: NYMEX }
cme_mic { key: "T14" value: NYMEX }
cme_mic { key: "T17" value: NYMEX }
cme_mic { key: "T18" value: NYMEX }
cme_mic { key: "T15" value: NYMEX }
cme_mic { key: "T16" value: NYMEX }
cme_mic { key: "T19" value: NYMEX }
cme_mic { key: "T1U" value: CBT }
cme_mic { key: "T20" value: NYMEX }
cme_mic { key: "T21" value: NYMEX }
cme_mic { key: "T24" value: NYMEX }
cme_mic { key: "T22" value: NYMEX }
cme_mic { key: "T23" value: NYMEX }
cme_mic { key: "T26" value: NYMEX }
cme_mic { key: "T27" value: NYMEX }
cme_mic { key: "T28" value: NYMEX }
cme_mic { key: "T29" value: NYMEX }
cme_mic { key: "T2B" value: NYMEX }
cme_mic { key: "T2D" value: NYMEX }
cme_mic { key: "T2M" value: NYMEX }
cme_mic { key: "T31" value: NYMEX }
cme_mic { key: "T30" value: NYMEX }
cme_mic { key: "T3B" value: NYMEX }
cme_mic { key: "T3L" value: NYMEX }
cme_mic { key: "T4B" value: NYMEX }
@@ -2624,6 +2692,7 @@ CmeSymbolMics
cme_mic { key: "TC" value: NYMEX }
cme_mic { key: "TC6" value: NYMEX }
cme_mic { key: "TC9" value: NYMEX }
cme_mic { key: "TCS" value: NYMEX }
cme_mic { key: "TD3" value: NYMEX }
cme_mic { key: "TD8" value: NYMEX }
cme_mic { key: "TEX" value: CBT }
@@ -2633,6 +2702,7 @@ CmeSymbolMics
cme_mic { key: "THB" value: NYMEX }
cme_mic { key: "THD" value: NYMEX }
cme_mic { key: "TIC" value: NYMEX }
cme_mic { key: "TIL" value: NYMEX }
cme_mic { key: "TIO" value: NYMEX }
cme_mic { key: "TK" value: NYMEX }
cme_mic { key: "TKB" value: NYMEX }
@@ -2669,7 +2739,6 @@ CmeSymbolMics
cme_mic { key: "TUT" value: CBT }
cme_mic { key: "TUX" value: CBT }
cme_mic { key: "TW" value: NYMEX }
cme_mic { key: "TXN" value: NYMEX }
cme_mic { key: "TYT" value: CBT }
cme_mic { key: "TYX" value: CBT }
cme_mic { key: "TZ6" value: NYMEX }
@@ -2679,10 +2748,12 @@ CmeSymbolMics
cme_mic { key: "UB" value: CBT }
cme_mic { key: "UCM" value: NYMEX }
cme_mic { key: "UDL" value: NYMEX }
cme_mic { key: "UFB" value: CBT }
cme_mic { key: "UFE" value: CBT }
cme_mic { key: "UFG" value: CBT }
cme_mic { key: "UFN" value: CBT }
cme_mic { key: "UFU" value: CBT }
cme_mic { key: "UFZ" value: CBT }
cme_mic { key: "UFV" value: CBT }
cme_mic { key: "UGG" value: NYMEX }
cme_mic { key: "UKG" value: NYMEX }
cme_mic { key: "ULB" value: NYMEX }
@@ -2693,10 +2764,12 @@ CmeSymbolMics
cme_mic { key: "UNB" value: NYMEX }
cme_mic { key: "UNS" value: NYMEX }
cme_mic { key: "UR" value: NYMEX }
cme_mic { key: "USC" value: NYMEX }
cme_mic { key: "USDBRL" value: CME }
cme_mic { key: "USDCAC" value: CME }
cme_mic { key: "USDCAD" value: FXS }
cme_mic { key: "USDCAN" value: CME }
cme_mic { key: "USDCHF" value: FXS }
cme_mic { key: "USDCKC" value: CME }
cme_mic { key: "USDCLP" value: CME }
cme_mic { key: "USDCNY" value: CME }
@@ -2726,6 +2799,7 @@ CmeSymbolMics
cme_mic { key: "USDTLC" value: CME }
cme_mic { key: "USDTWD" value: CME }
cme_mic { key: "USDZRC" value: CME }
cme_mic { key: "USE" value: NYMEX }
cme_mic { key: "UV" value: NYMEX }
cme_mic { key: "UX" value: NYMEX }
cme_mic { key: "V3L" value: NYMEX }
@@ -2755,6 +2829,7 @@ CmeSymbolMics
cme_mic { key: "WTA" value: NYMEX }
cme_mic { key: "WTD" value: NYMEX }
cme_mic { key: "WTI" value: NYMEX }
cme_mic { key: "WTL" value: NYMEX }
cme_mic { key: "WTS" value: NYMEX }
cme_mic { key: "WTT" value: NYMEX }
cme_mic { key: "X0" value: NYMEX }
@@ -2807,6 +2882,7 @@ CmeSymbolMics
cme_mic { key: "YWE" value: NYMEX }
cme_mic { key: "YWF" value: NYMEX }
cme_mic { key: "YWK" value: NYMEX }
cme_mic { key: "Z00000" value: CME }
cme_mic { key: "Z1B" value: NYMEX }
cme_mic { key: "Z3N" value: CBT }
cme_mic { key: "Z4" value: NYMEX }
+188 -352
View File
@@ -5,7 +5,7 @@ JetFIXSimConnection {
name: "sim"
platform: SIM
socket_connect_host_ip: "127.0.0.1"
socket_connect_port: @Ports.glbx_sim_fix_port
socket_connect_port: @Ports.exchange_sim_fix_port
sender_compid: "SPARK" # this is the FIX session name
sender_subid: "BTS"
target_compid: "BTS"
@@ -18,173 +18,9 @@ JetFIXSimConnection {
seconds_to_pause : 1
max_connection_attempts: 9999999
}
sim_ice {
name: "sim_ice"
platform: SIMICE
socket_connect_host_ip: "127.0.0.1"
socket_connect_port: @Ports.ice_sim_fix_port
sender_compid: "51239" # this is the FIX session name
sender_subid: "BTS"
target_compid: "BTS"
target_subid: "BTS"
cme_market_segment_id: 0
end_time: "02:00:00"
start_time: "02:05:00"
raw_data: "1JE9X"
use_cme_secure_logon: false
seconds_to_pause : 1
}
}
}
JetFIX {
rule: "CannedCertSession.name='ice_cert'"
value {
#connection: @JetFIXSimConnection.sim_ice
connection {
name: "ice_cert"
platform: ICE
use_cme_secure_logon: false
log_fix_stream: true
socket_connect_host_ip: "63.247.113.154"
socket_connect_port: 80
sender_compid: "51251"
target_compid: "ICE"
start_time: "22:55:00"
end_time: "22:05:00"
sender_subid: "BTS"
user_name: "bluetrd-os" #this is the order_server_id
raw_data: "Starts123"
max_order_msgs_per_window: 300
auto_fix_seq_num: true
seconds_to_replay: 6000
}
connection: @JetFIXSimConnection.sim
#connection: @JetFIXSimConnection.sim_ice
connection {
name: "cme_mc5_99"
platform: GLBX
socket_connect_host_ip: "69.50.112.199"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "99"
cme_market_segment_id: 99
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc5_58"
platform: GLBX
socket_connect_host_ip: "69.50.112.172"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "58"
cme_market_segment_id: 58
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc5_54"
platform: GLBX
socket_connect_host_ip: "69.50.112.191"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "54"
cme_market_segment_id: 54
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc5_82"
platform: GLBX
socket_connect_host_ip: "69.50.112.179"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "82"
cme_market_segment_id: 82
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc5_56"
platform: GLBX
socket_connect_host_ip: "69.50.112.174"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "56"
cme_market_segment_id: 56
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc5_50"
platform: GLBX
socket_connect_host_ip: "69.50.112.202"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "50"
cme_market_segment_id: 50
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc5_52"
platform: GLBX
socket_connect_host_ip: "69.50.112.181"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "52"
cme_market_segment_id: 52
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
}
}
JetFIX {
rule: "CannedCertSession.name='mc7'"
value {
@@ -620,193 +456,193 @@ JetFIX {
raw_data: "S4PMA"
auto_fix_seq_num: true
}
# connection {
# name: "cme_mc5_60"
# platform: GLBX
# socket_connect_host_ip: "69.50.112.195"
# socket_connect_port: 61922
# sender_compid: "MC5004N"
# target_compid: "CME"
# target_subid: "60"
# cme_market_segment_id: 60
# start_time: "00:30:00"
# end_time: "23:30:00"
# start_day: "sunday"
# end_day: "friday"
# sender_subid: "BTS"
# raw_data: "S4PMA"
# auto_fix_seq_num: true
# }
# connection {
# name: "cme_mc5_76"
# platform: GLBX
# socket_connect_host_ip: "69.50.112.204"
# socket_connect_port: 61922
# sender_compid: "MC5004N"
# target_compid: "CME"
# target_subid: "76"
# cme_market_segment_id: 76
# start_time: "00:30:00"
# end_time: "23:30:00"
# start_day: "sunday"
# end_day: "friday"
# sender_subid: "BTS"
# raw_data: "S4PMA"
# auto_fix_seq_num: true
# }
# connection {
# name: "cme_mc5_88"
# platform: GLBX
# socket_connect_host_ip: "69.50.112.169"
# socket_connect_port: 61922
# sender_compid: "MC5004N"
# target_compid: "CME"
# target_subid: "88"
# cme_market_segment_id: 88
# start_time: "00:30:00"
# end_time: "23:30:00"
# start_day: "sunday"
# end_day: "friday"
# sender_subid: "BTS"
# raw_data: "S4PMA"
# auto_fix_seq_num: true
# }
# connection {
# name: "cme_mc5_74"
# platform: GLBX
# socket_connect_host_ip: "69.50.112.197"
# socket_connect_port: 61922
# sender_compid: "MC5004N"
# target_compid: "CME"
# target_subid: "74"
# cme_market_segment_id: 74
# start_time: "00:30:00"
# end_time: "23:30:00"
# start_day: "sunday"
# end_day: "friday"
# sender_subid: "BTS"
# raw_data: "S4PMA"
# auto_fix_seq_num: true
# }
# connection {
# name: "cme_mc5_64"
# platform: GLBX
# socket_connect_host_ip: "69.50.112.177"
# socket_connect_port: 61922
# sender_compid: "MC5004N"
# target_compid: "CME"
# target_subid: "64"
# cme_market_segment_id: 64
# start_time: "00:30:00"
# end_time: "23:30:00"
# start_day: "sunday"
# end_day: "friday"
# sender_subid: "BTS"
# raw_data: "S4PMA"
# auto_fix_seq_num: true
# }
# connection {
# name: "cme_mc5_72"
# platform: GLBX
# socket_connect_host_ip: "69.50.112.189"
# socket_connect_port: 61922
# sender_compid: "MC5004N"
# target_compid: "CME"
# target_subid: "72"
# cme_market_segment_id: 72
# start_time: "00:30:00"
# end_time: "23:30:00"
# start_day: "sunday"
# end_day: "friday"
# sender_subid: "BTS"
# raw_data: "S4PMA"
# auto_fix_seq_num: true
# }
# connection {
# name: "cme_mc5_70"
# platform: GLBX
# socket_connect_host_ip: "69.50.112.183"
# socket_connect_port: 61922
# sender_compid: "MC5004N"
# target_compid: "CME"
# target_subid: "70"
# cme_market_segment_id: 70
# start_time: "00:30:00"
# end_time: "23:30:00"
# start_day: "sunday"
# end_day: "friday"
# sender_subid: "BTS"
# raw_data: "S4PMA"
# auto_fix_seq_num: true
# }
# connection {
# name: "cme_mc5_68"
# platform: GLBX
# socket_connect_host_ip: "69.50.112.168"
# socket_connect_port: 61922
# sender_compid: "MC5004N"
# target_compid: "CME"
# target_subid: "68"
# cme_market_segment_id: 68
# start_time: "00:30:00"
# end_time: "23:30:00"
# start_day: "sunday"
# end_day: "friday"
# sender_subid: "BTS"
# raw_data: "S4PMA"
# auto_fix_seq_num: true
# }
# connection {
# name: "cme_mc5_80"
# platform: GLBX
# socket_connect_host_ip: "69.50.112.187"
# socket_connect_port: 61922
# sender_compid: "MC5004N"
# target_compid: "CME"
# target_subid: "80"
# cme_market_segment_id: 80
# start_time: "00:30:00"
# end_time: "23:30:00"
# start_day: "sunday"
# end_day: "friday"
# sender_subid: "BTS"
# raw_data: "S4PMA"
# auto_fix_seq_num: true
# }
# connection {
# name: "cme_mc5_84"
# platform: GLBX
# socket_connect_host_ip: "69.50.112.198"
# socket_connect_port: 61922
# sender_compid: "MC5004N"
# target_compid: "CME"
# target_subid: "84"
# cme_market_segment_id: 84
# start_time: "00:30:00"
# end_time: "23:30:00"
# start_day: "sunday"
# end_day: "friday"
# sender_subid: "BTS"
# raw_data: "S4PMA"
# auto_fix_seq_num: true
# }
# connection {
# name: "cme_mc5_78"
# platform: GLBX
# socket_connect_host_ip: "69.50.112.167"
# socket_connect_port: 61922
# sender_compid: "MC5004N"
# target_compid: "CME"
# target_subid: "78"
# cme_market_segment_id: 78
# start_time: "00:30:00"
# end_time: "23:30:00"
# start_day: "sunday"
# end_day: "friday"
# sender_subid: "BTS"
# raw_data: "S4PMA"
# auto_fix_seq_num: true
# }
connection {
name: "cme_mc5_60"
platform: GLBX
socket_connect_host_ip: "69.50.112.195"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "60"
cme_market_segment_id: 60
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc5_76"
platform: GLBX
socket_connect_host_ip: "69.50.112.204"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "76"
cme_market_segment_id: 76
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc5_88"
platform: GLBX
socket_connect_host_ip: "69.50.112.169"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "88"
cme_market_segment_id: 88
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc5_74"
platform: GLBX
socket_connect_host_ip: "69.50.112.197"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "74"
cme_market_segment_id: 74
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc5_64"
platform: GLBX
socket_connect_host_ip: "69.50.112.177"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "64"
cme_market_segment_id: 64
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc5_72"
platform: GLBX
socket_connect_host_ip: "69.50.112.189"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "72"
cme_market_segment_id: 72
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc5_70"
platform: GLBX
socket_connect_host_ip: "69.50.112.183"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "70"
cme_market_segment_id: 70
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc5_68"
platform: GLBX
socket_connect_host_ip: "69.50.112.168"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "68"
cme_market_segment_id: 68
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc5_80"
platform: GLBX
socket_connect_host_ip: "69.50.112.187"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "80"
cme_market_segment_id: 80
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc5_84"
platform: GLBX
socket_connect_host_ip: "69.50.112.198"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "84"
cme_market_segment_id: 84
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc5_78"
platform: GLBX
socket_connect_host_ip: "69.50.112.167"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "78"
cme_market_segment_id: 78
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
}
}
JetFIX {
@@ -2,14 +2,4 @@ OrdersSoftCleanupCutoff {
value {
extra_days: 1
}
}
SODTime
{
rule: "DeploymentType.type == 'dev'"
value
{
sod_hh: 20
sod_mm: 30
}
}
+2 -1
View File
@@ -126,6 +126,8 @@ message CMEOptions
// optional BookType book_type = 34 [default = BOOKTYPE_CONSOLIDATED];
optional bool validate_mbo = 35 [default = false];
optional bool sunday_pre_open = 36 [ default = true ];
}
optional string onixs_license = 1 [default = "{default}"];
repeated CMEChannel channel = 3;
@@ -154,7 +156,6 @@ message ICEOptions
message ICEChannel {
required string name = 1;
repeated uint32 market_type = 2;
repeated uint32 uds_market_type = 7;
optional uint32 udp_buffer_size = 3 [default = 4194304]; //4mb
optional uint32 heartbeat_interval = 4 [default = 36000];
optional uint32 sequence_gap_margin = 5 [default = 10000];
+1 -2
View File
@@ -5,7 +5,6 @@ message Ports {
// see ports.conf for actual defaults
optional int32 config_port = 1 ;
optional int32 qbus_port = 2 ;
optional int32 glbx_sim_fix_port = 3 ;
optional int32 ice_sim_fix_port = 5 ;
optional int32 exchange_sim_fix_port = 3 ;
optional int32 replicator_port = 4 ;
}
-1
View File
@@ -20,5 +20,4 @@ message Symbols {
optional SecurityExchangeList glbx = 10;
optional SecurityExchangeList sim = 20;
optional SecurityExchangeList ice = 30;
optional SecurityExchangeList simice = 40;
}
+3 -7
View File
@@ -7,11 +7,9 @@ message JetFIX {
required string name = 10;
enum JetFIXPlatform {
GLBX = 1;
CBOE = 6;
SIM = 2;
ICE = 3;
SIMICE = 4;
GLBX = 1;
CBOE = 6;
SIM = 2;
}
optional JetFIXPlatform platform = 15 [default = GLBX];
@@ -49,7 +47,6 @@ message JetFIX {
optional string target_subid = 130 [default = ""];
optional string sender_locationid = 135 [default = "US,NC"];
optional string raw_data = 136 [default =""];
optional string user_name = 138 [default =""];
optional string self_match_prevention_id = 140 [default=""];
optional string cti_code = 145 [default="1"];
optional int32 customer_or_firm = 147 [default=1];
@@ -94,7 +91,6 @@ message JetFIX {
message JetFIXSimConnection {
required JetFIX.Connection sim = 10;
required JetFIX.Connection sim_ice = 20;
}
message CannedCertSession {
+4
View File
@@ -48,6 +48,10 @@ message RejectStopAndStopLimitOrders {
optional bool enabled = 1 [default = true];
}
message SOMTicksFix {
optional bool enabled = 1 [default = true];
}
message EnsureOnScreenWithWorkAreaRect {
// Defaulting to false bc this is near the end of the cycle (04/27/2019),
// and the new ensure_onscreen code has only been tested with a single monitor arrangement.
+1 -2
View File
@@ -27,10 +27,9 @@ std::string descriptor(api::Security const &sec) {
else if (sec.has_ice())
return sec.ice().security_desc();
else
return "No descriptor for non glbx / ice exchange";
return "No descriptor for non glbx exchange";
}
boost::gregorian::date smallest_leg(
::google::protobuf::RepeatedPtrField<::bts::api::ContractLeg> const &l) {
bts_assert(l.size());
+2 -3
View File
@@ -182,6 +182,5 @@ inline bool gr_than(double p1, double p2, double tick_size) {
return gr_than_eq(p1, p2, tick_size) &&
!test_price_equality(p1,p2,tick_size);
}
}}
} // namespace securities
} // namespace bts
+7 -10
View File
@@ -12,7 +12,6 @@ enum Venue {
VENUE_CBOECFE = 207;
VENUE_GLBX = 301;
VENUE_ICE = 306;
VENUE_SIMICE = 3;
}
enum SecurityType {
@@ -55,12 +54,11 @@ enum CMEMics {
}
enum ICEMics{
IF_UNSET = 0;
IFU = 1;
IFE = 2;
IFL = 3;
IFC = 4;
IFEN = 5;
ICE_UNSET=0;
ICE_US = 1;
ICE_EU = 2;
ICE_LIFFE = 3;
ICE_CA = 4;
}
enum Side {
@@ -105,9 +103,8 @@ message CBOECFEExchangeData {
message ICEExchangeData {
int64 exchange_id = 10;
string security_desc = 15; //contractSymbol
int32 price_denominator = 17;
int32 deal_denominator = 20;
int32 settle_denominator = 30;
int32 deal_display_factor = 20;
int32 settle_display_factor = 30;
string market_description = 100;
string cleared_alias = 110;
+124 -125
View File
@@ -1,11 +1,11 @@
#pragma once
#include "lib/jetfix/codec/FIXBuffer.h"
#include "lib/jetfix/codec/FIXFragment.h"
#include "lib/jetfix/codec/FieldDefinitions.h"
#include "lib/jetfix/codec/Fields.h"
#include "lib/jetfix/codec/MessageTypes.h"
#include <memory>
#include "lib/jetfix/codec/FIXBuffer.h"
#include "lib/jetfix/codec/MessageTypes.h"
#include "lib/jetfix/codec/FIXFragment.h"
#include "lib/jetfix/codec/Fields.h"
#include "lib/jetfix/codec/FieldDefinitions.h"
#include "lib/config/protos/jetfix.pb.h"
@@ -14,186 +14,185 @@ namespace jetfix {
// Helper to batch the encoding of multiple FIX messages all sharing
// the same FIX headers.
class FIXEncodingStream {
public:
class FIXEncodingStream
{
public:
FIXEncodingStream(config::JetFIX::Connection const &cfg,
uint32_t initial_capacity = 1024 * 10)
: _msg_header_template(), _header_template_size(),
_header_template_checksum(), _buffer(initial_capacity), _message_map(),
_current_msg(_buffer), _state(State::OPEN), _seq_num_bm(),
_last_seq_num_bm(), _sending_time_bm() {
_message_map.reserve(10 * 1024);
uint32_t initial_capacity = 1024*10)
:
_msg_header_template (),
_header_template_size (),
_header_template_checksum (),
_buffer (initial_capacity),
_message_map (),
_current_msg (_buffer),
_state (State::OPEN),
_body_length_bm (),
_msg_type_bm (),
_seq_num_bm (),
_last_seq_num_bm (),
_sending_time_bm ()
{
_message_map.reserve (10*1024);
FIXBuffer header_buffer(&_msg_header_template[0],
_msg_header_template.size());
FIXFragment header(header_buffer);
FIXBuffer header_buffer (&_msg_header_template[0],_msg_header_template.size ());
FIXFragment header (header_buffer);
header.add<fix::BeginString>("FIX.4.2");
// We cannot include body lenght and msg type in the header
// because message type is not fixed lenght, and therefore its
// not possible to have bookmarks to fields after it, ahead of
// knowing the message type value. The rest of the header is
// fixed lenght so we form it here.
_seq_num_bm = header.add<fix::MsgSeqNum>(0, 9);
_last_seq_num_bm = header.add<fix::LastSeqNumProcessed>(0, 9);
_body_length_bm = header.add<fix::BodyLength>(0,6);
_msg_type_bm = header.add<fix::MsgType>(" ",1);
_seq_num_bm = header.add<fix::MsgSeqNum>(0,9);
_last_seq_num_bm = header.add<fix::LastSeqNumProcessed>(0,9);
_sending_time_bm = header.add<SendingTimeStr>(
"20150427-19:05:18.923", sizeof("20150427-19:05:18.923") - 1);
"20150427-19:05:18.923",sizeof("20150427-19:05:18.923")-1);
header.add<fix::SenderCompID>(cfg.sender_compid());
header.add<fix::TargetCompId>(cfg.target_compid());
header.add<fix::TargetSubID>(cfg.target_subid());
_header_template_size = header.size();
_header_template_checksum = header.checksum();
header.add<fix::SenderCompID>(cfg.sender_compid ());
header.add<fix::TargetCompId>(cfg.target_compid ());
header.add<fix::TargetSubID>(cfg.target_subid ());
_header_template_size = header.size ();
_header_template_checksum = header.checksum ();
}
inline FIXFragment &new_msg(MessageTypes type) {
bts_assert(_state == State::OPEN);
tidy_last_msg();
auto msg_offset = _buffer.size();
_current_msg = FIXFragment(_buffer);
_begin_string_bm = _current_msg.add<fix::BeginString>("FIX.4.2");
_body_length_bm = _current_msg.add<fix::BodyLength>(0, 6);
char mt_encoding[4];
auto start = encode_message_type(type, mt_encoding);
_msg_type_bm = _current_msg.add<fix::MsgType>(
mt_encoding + start, sizeof(mt_encoding) - start);
auto header_offset = _buffer.size();
_message_map.emplace_back(msg_offset, header_offset, 0u, 0u, 0u,
FIXFragment::Bookmark<IntField<10u>>());
_current_msg.append(&_msg_header_template[0], _header_template_size,
_header_template_checksum);
inline FIXFragment &new_msg (MessageTypes type)
{
bts_assert (_state == State::OPEN);
tidy_last_msg ();
auto msg_offset = _buffer.size ();
_message_map.emplace_back (msg_offset,0u,0u,0u,FIXFragment::Bookmark<IntField<10u>>());
_current_msg = FIXFragment (_buffer);
_current_msg.append (&_msg_header_template[0],
_header_template_size,
_header_template_checksum);
char msg_type_str[1] = {(char) type};
_current_msg.overwrite (_msg_type_bm.shift (msg_offset),msg_type_str,1);
return _current_msg;
}
inline void close() {
bts_assert(_state == State::OPEN);
tidy_last_msg();
inline void close ()
{
bts_assert (_state == State::OPEN);
tidy_last_msg ();
_state = State::CLOSED;
}
inline void reopen_empty() {
bts_assert(_state == State::CLOSED);
bts_assert(_message_map.empty());
inline void reopen_empty ()
{
bts_assert (_state == State::CLOSED);
bts_assert (_message_map.empty ());
_state = State::OPEN;
}
inline uint32_t size () const
{return _buffer.size ();}
inline uint32_t size() const { return _buffer.size(); }
inline const char* data () const
{return _buffer.data ();}
inline const char *data() const { return _buffer.data(); }
struct MessageDesc {
MessageDesc(uint32_t offset, uint32_t header_offset, uint32_t size,
uint32_t checksum, uint32_t seq_num,
FIXFragment::Bookmark<fix::Checksum> checksum_bm)
: offset(offset), header_offset(header_offset), size(size),
checksum(checksum), seq_num(seq_num), checksum_bm(checksum_bm) {}
struct MessageDesc
{
MessageDesc (uint32_t offset,
uint32_t size,
uint32_t checksum,
uint32_t seq_num,
FIXFragment::Bookmark<fix::Checksum> checksum_bm)
: offset (offset),
size (size),
checksum (checksum),
seq_num (seq_num),
checksum_bm (checksum_bm)
{}
uint32_t offset;
uint32_t header_offset;
uint32_t size;
uint32_t checksum;
uint32_t seq_num;
FIXFragment::Bookmark<fix::Checksum> checksum_bm;
};
std::string to_str() const {
std::string to_str () const
{
std::string result;
if (size()) {
if (size ()) {
// return std::string(data(),size() is simpler but valgrind
// reports a warning in that call
result.resize(size());
std::copy(data(), data() + size(), result.begin());
result.resize (size ());
std::copy (data (), data ()+size(),result.begin ());
}
return result;
}
std::string to_human_str() const {
auto s = to_str();
std::replace(s.begin(), s.end(), '\001', '|');
std::string to_human_str () const
{
auto s = to_str ();
std::replace( s.begin(), s.end(), '\001', '|' );
return s;
}
inline uint32_t stamp(uint32_t seq_num, uint32_t last_processed,
std::string const &time_str) {
bts_assert(_state == State::CLOSED);
inline uint32_t stamp (uint32_t seq_num,uint32_t last_processed, std::string const&time_str)
{
bts_assert (_state == State::CLOSED);
_state = State::STAMPED;
for (auto &m : _message_map) {
++seq_num;
m.seq_num = seq_num;
FIXFragment frag(_buffer, m.checksum);
frag.overwrite(_seq_num_bm.shift(m.header_offset), m.seq_num, 9);
frag.overwrite(_last_seq_num_bm.shift(m.header_offset), last_processed,
9);
frag.overwrite(_sending_time_bm.shift(m.header_offset), time_str);
frag.overwrite_checksum(m.checksum_bm, frag.checksum() % 256);
FIXFragment frag (_buffer,m.checksum);
frag.overwrite (_seq_num_bm.shift (m.offset),m.seq_num,9);
frag.overwrite (_last_seq_num_bm.shift (m.offset),last_processed,9);
frag.overwrite (_sending_time_bm.shift (m.offset),time_str);
frag.overwrite_checksum (m.checksum_bm,frag.checksum () % 256);
}
return seq_num;
}
inline void reset() {
_buffer.reset();
_message_map.clear();
inline void reset ()
{
_buffer.reset ();
_message_map.clear ();
_state = State::OPEN;
}
inline bool is_closed() const { return _state == State::CLOSED; }
inline bool is_closed () const
{return _state == State::CLOSED;}
size_t n_msgs() const { return _message_map.size(); }
std::vector<MessageDesc> const &msg_map() const { return _message_map; }
private:
std::array<char, 256> _msg_header_template;
size_t n_msgs () const {return _message_map.size ();}
std::vector<MessageDesc> const &msg_map () const {return _message_map;}
private:
std::array<char,256> _msg_header_template;
uint32_t _header_template_size;
uint32_t _header_template_checksum;
FIXBuffer _buffer;
std::vector<MessageDesc> _message_map;
FIXFragment _current_msg;
enum class State { OPEN, CLOSED, STAMPED };
enum class State { OPEN,CLOSED,STAMPED};
State _state;
// These bookmarks point to the current msg (not the header)
FIXFragment::Bookmark<fix::BeginString> _begin_string_bm;
FIXFragment::Bookmark<fix::BodyLength> _body_length_bm;
FIXFragment::Bookmark<fix::MsgType> _msg_type_bm;
// These bookmarks point to the header and thus have to be shifted
// by the offset of the end of the message type.
FIXFragment::Bookmark<fix::MsgSeqNum> _seq_num_bm;
FIXFragment::Bookmark<fix::LastSeqNumProcessed> _last_seq_num_bm;
typedef StringField<fix::SendingTime::tag> SendingTimeStr;
FIXFragment::Bookmark<SendingTimeStr> _sending_time_bm;
inline void tidy_last_msg() {
if (_message_map.size()) {
auto &this_msg_map = _message_map.back();
auto start = _msg_type_bm.offset - fix::MsgType::tag_sz - 1;
auto end = _buffer.size();
_current_msg.overwrite(_body_length_bm, end - start, 6);
this_msg_map.checksum = _current_msg.checksum();
this_msg_map.checksum_bm = _current_msg.add_checksum(0);
this_msg_map.size = _buffer.size() - this_msg_map.offset;
inline void tidy_last_msg ()
{
if (_message_map.size ()) {
auto &this_msg_map = _message_map.back ();
auto start =
this_msg_map.offset + _msg_type_bm.offset - fix::MsgType::tag_sz-1;
auto end = _buffer.size ();
_current_msg.overwrite (_body_length_bm.shift (this_msg_map.offset),
end-start,6);
this_msg_map.checksum = _current_msg.checksum ();
this_msg_map.checksum_bm = _current_msg.add_checksum (0);
this_msg_map.size = _buffer.size () - this_msg_map.offset;
}
}
uint32_t encode_message_type(MessageTypes m, char out[4]) {
auto mt = (uint32_t)m;
for (int i = 0; i < 4; i++) {
out[i] = mt >> (8 * (3 - i));
mt &= ((1 << (8 * (3 - i))) - 1);
}
for (int i = 0; i < 4; i++)
if (out[i])
return i;
return 0;
}
};
} // namespace jetfix
} // namespace bts
}}
-36
View File
@@ -69,9 +69,6 @@ typedef StringField<143> TargetLocationID;
typedef StringField<1603> ApplicationSystemName;
typedef StringField<1604> ApplicationSystemVersion;
typedef StringField<1605> ApplicationSystemVendor;
typedef StringField<9450> ICEApplicationSystemName;
typedef StringField<9451> ICEApplicationSystemVersion;
typedef StringField<9452> ICEApplicationSystemVendor;
typedef StringField<167> SecurityType;
typedef StringField<17> ExecID;
typedef StringField<19> ExecRefID;
@@ -100,7 +97,6 @@ typedef StringField<7928> SelfMatchPreventionID;
typedef StringField<8> BeginString;
typedef StringField<9324> OrderOptionalData;
typedef StringField<96> RawData;
typedef StringField<553> UserName;
typedef StringField<9717> CorrelationClOrdID;
typedef StringField<9771> MMAccount;
typedef TimeField<122> OrigSendingTime;
@@ -108,38 +104,6 @@ typedef TimeField<52> SendingTime;
typedef TimeField<5979> RequestTime;
typedef TimeField<60> TransactTime;
//ICE
typedef IntField<9208> Int_CtiCode;
typedef BigIntField<11> Int_ClOrdID;
typedef BigIntField<37> Int_OrderID;
typedef BigIntField<41> Int_OrigClOrdID;
typedef IntField<109> CompanyID;
typedef IntField<55> Int_Symbol;
typedef IntField<439> Int_ClearingFirm;
typedef StringField<9121> Memo;
typedef IntField<103> OrdRejReason;
typedef IntField<285> DeleteReason;
typedef CharField<9195> AccountCode;
typedef StringField<9207> CustomerAccountRefId;
typedef StringField<115> OnBehalfOfCompID;
typedef StringField<116> OnBehalfOfSubID;
typedef StringField<144> OnBehalfOfLocationID;
typedef StringField<9139> OriginatorUserID;
typedef CharField<18> ExecInst;
typedef IntField<210> MaxShow;
typedef IntField<9006> ICEStrategyPreference;
typedef IntField<9007> ICETimeStampPreference;
typedef StringField<1031> CustOrderHandlingInst;
typedef IntField<9700> MifidDirectElectronicAccess;
typedef IntField<9701> MifidTradingCapacity;
typedef IntField<9702> MifidLiquidityProvision;
typedef IntField<9703> MifidCommodityDerivIndicator;
typedef BigIntField<9704> MifidInvestmentDecision;
typedef BigIntField<9705> MifidExecutionDecision;
typedef BigIntField<9706> MifidClientIDCode;
typedef BigIntField<9707> MifidId;
typedef Group<NoQuoteEntries,
QuoteEntryID,
Symbol,
-27
View File
@@ -156,33 +156,6 @@ public:
}
};
template <uint16_t tag>
class BigIntField : public BaseField<tag,int64_t>
{
public:
typedef BaseField<tag,int64_t> Parent;
void read (ReaderCursor &cursor)
{
auto loc = cursor.read_field ();
Parent::_value = atoll (&(cursor.data ()[loc.first]));
}
static uint32_t max_value_size (int64_t,int pad = 0)
{
if (pad == 0)
return 20;
else
return pad;
}
static std::pair<uint32_t,uint32_t> write (char*buffer,int64_t i,int pad = 0)
{
auto written = i64_toa (i,buffer,pad);
return std::make_pair (written,sum_bytes (buffer,written));
}
};
template <uint16_t tag>
class StringField : public BaseField<tag,std::string>
{
-53
View File
@@ -66,58 +66,5 @@ typedef FIXMsg<MessageTypes::CancelReject,
CorrelationClOrdID>
CancelRejectMsg;
typedef FIXMsg<MessageTypes::ICETraderLoginResponse,
CompanyID,
UserName,
Text>
ICETraderLoginResponseMsg;
typedef FIXMsg<MessageTypes::ICETraderLogoutResponse,
CompanyID,
UserName,
Text>
ICETraderLogoutResponseMsg;
typedef FIXMsg<MessageTypes::ExecutionReport,
Int_OrderID,
Int_ClOrdID,
CompanyID,
ExecID,
ExecRefID,
ExecType,
OrdStatus,
OrdRejReason,
Int_Symbol,
Side,
OrderQty,
MaxShow,
OrdType,
Price,
StopPx,
TimeInForce,
LeavesQty,
CumQty,
AvgPx,
LastPx,
LastShares,
TransactTimeStr,
MultiLegReportingType,
ClearingAccount,
Memo,
Text,
DeleteReason,
TargetSubID,
MsgSeqNum>
ICEExecutionReportMsg;
typedef FIXMsg<MessageTypes::CancelReject,
Int_OrderID,
Int_ClOrdID,
Int_OrigClOrdID,
CXlRejReason,
Text,
Memo>
ICECancelRejectMsg;
}}}
+2 -7
View File
@@ -5,7 +5,7 @@
namespace bts {
namespace jetfix {
enum class MessageTypes : uint32_t
enum class MessageTypes
{
Advertisement = '7',
Allocation = 'J',
@@ -48,12 +48,7 @@ enum class MessageTypes : uint32_t
SettlementInstructions = 'T',
TestRequest = '1',
TradingSessionStatus = 'h',
TradingSessionStatusRequest = 'g',
ICETraderLogin = ('U' << 16) + ('C' << 8) + 'G',
ICETraderLoginResponse = ('U' << 16) + ('C' << 8) + 'I',
ICETraderLogout = ('U' << 16) + ('C' << 8) + 'H',
ICETraderLogoutResponse = ('U' << 16) + ('C' << 8) + 'J',
TradingSessionStatusRequest = 'g'
};
}}
-196
View File
@@ -259,199 +259,3 @@ inline int u32_toa(uint32_t u, char* buffer, int pad) {
}
///https://github.com/miloyip/itoa-benchmark
#define BEGIN2(n) \
do { \
int t = (n); \
if(t < 10) *p++ = '0' + t; \
else { \
t *= 2; \
*p++ = gDigitsLut[t]; \
*p++ = gDigitsLut[t + 1]; \
} \
} while(0)
#define MIDDLE2(n) \
do { \
int t = (n) * 2; \
*p++ = gDigitsLut[t]; \
*p++ = gDigitsLut[t + 1]; \
} while(0)
#define BEGIN4(n) \
do { \
int t4 = (n); \
if(t4 < 100) BEGIN2(t4); \
else { BEGIN2(t4 / 100); MIDDLE2(t4 % 100); } \
} while(0)
#define MIDDLE4(n) \
do { \
int t4 = (n); \
MIDDLE2(t4 / 100); MIDDLE2(t4 % 100); \
} while(0)
#define BEGIN8(n) \
do { \
uint32_t t8 = (n); \
if(t8 < 10000) BEGIN4(t8); \
else { BEGIN4(t8 / 10000); MIDDLE4(t8 % 10000); } \
} while(0)
#define MIDDLE8(n) \
do { \
uint32_t t8 = (n); \
MIDDLE4(t8 / 10000); MIDDLE4(t8 % 10000); \
} while(0)
#define MIDDLE16(n) \
do { \
uint64_t t16 = (n); \
MIDDLE8(t16 / 100000000); MIDDLE8(t16 % 100000000); \
} while(0)
inline int u64_toa(uint64_t value, char* p)
{
auto start = p;
if(value < 100000000) BEGIN8(value);
else if(value < 10000000000000000) { BEGIN8(value / 100000000); MIDDLE8(value % 100000000); }
else { BEGIN4(value / 10000000000000000); MIDDLE16(value % 10000000000000000); }
*p = 0;
return p-start;
}
inline int count_digits (int64_t value)
{
static auto P01 = 10ull;
static auto P02 = P01*10;
static auto P03 = P02*10;
static auto P04 = P03*10;
static auto P05 = P04*10;
static auto P06 = P05*10;
static auto P07 = P06*10;
static auto P08 = P07*10;
static auto P09 = P08*10;
static auto P10 = P09*10;
static auto P11 = P10*10;
static auto P12 = P11*10;
static auto P13 = P12*10;
static auto P14 = P13*10;
static auto P15 = P14*10;
static auto P16 = P15*10;
static auto P17 = P16*10;
static auto P18 = P17*10;
static auto P19 = P18*10;
uint64_t u = static_cast<uint64_t>(value);
if (value < 0)
u = ~u + 1;
if (u < P01) return 1;
if (u < P02) return 2;
if (u < P03) return 3;
if (u < P04) return 4;
if (u < P05) return 5;
if (u < P06) return 6;
if (u < P07) return 7;
if (u < P08) return 8;
if (u < P09) return 9;
if (u < P10) return 10;
if (u < P11) return 11;
if (u < P12) return 12;
if (u < P13) return 13;
if (u < P14) return 14;
if (u < P15) return 15;
if (u < P16) return 16;
if (u < P17) return 17;
if (u < P18) return 18;
if (u < P19) return 19;
return 20;
}
inline int count_digits (uint64_t u)
{
static auto P01 = 10ull;
static auto P02 = P01*10;
static auto P03 = P02*10;
static auto P04 = P03*10;
static auto P05 = P04*10;
static auto P06 = P05*10;
static auto P07 = P06*10;
static auto P08 = P07*10;
static auto P09 = P08*10;
static auto P10 = P09*10;
static auto P11 = P10*10;
static auto P12 = P11*10;
static auto P13 = P12*10;
static auto P14 = P13*10;
static auto P15 = P14*10;
static auto P16 = P15*10;
static auto P17 = P16*10;
static auto P18 = P17*10;
static auto P19 = P18*10;
if (u < P01) return 1;
if (u < P02) return 2;
if (u < P03) return 3;
if (u < P04) return 4;
if (u < P05) return 5;
if (u < P06) return 6;
if (u < P07) return 7;
if (u < P08) return 8;
if (u < P09) return 9;
if (u < P10) return 10;
if (u < P11) return 11;
if (u < P12) return 12;
if (u < P13) return 13;
if (u < P14) return 14;
if (u < P15) return 15;
if (u < P16) return 16;
if (u < P17) return 17;
if (u < P18) return 18;
if (u < P19) return 19;
return 20;
}
inline int i64_toa(int64_t value, char* buffer, int pad)
{
auto start = buffer;
uint64_t u = static_cast<uint64_t>(value);
if (value < 0) {
*buffer++ = '-';
u = ~u + 1;
}
if (pad)
{
auto digits = count_digits (value);
auto offset = pad - digits;
if (offset > 0)
{
auto start = buffer + offset;
while (buffer != start)
{
*buffer='0';
buffer++;
}
}
else if (offset < 0)
return 0;
}
return (buffer-start) + u64_toa(u, buffer);
}
inline int u64_toa(uint64_t u, char* buffer, int pad)
{
auto start = buffer;
if (pad)
{
auto digits = count_digits (u);
auto offset = pad - digits;
if (offset > 0)
{
auto start = buffer + offset;
while (buffer != start)
{
*buffer='0';
buffer++;
}
}
else if (offset < 0)
return 0;
}
return (buffer-start) + u64_toa(u, buffer);
}
+33 -54
View File
@@ -783,63 +783,42 @@ OutFIXPtr make_logon(uint32_t seq_num, uint32_t last_seq_num_processed,
const char *application = "O2";
#endif
if(session_cfg.platform() == bts::config::JetFIX_Connection_JetFIXPlatform_ICE ||
session_cfg.platform() == bts::config::JetFIX_Connection_JetFIXPlatform_SIMICE)
{
buffer.add<ICEApplicationSystemName>(application);
buffer.add<ICEApplicationSystemVersion>("1.0");
buffer.add<ICEApplicationSystemVendor>("BTS");
buffer.add<UserName>(session_cfg.user_name());
buffer.add<RawDataLength>(session_cfg.raw_data().size());
buffer.add<RawData>(session_cfg.raw_data());
buffer.add<EncryptMethod>(0);
buffer.add<ICEStrategyPreference>(1);
buffer.add<ICETimeStampPreference>(1);
buffer.add<ApplicationSystemName>(application);
buffer.add<ApplicationSystemVersion>("1.0");
buffer.add<ApplicationSystemVendor>("BTS");
if (session_cfg.has_trading_session_id()) {
buffer.add<fix::NoTradingSessions>(1);
buffer.add<fix::TradingSessionID>(session_cfg.trading_session_id());
}
else
{
buffer.add<ApplicationSystemName>(application);
buffer.add<ApplicationSystemVersion>("1.0");
buffer.add<ApplicationSystemVendor>("BTS");
if (session_cfg.has_udf_support_indicator())
buffer.add<fix::UDFSupportIndicator>(session_cfg.udf_support_indicator());
if (session_cfg.has_trading_session_id()) {
buffer.add<fix::NoTradingSessions>(1);
buffer.add<fix::TradingSessionID>(session_cfg.trading_session_id());
}
if (session_cfg.has_udf_support_indicator())
buffer.add<fix::UDFSupportIndicator>(session_cfg.udf_support_indicator());
if (session_cfg.use_cme_secure_logon()) {
bts_assert(session_cfg.sender_compid().size() >= 3);
auto session_id = session_cfg.sender_compid().substr(0, 3);
std::string seq_num_str(9, ' ');
i32_toa(seq_num, &seq_num_str[0], 9);
if (session_cfg.use_cme_secure_logon()) {
bts_assert(session_cfg.sender_compid().size() >= 3);
auto session_id = session_cfg.sender_compid().substr(0, 3);
std::string seq_num_str(9, ' ');
i32_toa(seq_num, &seq_num_str[0], 9);
std::string last_seq_num_str(9, ' ');
i32_toa(last_seq_num_processed, &last_seq_num_str[0], 9);
auto ld = glbx::calculate_hmac(
session_id, seq_num_str, session_cfg.sender_compid(),
session_cfg.sender_subid(), time_str, session_cfg.target_subid(),
std::to_string(session_cfg.seconds_between_hbs()),
session_cfg.sender_locationid(), last_seq_num_str, application, "1.0",
"BTS");
#ifndef BTS_EDGE
LOG(Jetfix, Info, "Canonical string for secure logon: {}", ld.canonical);
#endif
buffer.add<EncodedTextLen>(ld.access_key.size());
buffer.add<EncodedText>(ld.access_key);
buffer.add<EncryptedPasswordMethod>("CME-1-SHA-256");
buffer.add<EncryptedPasswordLen>(ld.signature.size());
buffer.add<EncryptedPassword>(ld.signature);
}
else
{
buffer.add<RawDataLength>(session_cfg.raw_data().size());
buffer.add<RawData>(session_cfg.raw_data());
if(session_cfg.user_name() != "")
buffer.add<UserName>(session_cfg.user_name());
}
std::string last_seq_num_str(9, ' ');
i32_toa(last_seq_num_processed, &last_seq_num_str[0], 9);
auto ld = glbx::calculate_hmac(
session_id, seq_num_str, session_cfg.sender_compid(),
session_cfg.sender_subid(), time_str, session_cfg.target_subid(),
std::to_string(session_cfg.seconds_between_hbs()),
session_cfg.sender_locationid(), last_seq_num_str, application, "1.0",
"BTS");
#ifndef BTS_EDGE
LOG(Jetfix, Info, "Canonical string for secure logon: {}", ld.canonical);
#endif
buffer.add<EncodedTextLen>(ld.access_key.size());
buffer.add<EncodedText>(ld.access_key);
buffer.add<EncryptedPasswordMethod>("CME-1-SHA-256");
buffer.add<EncryptedPasswordLen>(ld.signature.size());
buffer.add<EncryptedPassword>(ld.signature);
} else {
buffer.add<RawDataLength>(session_cfg.raw_data().size());
buffer.add<RawData>(session_cfg.raw_data());
}
stream.close();
+1 -2
View File
@@ -293,7 +293,7 @@ TimeStamp copy_synthetic_depth(const SyntheticStrategy& synth, size_t count, Pri
// END SYNTHETIC DEPTH
/////////////////////////////
bool MDConsumerHandle::get_last_trade(TimeStamp& time, PriceSize& trade, datetime::LLDateTime& trade_timestamp, size_t* total_volume, int* from_spread) const {
bool MDConsumerHandle::get_last_trade(TimeStamp& time, PriceSize& trade, datetime::LLDateTime& trade_timestamp, size_t* total_volume) const {
switch(_type) {
case HANDLETYPE_VOID: return false;
case HANDLETYPE_DEPTH:
@@ -303,7 +303,6 @@ bool MDConsumerHandle::get_last_trade(TimeStamp& time, PriceSize& trade, datetim
if (result) {
trade_timestamp = pcold->last_trade_time;
if (total_volume) { *total_volume = pcold->total_volume; }
if (from_spread) { *from_spread = pcold->from_spread; }
}
return result;
}
+1 -1
View File
@@ -239,7 +239,7 @@ public:
return get_book(read_combined, time, copydepth, bids, asks);
}
bool get_last_trade(TimeStamp& time, PriceSize& out_trade, datetime::LLDateTime& out_trade_timestamp, size_t* total_volume=nullptr,int* from_spread=nullptr) const;
bool get_last_trade(TimeStamp& time, PriceSize& out_trade, datetime::LLDateTime& out_trade_timestamp, size_t* total_volume=nullptr) const;
IntPrice settlement_price() const {
switch(_type) {
+4 -13
View File
@@ -101,9 +101,8 @@ void MDProducerHandle::set_status(CoconutSecurityStatus status) {
}
}
void MDProducerHandle::add_trade(TimeStamp time, const PriceSize price, LLDateTime tradetime,
co2::AggressorSide agside, uint32_t volume, bool from_spread) {
// Add this trade to the last trade if price/side match
void MDProducerHandle::add_trade(TimeStamp time, const PriceSize price, LLDateTime tradetime, co2::AggressorSide agside, uint32_t volume) {
// Add this trade to the last trade if price match
auto current = std::get<PriceSize>(cdata().last_trade.load());
if (current.int_price() == price.int_price()) {
cdata().last_trade.store(PriceSize { price.int_price(), price.size() + current.size() }, time);
@@ -112,9 +111,7 @@ void MDProducerHandle::add_trade(TimeStamp time, const PriceSize price, LLDateTi
cdata().last_trade.store(price,time);
}
cdata().last_trade_time = tradetime;
cdata().from_spread = (from_spread ? 1 : 0);
if (volume > 0)
cdata().total_volume = volume;
cdata().total_volume = volume;
if (key() != invalid_security_key) {
co2::TradeMessage trade;
@@ -128,15 +125,9 @@ void MDProducerHandle::add_trade(TimeStamp time, const PriceSize price, LLDateTi
_channel.add_trade(trade);
}
}
void MDProducerHandle::set_last_trade(TimeStamp time, const PriceSize ps, datetime::LLDateTime tradetime, uint32_t total_volume, bool from_spread) {
void MDProducerHandle::set_last_trade(TimeStamp time, const PriceSize ps, datetime::LLDateTime tradetime, uint32_t total_volume) {
cdata().last_trade.store(ps,time);
cdata().last_trade_time = tradetime;
cdata().from_spread = (from_spread ? 1 : 0);
if(total_volume > 0)
cdata().total_volume = total_volume;
}
void MDProducerHandle::set_total_volume(uint32_t total_volume) {
cdata().total_volume = total_volume;
}
+2 -4
View File
@@ -92,11 +92,9 @@ 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,
co2::AggressorSide agside, uint32_t total_volume=0, bool from_spread=false); // 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=0,bool from_spread=false);
void set_total_volume(uint32_t total_volume);
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
void update_exchange_status(TimeStamp time, TradingStatus status); // cold
+22 -35
View File
@@ -90,7 +90,7 @@ void add_symbols_to_result(
size_t get_system_md_symbols(api::Venue exchange, SecurityType type,
std::set<UserSymbol> &result) {
bts_assert(config::system_symbols::Symbols::descriptor()->field_count() == 4);
bts_assert(config::system_symbols::Symbols::descriptor()->field_count() == 3);
{
auto const &e = config::get<config::system_symbols::Symbols>().glbx();
if (exchange == api::VENUE_UNSET || exchange == api::VENUE_GLBX) {
@@ -146,47 +146,34 @@ size_t get_system_md_symbols(api::Venue exchange, SecurityType type,
{
auto const &e = config::get<config::system_symbols::Symbols>().sim();
if (exchange == api::VENUE_UNSET || exchange == api::VENUE_SIM)
{
if (type == api::SECURITYTYPE_FUTURE || type == api::SECURITYTYPE_UNSET)
add_symbols_to_result(e.future(), api::VENUE_SIM, api::SECURITYTYPE_FUTURE, &result);
if (type == api::SECURITYTYPE_OPTION || type == api::SECURITYTYPE_UNSET)
add_symbols_to_result(e.option(), api::VENUE_SIM, api::SECURITYTYPE_OPTION, &result);
if (type == api::SECURITYTYPE_SPREAD || type == api::SECURITYTYPE_UNSET)
add_symbols_to_result(e.spread(), api::VENUE_SIM, api::SECURITYTYPE_SPREAD, &result);
if (exchange == api::VENUE_UNSET || exchange == api::VENUE_SIM) {
if (type == api::SECURITYTYPE_FUTURE ||
type == api::SECURITYTYPE_UNSET) {
add_symbols_to_result(e.future(), api::VENUE_SIM,
api::SECURITYTYPE_FUTURE, &result);
}
if (type == api::SECURITYTYPE_OPTION ||
type == api::SECURITYTYPE_UNSET) {
add_symbols_to_result(e.option(), api::VENUE_SIM,
api::SECURITYTYPE_OPTION, &result);
}
if (type == api::SECURITYTYPE_SPREAD ||
type == api::SECURITYTYPE_UNSET) {
add_symbols_to_result(e.spread(), api::VENUE_SIM,
api::SECURITYTYPE_SPREAD, &result);
}
}
if (exchange == api::VENUE_BTS || exchange == api::VENUE_UNSET)
{
if (exchange == api::VENUE_BTS || exchange == api::VENUE_UNSET) {
std::set<std::string> all_symbols;
all_symbols.insert(e.future().begin(), e.future().end());
all_symbols.insert(e.option().begin(), e.option().end());
all_symbols.insert(e.spread().begin(), e.spread().end());
for (const auto &symbol : all_symbols)
result.insert(UserSymbol(symbol, api::VENUE_BTS, api::SECURITYTYPE_SYNTHETIC));
for (const auto &symbol : all_symbols) {
result.insert(UserSymbol(symbol, api::VENUE_BTS,
api::SECURITYTYPE_SYNTHETIC));
}
}
}
{
auto const &e = config::get<config::system_symbols::Symbols>().simice();
if (exchange == api::VENUE_UNSET || exchange == api::VENUE_SIMICE)
{
if (type == api::SECURITYTYPE_FUTURE || type == api::SECURITYTYPE_UNSET)
add_symbols_to_result(e.future(), api::VENUE_SIMICE, api::SECURITYTYPE_FUTURE, &result);
if (type == api::SECURITYTYPE_OPTION || type == api::SECURITYTYPE_UNSET)
add_symbols_to_result(e.option(), api::VENUE_SIMICE, api::SECURITYTYPE_OPTION, &result);
if (type == api::SECURITYTYPE_SPREAD || type == api::SECURITYTYPE_UNSET)
add_symbols_to_result(e.spread(), api::VENUE_SIMICE, api::SECURITYTYPE_SPREAD, &result);
}
if (exchange == api::VENUE_BTS || exchange == api::VENUE_UNSET)
{
std::set<std::string> all_symbols;
all_symbols.insert(e.future().begin(), e.future().end());
all_symbols.insert(e.option().begin(), e.option().end());
all_symbols.insert(e.spread().begin(), e.spread().end());
for (const auto &symbol : all_symbols)
result.insert(UserSymbol(symbol, api::VENUE_BTS, api::SECURITYTYPE_SYNTHETIC));
}
}
return result.size();
}
+7 -13
View File
@@ -31,9 +31,8 @@ FixedSecurity::FixedSecurity() :
cme_main_fraction(0),
cme_sub_fraction(0),
cme_price_display_format(0),
ice_price_denominator(0),
ice_deal_denominator(0),
ice_settle_denominator(0),
ice_deal_display_factor(0),
ice_settle_display_factor(0),
_symbol(),
_cfi_code(),
_security_desc(),
@@ -100,10 +99,7 @@ void write_leg_descriptor(std::ostringstream& result, char separator, const api:
std::string security_descriptor(const api::Security& security) {
const char separator = ' ';
std::ostringstream result;
if(security.exchange() == Venue::VENUE_ICE || security.exchange() == Venue::VENUE_SIMICE)
result << security.ice().security_desc() << separator << Venue_Name(security.exchange());
else
result << security.symbol() << separator << Venue_Name(security.exchange());
result << security.symbol() << separator << Venue_Name(security.exchange());
switch(security.Contract_case()) {
case Security::ContractCase::kOption: {
result << separator;
@@ -185,9 +181,8 @@ void convert_security(const FixedSecurity& source, Security* presult) {
case Venue::VENUE_ICE:
dest.mutable_ice()->set_exchange_id(source.numeric_id);
dest.mutable_ice()->set_security_desc(source.security_desc());
dest.mutable_ice()->set_price_denominator(source.ice_price_denominator);
dest.mutable_ice()->set_deal_denominator(source.ice_deal_denominator);
dest.mutable_ice()->set_settle_denominator(source.ice_settle_denominator);
dest.mutable_ice()->set_deal_display_factor(source.ice_deal_display_factor);
dest.mutable_ice()->set_settle_display_factor(source.ice_settle_display_factor);
dest.mutable_ice()->set_market_description(source.ice_market_description());
dest.mutable_ice()->set_cleared_alias(source.ice_cleared_alias());
@@ -317,9 +312,8 @@ void convert_security(const Security& src, FixedSecurity& dest, bool set_securit
case Security::ExchangeDataCase::kIce:
dest.numeric_id = src.ice().exchange_id();
dest.security_desc(src.ice().security_desc());
dest.ice_price_denominator = src.ice().price_denominator();
dest.ice_deal_denominator = src.ice().deal_denominator();
dest.ice_settle_denominator = src.ice().settle_denominator();
dest.ice_deal_display_factor = src.ice().deal_display_factor();
dest.ice_settle_display_factor = src.ice().settle_display_factor();
dest.ice_market_description(src.ice().market_description());
dest.ice_cleared_alias(src.ice().cleared_alias());
+2 -3
View File
@@ -59,9 +59,8 @@ public:
uint8_t cme_main_fraction;
uint8_t cme_sub_fraction;
uint8_t cme_price_display_format;
int8_t ice_price_denominator;
int8_t ice_deal_denominator;
int8_t ice_settle_denominator;
int8_t ice_deal_display_factor;
int8_t ice_settle_display_factor;
STRING_PROPERTY(ice_market_description);
STRING_PROPERTY(ice_cleared_alias);
+6 -8
View File
@@ -26,7 +26,7 @@ namespace md {
using utils::TimeStamp;
const uint32_t shm_version = 107;
const uint32_t shm_version = 102;
struct ALIGNED_(CACHE_LINE) HotHeader {
size_t count;
@@ -213,10 +213,9 @@ struct ColdEntry {
exchange_status(co2::TRADINGSTATUS_UNKNOWN),
last_trade(),
total_volume(0),
last_trade_time(),
last_trade_time(),
misc(),
from_spread(0),
deleted(0)
deleted(false)
{
this->security.size = security_size;
}
@@ -228,13 +227,12 @@ struct ColdEntry {
// Last Trade
AtomicPriceSize last_trade;
size_t total_volume;
size_t total_volume;
datetime::LLDateTime last_trade_time;
MiscData misc;
int from_spread;
int deleted;
bool deleted;
FixedSecurity security;
};
-5
View File
@@ -27,8 +27,6 @@ std::string ICEChannel::to_string() const
std::string mt = name;
for(const auto& x : market_types)
mt += " " + std::to_string(x);
for(const auto& x : uds_market_types)
mt += " " + std::to_string(x);
return mt;
}
@@ -47,9 +45,6 @@ const vector<ICEChannel> parse_ice_channels(const vector<UserSymbol>& symbols)
chan.symbols.insert(symbols.begin(), symbols.end());
for(const auto& xx : x.market_type())
chan.market_types.push_back(xx);
for(const auto& xx : x.uds_market_type())
chan.uds_market_types.push_back(xx);
result.push_back(chan);
}
return result;
-1
View File
@@ -13,7 +13,6 @@ struct ICEChannel
{
std::string name;
std::vector<uint32_t> market_types;
std::vector<uint32_t> uds_market_types;
std::set<UserSymbol> symbols;
std::string to_string() const;
};
-1
View File
@@ -151,7 +151,6 @@ message TradeMessage {
uint32 total_volume = 7;
bool gap = 8;
AggressorSide aggressor_side = 9;
bool from_spread = 10;
}
message QuoteRequestMessage {
enum Side {
+13 -40
View File
@@ -219,12 +219,8 @@ public:
}
// the hot part
void fill(const SecurityChannel& chan, MDConsumerGroup& group, ChannelReply* reply,
const Entitlements* entitlements, bool bypass_entitlement) const {
void fill(const SecurityChannel& chan, MDConsumerGroup& group, ChannelReply* reply, bool entitled) const {
bts_assert(reply);
bool entitled = bypass_entitlement || chan.exchange() == api::VENUE_BTS ||
(chan.exchange() == api::VENUE_GLBX && entitlements && entitlements->count(chan.symbol()));
reply->mutable_channel()->CopyFrom(chan);
reply->set_platform(group.platform);
reply->mutable_channel()->set_time(TimeStamp::now().to_uint64());
@@ -246,17 +242,9 @@ public:
ChannelUpdate* pupd = &temp_update;
pupd->set_key(instrument.handle.key());
// If the security was just discovered try to ensure all data is sent
if (instrument.discovered > TimeStamp(chan.time()))
{
auto security = handle.get_normalized_security();
pupd->mutable_security()->CopyFrom(security);
if (instrument.discovered > TimeStamp(chan.time())) {
pupd->mutable_security()->CopyFrom(handle.get_normalized_security());
snapshot = true;
if(!entitled && (chan.exchange() == api::VENUE_ICE || chan.exchange() == api::VENUE_SIMICE))
{
entitled = entitlements && entitlements->count("ICE:" + security.ice().mic_code());
if(entitled)
reply->mutable_channel()->set_entitled(entitled);
}
}
//if we are not entitled AND this is the first request since we lost our entitlement, zero out books
if (!entitled && chan.entitled() ) {
@@ -335,13 +323,12 @@ public:
TimeStamp time(snapshot ? 0 : chan.time());
PriceSize price;
datetime::LLDateTime trade_time;
size_t volume; int from_spread;
if (handle.get_last_trade(time, price, trade_time, &volume, &from_spread)) {
size_t volume;
if (handle.get_last_trade(time, price, trade_time, &volume)) {
auto* trade = pupd->mutable_last_trade();
trade->set_key(handle.key());
trade->set_time(trade_time);
trade->set_total_volume(volume);
trade->set_from_spread(from_spread);
set_price(price, trade);
}
}
@@ -386,7 +373,10 @@ public:
auto groupiter = _groups.find(UserSymbol(ch.symbol(), ch.exchange(), ch.type()));
if (groupiter != _groups.end()) {
auto& group = groupiter->second;
fill(ch, *group, reply->add_channels(), entitlements, bypass_entitlement);
bool is_entitled = bypass_entitlement ||
ch.exchange() == api::VENUE_BTS ||
(entitlements && entitlements->count(ch.symbol()));
fill(ch, *group, reply->add_channels(), is_entitled);
}
}
}
@@ -551,14 +541,10 @@ QueryServerPtr run_query_server(const bts::api::ServiceContext& ctx, MDClient& c
{
const auto& cme_symb_mics = config::get<config::CmeSymbolMics>().cme_mic();
auto entitlements = std::make_shared<std::unordered_map<uint32_t, Entitlements>>();
for (const auto& row : all_updates)
{
if (row && row->enabled())
{
for(auto mic=cme_symb_mics.begin();mic!=cme_symb_mics.end();mic++)
{
if(api::CMEMics_Name(mic->second) == row->mic())
{
for (const auto& row : all_updates) {
if (row && row->enabled()) {
for(auto mic=cme_symb_mics.begin();mic!=cme_symb_mics.end();mic++){
if(api::CMEMics_Name(mic->second) == row->mic()) {
const auto& symbol = mic->first;
auto iter = entitlements->find(row->user_id());
if (iter == entitlements->end()) {
@@ -573,19 +559,6 @@ QueryServerPtr run_query_server(const bts::api::ServiceContext& ctx, MDClient& c
}
}
}
api::ICEMics icemic;
if(api::ICEMics_Parse(row->mic(), &icemic)) //this is an ice mic, just put the mic in the set and resolve later
{
auto iter = entitlements->find(row->user_id());
if (iter == entitlements->end()) {
Entitlements ents;
ents.insert("ICE:" + row->mic());
entitlements->insert(iter, std::make_pair(row->user_id(), std::move(ents)));
}
else {
iter->second.insert("ICE:" + row->mic());
}
}
}
}
container->relay.update_entitlements(entitlements);
+1 -1
View File
@@ -86,7 +86,7 @@ class RelayProducer : public IRelayWriter {
handle.update_fixing_price(updated, misc.fixing_price());
}
if (update.has_last_trade()) {
handle.set_last_trade(updated, trade_pricesize(update.last_trade()), update.last_trade().time(), update.last_trade().total_volume(), update.last_trade().from_spread());
handle.set_last_trade(updated, trade_pricesize(update.last_trade()), update.last_trade().time(), update.last_trade().total_volume());
}
}
+1 -2
View File
@@ -87,8 +87,7 @@ extern "C" BTS_EXPORT void co2_get_sample_cold(size_t& size, ColdEntry& entry) {
entry.misc.session_high_bid = 4.4;
entry.misc.session_low_offer = 5.5;
entry.misc.fixing_price = 6.6;
entry.deleted = 1;
entry.from_spread = 0;
entry.deleted = true;
}
extern "C" BTS_EXPORT void co2_get_sample_cold_header(ColdHeader& header) {
@@ -1,4 +1,4 @@
#include "GLBXExecutionGateway.h"
#include "ExecutionGateway.h"
#include "lib/jetfix/codec/MessageDefinitions.h"
#include "lib/jetfix/common/OutFIX.h"
#include "lib/jetfix/gateway/JetFIXGateway.h"
@@ -24,7 +24,7 @@ using JFGw =
JetFIXGateway<fix::ExecutionReportMsg, fix::BusinessMessageRejectMsg,
fix::RejectMsg, fix::CancelRejectMsg>;
struct GLBXExecutionGateway::PImpl {
struct ExecutionGateway::PImpl {
PImpl(config::JetFIX::Connection const &cfg, trace::PerfLog &l,
md::SecurityOracle o)
: gw(cfg, l), exe_report_pool(), state(State::WAITING_FOR_SECURITIES),
@@ -46,16 +46,14 @@ struct GLBXExecutionGateway::PImpl {
md::SecurityOracle sec_oracle;
};
GLBXExecutionGateway::GLBXExecutionGateway(config::JetFIX::Connection const &cfg,
ExecutionGateway::ExecutionGateway(config::JetFIX::Connection const &cfg,
trace::PerfLog &log, md::SecurityOracle o)
: me(new PImpl(cfg, log, o)) {
me->state = State::WAITING_FOR_SECURITIES;
}
GLBXExecutionGateway::~GLBXExecutionGateway() {}
ExecutionGateway::~ExecutionGateway() {}
void GLBXExecutionGateway::on_admin_data(const mercury::Update<NewAdminDataEvent> &) {}
void GLBXExecutionGateway::on_securities(
void ExecutionGateway::on_securities(
const mercury::Update<NewSecuritiesEvent> &update) {
if (update.events) {
@@ -98,19 +96,19 @@ void GLBXExecutionGateway::on_securities(
}
}
void GLBXExecutionGateway::start() { me->gw.start(); }
void ExecutionGateway::start() { me->gw.start(); }
OnExeReport &GLBXExecutionGateway::on_exe_report() { return me->on_exe_report; }
OnExeReport &ExecutionGateway::on_exe_report() { return me->on_exe_report; }
OnGwStatusChange &GLBXExecutionGateway::on_gw_status_change() {
OnGwStatusChange &ExecutionGateway::on_gw_status_change() {
return me->on_gw_status_change;
}
OnCancelReject &GLBXExecutionGateway::on_cancel_reject() {
OnCancelReject &ExecutionGateway::on_cancel_reject() {
return me->on_cancel_reject;
}
void GLBXExecutionGateway::on_exe_report(
void ExecutionGateway::on_exe_report(
const jetfix::fix::ExecutionReportMsg &msg) {
OrderKey ok;
SecurityKey sk;
@@ -118,7 +116,7 @@ void GLBXExecutionGateway::on_exe_report(
auto scoped_log =
trace::log_scope(me->perf_log, msg.trace(),
"GLBXExecutionGateway::on_exe_report", ok.value());
"ExecutionGateway::on_exe_report", ok.value());
LOG(Latency, Info, "Started handling of execution report for order {}",
ok.value());
@@ -268,7 +266,7 @@ void GLBXExecutionGateway::on_exe_report(
}
}
void GLBXExecutionGateway::on_cancel_reject(
void ExecutionGateway::on_cancel_reject(
const jetfix::fix::CancelRejectMsg &msg) {
OrderKey ok;
SecurityKey sk;
@@ -283,7 +281,7 @@ void GLBXExecutionGateway::on_cancel_reject(
me->on_cancel_reject(ok, reject_msg);
}
void GLBXExecutionGateway::on_connection_status_change(bool is_connected) {
void ExecutionGateway::on_connection_status_change(bool is_connected) {
LOG(OrderMan, Info, "Connection state of {} changed to {}",
me->gw_name.value(),
is_connected ? std::string("connected") : std::string("disconnected"));
@@ -291,7 +289,7 @@ void GLBXExecutionGateway::on_connection_status_change(bool is_connected) {
me->on_gw_status_change(is_connected);
}
void GLBXExecutionGateway::on_business_reject(
void ExecutionGateway::on_business_reject(
jetfix::fix::BusinessMessageRejectMsg const &m) {
LOG(OrderMan, Error,
"Unexpected business reject in {} gateway . Reason: "
@@ -300,7 +298,7 @@ void GLBXExecutionGateway::on_business_reject(
m.has<fix::Text>() ? m.get<fix::Text>() : std::string("Unknown"));
}
void GLBXExecutionGateway::on_session_reject(jetfix::fix::RejectMsg const &m) {
void ExecutionGateway::on_session_reject(jetfix::fix::RejectMsg const &m) {
LOG(OrderMan, Error,
"Unexpected reject message in {} gateway . Reason: {}. "
"This should be investigated",
@@ -308,14 +306,14 @@ void GLBXExecutionGateway::on_session_reject(jetfix::fix::RejectMsg const &m) {
m.has<fix::Text>() ? m.get<fix::Text>() : std::string("Unknown"));
}
void GLBXExecutionGateway::dispatch_incoming_fix_messages() {
void ExecutionGateway::dispatch_incoming_fix_messages() {
me->gw.dispatch_events();
}
void GLBXExecutionGateway::send_fix(jetfix::OutFIXPtr const &fix,
void ExecutionGateway::send_fix(jetfix::OutFIXPtr const &fix,
trace::CorID trace) {
auto scoped_log =
trace::log_scope(me->perf_log, trace, "GLBXExecutionGateway::send_fix");
trace::log_scope(me->perf_log, trace, "ExecutionGateway::send_fix");
me->gw.send(fix, trace);
me->gw.dispatch_events();
}
@@ -0,0 +1,53 @@
#pragma once
#include "lib/config/protos/jetfix.pb.h"
#include "lib/jetfix/codec/MessageDefinitions.h"
#include "lib/jetfix/common/OutFIXPtr.h"
#include "lib/mercury/events/Update.h"
#include "lib/orderman/orderman_utils/orderman_common.h"
#include <memory>
namespace bts {
namespace md { class SecurityOracle;}
namespace trace {struct CorID;class PerfLog;}
namespace orderman {
class NewSecuritiesEvent;
class ExecutionReport;
using OnExeReport =
std::function<void(ExecutionReport const &, trace::CorID const &)>;
using OnGwStatusChange = std::function<void(bool)>;
using OnCancelReject = std::function<void(OrderKey, std::string const &)>;
// fix execution gateway for a single FIX session
class ExecutionGateway {
public:
ExecutionGateway(config::JetFIX::Connection const &, trace::PerfLog &,
md::SecurityOracle);
~ExecutionGateway();
void start();
void dispatch_incoming_fix_messages();
void on_securities(const mercury::Update<NewSecuritiesEvent> &);
void send_fix(jetfix::OutFIXPtr const &fix, trace::CorID trace);
OnExeReport& on_exe_report();
OnGwStatusChange& on_gw_status_change();
OnCancelReject &on_cancel_reject();
private:
enum class State { WAITING_FOR_SECURITIES, READY };
struct PImpl;
std::unique_ptr<PImpl> me;
// fix gateway events
void on_exe_report(jetfix::fix::ExecutionReportMsg const &);
void on_cancel_reject(jetfix::fix::CancelRejectMsg const &);
void on_connection_status_change(bool connected);
void on_business_reject(jetfix::fix::BusinessMessageRejectMsg const &);
void on_session_reject(jetfix::fix::RejectMsg const &);
};
} // namespace orderman
} // namespace bts
+5 -60
View File
@@ -95,13 +95,12 @@ void FillStore::on_execution_report(
if (u.events) {
for (auto const &ev : *u.events) {
auto &er = *ev.data;
auto fk = fmt::format("{}:{}", er.order_key.value(),
to_str(er.exchange_fill_id));
auto is_known = me->known_fills.count(fk);
if (er.exec_type == api::orderman::EXEC_TYPE_PARTIAL_FILL ||
er.exec_type == api::orderman::EXEC_TYPE_FILL ||
er.exec_type == api::orderman::EXEC_TYPE_TRADE_CORRECT) {
er.exec_type == api::orderman::EXEC_TYPE_FILL) {
auto fk = fmt::format("{}:{}", er.order_key.value(),
to_str(er.exchange_fill_id));
auto is_known = me->known_fills.count(fk);
api::orderman::Fill fill;
if (!is_known) {
fill.set_order_key(er.order_key.value());
@@ -117,9 +116,6 @@ void FillStore::on_execution_report(
fill.set_avg_price(er.avg_price.value());
fill.set_side(er.side);
fill.set_last_shares(er.last_shares.value());
fill.set_fill_status(api::orderman::Fill::FILL_STATUS_ACTIVE);
if(er.exec_type == api::orderman::EXEC_TYPE_TRADE_CORRECT)
fill.set_fill_status(api::orderman::Fill::FILL_STATUS_CORRECTED);
fill.set_fill_key(fk);
struct timeval tv;
gettimeofday(&tv, NULL);
@@ -143,57 +139,6 @@ void FillStore::on_execution_report(
"Discarding known execution report for fill {}", fk);
} // if partial_fill or fill
}
for (auto const &ev : *u.events)
{
auto &er = *ev.data;
auto efi = to_str(er.exchange_fill_id);
if(std::count(efi.begin(), efi.end(), ':') > 0)
{
auto cpos = efi.find_last_of(':');
efi = efi.substr(0, cpos);
ExchangeFillID temp;
str_to(efi, &temp);
efi = to_str(temp);
}
if(efi == "")
continue;
auto fk = fmt::format("{}:{}", er.order_key.value(), efi);
auto is_known = me->known_fills.count(fk);
if(er.exec_type == api::orderman::EXEC_TYPE_TRADE_CANCEL)
{
auto data = me->store->retrieve_one(fills_ns, fk);
Fill existing_fill;
if(is_known && data.first && utils::pb::from_string(data.second, &existing_fill))
{
existing_fill.set_fill_status(api::orderman::Fill::FILL_STATUS_BUSTED);
auto fv = utils::pb::to_string(existing_fill);
me->store->update(fills_ns, fk, fv);
publish(me->fill_stream, existing_fill, *er.security);
}
else
LOG(OrderMan, Warn, "Received bust for unknown fill {}", fk);
}
else if(er.exec_type == api::orderman::EXEC_TYPE_TRADE_CORRECT)
{
auto data = me->store->retrieve_one(fills_ns, fk);
Fill existing_fill;
if(is_known && data.first && utils::pb::from_string(data.second, &existing_fill))
{
existing_fill.set_fill_status(api::orderman::Fill::FILL_STATUS_CORRECTED);
existing_fill.set_last_price(er.last_price.value());
existing_fill.set_avg_price(er.avg_price.value());
existing_fill.set_side(er.side);
existing_fill.set_last_shares(er.last_shares.value());
auto fv = utils::pb::to_string(existing_fill);
me->store->update(fills_ns, fk, fv);
publish(me->fill_stream, existing_fill, *er.security);
}
else
LOG(OrderMan, Warn, "Received correction for unknown fill {}", fk);
}
} // for loop
} // if u.events
}
@@ -1,41 +0,0 @@
#pragma once
#include "IExecutionGateway.h"
namespace bts {
namespace orderman {
// fix execution gateway for a single FIX session
class GLBXExecutionGateway : public IExecutionGateway {
public:
GLBXExecutionGateway(config::JetFIX::Connection const &, trace::PerfLog &,
md::SecurityOracle);
virtual ~GLBXExecutionGateway();
void start() override;
void dispatch_incoming_fix_messages() override;
void on_securities(const mercury::Update<NewSecuritiesEvent> &) override;
void on_admin_data(const mercury::Update<NewAdminDataEvent> &) override;
void send_fix(jetfix::OutFIXPtr const &fix, trace::CorID trace) override;
OnExeReport& on_exe_report() override;
OnGwStatusChange& on_gw_status_change() override;
OnCancelReject &on_cancel_reject() override;
private:
BTS_NO_COPY(GLBXExecutionGateway);
enum class State { WAITING_FOR_SECURITIES, READY };
struct PImpl;
std::unique_ptr<PImpl> me;
// fix gateway events
void on_exe_report(jetfix::fix::ExecutionReportMsg const &);
void on_cancel_reject(jetfix::fix::CancelRejectMsg const &);
void on_connection_status_change(bool connected);
void on_business_reject(jetfix::fix::BusinessMessageRejectMsg const &);
void on_session_reject(jetfix::fix::RejectMsg const &);
};
} // namespace orderman
} // namespace bts
@@ -1,490 +0,0 @@
#include "ICEExecutionGateway.h"
#include "lib/jetfix/codec/MessageDefinitions.h"
#include "lib/jetfix/codec/i32_toa.h"
#include "lib/jetfix/common/OutFIX.h"
#include "lib/jetfix/gateway/JetFIXGateway.h"
#include "lib/logging/logging.h"
#include "lib/orderman/events/CancelRejectEvent.h"
#include "lib/orderman/events/GatewayStatusChangeEvent.h"
#include "lib/orderman/events/NewExecutionReportEvent.h"
#include "lib/orderman/events/NewSecuritiesEvent.h"
#include "lib/orderman/orderman_utils/fix_order_codec.h"
#include "lib/api/services/AdminService.pb.h"
#include "lib/orderman/events/NewAdminDataEvent.h"
#include "lib/tracing/bts_trace.h"
#include "lib/utils/TimeStamp.h"
#include "lib/utils/helper_macros.h"
#include "lib/utils/Dispatcher.h"
#include "lib/utils/bts_chrono.h"
#include <boost/pool/object_pool.hpp>
#include <atomic>
#include <set>
namespace bts {
namespace orderman {
using namespace jetfix;
using JFGw = JetFIXGateway<fix::ICEExecutionReportMsg, fix::BusinessMessageRejectMsg, fix::RejectMsg,
fix::ICECancelRejectMsg, fix::ICETraderLoginResponseMsg, fix::ICETraderLogoutResponseMsg>;
struct ICEExecutionGateway::PImpl
{
PImpl(const config::JetFIX::Connection &cfg, trace::PerfLog &l,
md::SecurityOracle o)
: gw(cfg, l), exe_report_pool(), state(State::WAITING_FOR_SECURITIES),
securities(), securities_by_exchange_id(), gw_name(cfg.name()),
cfg(cfg), perf_log(l), admin_data(), nusers(-1), connection_time(), exec_id_to_memo(),
sec_oracle(o)
{}
JFGw gw;
boost::object_pool<ExecutionReport> exe_report_pool;
State state;
std::unordered_map<SecurityKey::Value, api::Security const *> securities;
std::unordered_map<int64_t, api::Security const *> securities_by_exchange_id;
GatewayName gw_name;
config::JetFIX::Connection cfg;
OnExeReport on_exe_report;
OnGwStatusChange on_gw_status_change;
OnCancelReject on_cancel_reject;
trace::PerfLog &perf_log;
api::admin::AdminData admin_data;
std::atomic<int> nusers;
TimeStamp connection_time;
std::unordered_map<std::string, std::string> exec_id_to_memo; //for the bullshit adjusts
md::SecurityOracle sec_oracle;
};
ICEExecutionGateway::ICEExecutionGateway(const config::JetFIX::Connection &cfg, trace::PerfLog &log, md::SecurityOracle o)
: IExecutionGateway(), me(new PImpl(cfg, log, o))
{
me->state = State::WAITING_FOR_ADMIN;
}
ICEExecutionGateway::~ICEExecutionGateway() {}
void ICEExecutionGateway::on_admin_data(const mercury::Update<NewAdminDataEvent>& update)
{
if (update.events)
{
for (auto const &ev : *(update.events))
me->admin_data.CopyFrom(*ev.admin_data);
if (me->state == State::WAITING_FOR_ADMIN)
{
LOG(OrderMan, Warn, "Received admin data. Waiting for securities {}", me->gw_name.value());
me->state = State::WAITING_FOR_SECURITIES;
}
}
}
void ICEExecutionGateway::on_securities(const mercury::Update<NewSecuritiesEvent> &update)
{
if (update.events)
{
for (auto const &ev : *(update.events))
{
auto sec_ptr = ev.security;
me->securities[sec_ptr->id()] = sec_ptr;
if(sec_ptr->has_ice())
me->securities_by_exchange_id[sec_ptr->ice().exchange_id()] = sec_ptr;
}
if (me->state == State::WAITING_FOR_SECURITIES)
{
LOG(OrderMan, Warn, "Received first set of {} securities. Beginning wait 2s for trader login {}",
update.events->size(), me->gw_name.value());
// got our security synopsis, ready to start the GW
me->state = State::READY_TO_START_GW;
// subscribe to gateway events
me->gw.on<fix::ICEExecutionReportMsg>() = [this](auto const &msg)
{
this->on_exe_report(msg);
};
me->gw.on<fix::ICECancelRejectMsg>() = [this](auto const &msg)
{
this->on_cancel_reject(msg);
};
me->gw.on_ready() = [this]()
{
this->on_connection_status_change(true);
};
me->gw.on_disconnect() = [this]()
{
this->on_connection_status_change(false);
};
me->gw.on<fix::BusinessMessageRejectMsg>() = [this](auto const &m)
{
this->on_business_reject(m);
};
me->gw.on<fix::RejectMsg>() = [this](auto const &m)
{
this->on_session_reject(m);
};
}
}
}
void ICEExecutionGateway::start()
{
me->gw.start();
bts_assert_msg(me->state == State::READY_TO_START_GW, "ICEExecutionGateway statemachine failure");
}
void ICEExecutionGateway::on_connection_status_change(bool is_connected)
{
LOG(OrderMan, Info, "Connection state of {} changed to {}",
me->gw_name.value(), is_connected ? std::string("connected") : std::string("disconnected"));
if(is_connected && me->state == State::READY_TO_START_GW)
{
me->state = State::TRADER_LOGIN_TIMEOUT;
me->connection_time = Timer::now();
}
if(me->state == State::READY)
{
me->on_gw_status_change(is_connected);
if(!is_connected) //if we disconnect, set state so we log in again
me->state = State::READY_TO_START_GW;
}
}
void ICEExecutionGateway::on_trader_login_timeout_expired()
{
if (me->state == State::TRADER_LOGIN_TIMEOUT)
{
LOG(OrderMan, Warn, "Done waiting for login timeout, logging on traders {}", me->gw_name.value());
// got our security synopsis, ready to start the GW
me->state = State::LOGIN_TIMEOUT_COMPLETE;
me->gw.on<fix::ICETraderLoginResponseMsg>() = [&](const fix::ICETraderLoginResponseMsg& lmsg)
{
std::string u = lmsg.get<fix::UserName>();
std::string m;
if(lmsg.has<fix::Text>())
m = lmsg.get<fix::Text>();
LOG(OrderMan, Error, "Succesffully logging trader {} into ICE {} {}", u, m, me->gw_name.value());
if(--me->nusers == 0)
this->on_login();
};
me->gw.on<fix::ICETraderLogoutResponseMsg>() = [&](const fix::ICETraderLogoutResponseMsg& lmsg)
{
std::string u = lmsg.get<fix::UserName>();
std::string m;
if(lmsg.has<fix::Text>())
m = lmsg.get<fix::Text>();
LOG(OrderMan, Error, "Error logging trader {} into ICE {} {}", u, m, me->gw_name.value());
if(--me->nusers == 0)
this->on_login();
};
std::set<std::string> auth_traders;
for(const auto& u : me->admin_data.users())
{
if(u.has_user_data() && u.user_data().has_exchange_user_data() && u.user_data().exchange_user_data().has_ice_data())
{
const auto& ice = u.user_data().exchange_user_data().ice_data();
if(auth_traders.find(ice.authorized_trader()) == auth_traders.end())
{
if(me->nusers == -1)
me->nusers = 0;
me->nusers++;
auto result = std::make_shared<OutFIX>(me->cfg);
auto &stream = result->fix.back();
auto &buffer = stream.new_msg(MessageTypes::ICETraderLogin);
buffer.add<fix::CompanyID>(ice.company_id());
buffer.add<fix::UserName>(ice.authorized_trader());
buffer.add<fix::RawData>(ice.password());
if(ice.mifid_direct_electronic_access() >= 0)
buffer.add<fix::MifidDirectElectronicAccess>(ice.mifid_direct_electronic_access());
if(ice.mifid_trading_capacity() >= 0)
buffer.add<fix::MifidTradingCapacity>(ice.mifid_trading_capacity());
if(ice.mifid_liquidity_provision() >= 0)
buffer.add<fix::MifidLiquidityProvision>(ice.mifid_liquidity_provision());
if(ice.mifid_commodity_deriv_indicator() >= 0)
buffer.add<fix::MifidCommodityDerivIndicator>(ice.mifid_commodity_deriv_indicator());
if(ice.mifid_investment_decision() > 0)
buffer.add<fix::MifidInvestmentDecision>(ice.mifid_investment_decision());
if(ice.mifid_execution_decision() > 0)
buffer.add<fix::MifidExecutionDecision>(ice.mifid_execution_decision());
if(ice.mifid_client_id_code() > 0)
buffer.add<fix::MifidClientIDCode>(ice.mifid_client_id_code());
if(ice.mifid_id() > 0)
buffer.add<fix::MifidId>(ice.mifid_id());
stream.close();
trace::CorID trace;
send_fix(result, trace);
auth_traders.insert(ice.authorized_trader());
}
}
}
LOG(OrderMan, Warn, "{} traders identified as ICE traders {}", auth_traders.size(), me->gw_name.value());
}
}
void ICEExecutionGateway::on_login()
{
if (me->state == State::LOGIN_TIMEOUT_COMPLETE)
{
LOG(OrderMan, Warn, "Successful login traders {}", me->gw_name.value());
me->state = State::READY;
me->on_gw_status_change(true);
}
}
OnExeReport &ICEExecutionGateway::on_exe_report() { return me->on_exe_report; }
OnGwStatusChange &ICEExecutionGateway::on_gw_status_change()
{
return me->on_gw_status_change;
}
OnCancelReject &ICEExecutionGateway::on_cancel_reject()
{
return me->on_cancel_reject;
}
bool ICEExecutionGateway::process_memo(const jetfix::fix::ICEExecutionReportMsg &msg, OrderKey* ok, SecurityKey* sk)
{
if(msg.has<fix::Memo>())
{
decode_memo(msg.get<fix::Memo>(), ok, sk);
return true;
}
else
{
if (msg.get<fix::ExecType>() == api::orderman::EXEC_TYPE_TRADE_CORRECT && msg.has<fix::ExecRefID>())
{
std::string ref_exec_id = msg.get<fix::ExecRefID>();
auto found = me->exec_id_to_memo.find(ref_exec_id);
if(found == me->exec_id_to_memo.end())
{
auto new_price = Price(0);
if(msg.has<fix::LastPx>())
new_price = Price(msg.get<fix::LastPx>());
LOG(OrderMan, Error,
"Received unsupported trade correction msg. This correction will not be forwarded. The trader should be alerted. "
"Partial original fill id: {}. New price: {}", ref_exec_id, new_price.value());
return false;
}
else
{
decode_memo(found->second, ok, sk);
return true;
}
}
}
return false;
}
void ICEExecutionGateway::on_exe_report(const jetfix::fix::ICEExecutionReportMsg &msg)
{
OrderKey ok;
SecurityKey sk;
if(!process_memo(msg, &ok, &sk))
{
std::string execid = "";
if(msg.has<fix::ExecID>())
execid = msg.get<fix::ExecID>();
LOG(OrderMan, Error,
"Received execution report with no memo execid: {}. Will not be able to process this report. This is likely a bug that could lead "
"to lost fills. Please investigate.", execid);
return;
}
auto scoped_log = trace::log_scope(me->perf_log, msg.trace(), "ICEExecutionGateway::on_exe_report", ok.value());
LOG(Latency, Info, "Started handling of execution report for order {}", ok.value());
auto &sec = me->securities[sk.value()];
if (!sec)
{
sec = me->sec_oracle.get_security(SecurityKey(sk.value()));
}
if (!sec)
LOG(OrderMan, Error,
"Received execution report for an unknown security {}. Will not be able to process this report. This is likely a bug that could lead "
"to lost fills. Please investigate.",
sk.value());
else
{
if(sec->has_ice())
me->securities_by_exchange_id[sec->ice().exchange_id()] = sec;
api::Security const *leg_security = nullptr;
if (msg.has<fix::MultiLegReportingType>() && msg.get<fix::MultiLegReportingType>() == 2)
{
auto it = me->securities_by_exchange_id.find(msg.get<fix::Int_Symbol>());
if (it == me->securities_by_exchange_id.end())
{
LOG(OrderMan, Error,
"Received execution report for an unknown spread leg"
"security {}. Will not be able to process this report. "
"This is likely a bug that could lead to "
"lost leg fills. Please investigate. Spread sec_key: {} leg "
"exchange id: {}",
sk.value(), msg.get<fix::Int_Symbol>());
return;
}
leg_security = it->second;
}
std::string text_msg;
if (msg.has<fix::Text>())
text_msg = msg.get<fix::Text>();
if (msg.has<fix::OrdRejReason>())
text_msg += " Rejected OrdRejReason: " + std::to_string(msg.get<fix::OrdRejReason>());
if (msg.has<fix::DeleteReason>())
text_msg += " Cancelled DeleteReason: " + std::to_string(msg.get<fix::DeleteReason>());
// allocate from our pool
auto data = me->exe_report_pool.construct();
if(msg.has<fix::Memo>())
data->memo = msg.get<fix::Memo>();
data->exec_type = api::orderman::ExecType(msg.get<fix::ExecType>());
data->msg_seq_num = msg.get<fix::MsgSeqNum>();
// copy data from fix msg to our structure
if (msg.has<fix::ClearingAccount>())
str_to(msg.get<fix::ClearingAccount>(), &data->account_name);
if (msg.has<fix::TargetSubID>())
str_to(msg.get<fix::TargetSubID>(), &data->operator_id);
if (msg.has<fix::CompanyID>())
data->ice_company_id = msg.get<fix::CompanyID>();
data->order_key = ok;
data->security = sec;
data->leg_security = leg_security;
data->side = api::Side(msg.get<fix::Side>());
if (msg.has<fix::TimeInForce>())
data->time_in_force = api::orderman::TimeInForce(msg.get<fix::TimeInForce>());
else
data->time_in_force = api::orderman::TIME_IN_FORCE_UNDEFINED;
if (msg.has<fix::OrdType>())
data->order_type = api::orderman::NativeOrderType(msg.get<fix::OrdType>());
else
data->order_type = api::orderman::NATIVE_ORDER_TYPE_UNDEFINED;
data->order_status = api::orderman::NativeOrderStatus(msg.get<fix::OrdStatus>());
data->manual_order_indicator = api::orderman::MANUAL_ORDER_INDICATOR_NO;
std::string oid_string = get_ice_order_id_string(msg);
str_to(oid_string, &data->exchange_order_id);
data->ice_cl_ord_id = 0;
if(msg.has<fix::Int_ClOrdID>())
data->ice_cl_ord_id = msg.get<fix::Int_ClOrdID>();
if (msg.has<fix::Price>())
data->price = securities::decode_exchange_price(*sec, Price(msg.get<fix::Price>()));
else
data->price = Price(os::nan());
if (msg.has<fix::StopPx>())
data->stop_price = securities::decode_exchange_price(*sec, Price(msg.get<fix::StopPx>()));
else
data->stop_price = Price(os::nan());
if (msg.has<fix::MaxShow>())
data->max_show = Quantity(msg.get<fix::MaxShow>());
else
data->max_show = Quantity(0);
if (msg.has<fix::OrderQty>())
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(*last_px_sec, Price(msg.get<fix::LastPx>()))
: Price(0);
data->avg_price = msg.has<fix::AvgPx>()
? securities::decode_exchange_price(*last_px_sec, Price(msg.get<fix::AvgPx>()))
: Price(0);
if (msg.has<fix::ExecID>())
{
auto execid = msg.get<fix::ExecID>();
str_to(execid, &data->exchange_fill_id);
if(msg.has<fix::Memo>())
me->exec_id_to_memo[execid] = msg.get<fix::Memo>();
}
if (msg.has<fix::TransactTimeStr>())
{
std::string stamp = msg.get<fix::TransactTimeStr>();
stamp.resize(sizeof(mercury::TimeStampStr));
str_to(stamp, &data->transact_time);
}
data->cfg = &me->cfg;
data->msg = text_msg;
data->exchange = api::Venue::VENUE_ICE;
me->on_exe_report(*data, msg.trace());
}
}
void ICEExecutionGateway::on_cancel_reject(const jetfix::fix::ICECancelRejectMsg &msg)
{
OrderKey ok(msg.get<fix::Int_ClOrdID>());
std::string reject_msg;
if (msg.has<fix::Text>())
reject_msg = msg.get<fix::Text>();
else if (msg.has<fix::CXlRejReason>())
reject_msg = fmt::format("Order cancel was rejected with error code {}",
msg.get<fix::CXlRejReason>());
me->on_cancel_reject(ok, reject_msg);
}
void ICEExecutionGateway::on_business_reject(const jetfix::fix::BusinessMessageRejectMsg& m)
{
LOG(OrderMan, Error,
"Unexpected business reject in {} gateway . Reason: {}. This should be investigated",
me->gw_name.value(),
m.has<fix::Text>() ? m.get<fix::Text>() : std::string("Unknown"));
}
void ICEExecutionGateway::on_session_reject(const jetfix::fix::RejectMsg& m)
{
LOG(OrderMan, Error,
"Unexpected reject message in {} gateway . Reason: {}. This should be investigated",
me->gw_name.value(),
m.has<fix::Text>() ? m.get<fix::Text>() : std::string("Unknown"));
}
void ICEExecutionGateway::dispatch_incoming_fix_messages()
{
me->gw.dispatch_events();
if(me->state == State::TRADER_LOGIN_TIMEOUT && ms_diff(Timer::now(), me->connection_time) >= 2000)
{
on_trader_login_timeout_expired();
}
}
void ICEExecutionGateway::send_fix(const jetfix::OutFIXPtr& fix, trace::CorID trace)
{
auto scoped_log = trace::log_scope(me->perf_log,trace,"ICEExecutionGateway::send_fix");
me->gw.send(fix,trace);
me->gw.dispatch_events();
}
} // namespace orderman
} // namespace bts
@@ -1,45 +0,0 @@
#pragma once
#include "IExecutionGateway.h"
namespace bts {
namespace orderman {
// fix execution gateway for a single FIX session
class ICEExecutionGateway : public IExecutionGateway {
public:
ICEExecutionGateway(const config::JetFIX::Connection&, trace::PerfLog &,
md::SecurityOracle);
virtual ~ICEExecutionGateway();
void start() override;
void dispatch_incoming_fix_messages() override;
void on_securities(const mercury::Update<NewSecuritiesEvent> &) override;
void on_admin_data(const mercury::Update<NewAdminDataEvent> &) override;
void send_fix(const jetfix::OutFIXPtr& fix, trace::CorID trace) override;
OnExeReport& on_exe_report() override;
OnGwStatusChange& on_gw_status_change() override;
OnCancelReject &on_cancel_reject() override;
private:
BTS_NO_COPY(ICEExecutionGateway);
enum class State { WAITING_FOR_ADMIN, WAITING_FOR_SECURITIES, READY_TO_START_GW, TRADER_LOGIN_TIMEOUT, LOGIN_TIMEOUT_COMPLETE, READY };
struct PImpl;
std::unique_ptr<PImpl> me;
void on_trader_login_timeout_expired();
void on_login();
// fix gateway events
void on_exe_report(const jetfix::fix::ICEExecutionReportMsg&);
void on_cancel_reject(const jetfix::fix::ICECancelRejectMsg&);
void on_connection_status_change(bool connected);
void on_business_reject(const jetfix::fix::BusinessMessageRejectMsg&);
void on_session_reject(const jetfix::fix::RejectMsg&);
bool process_memo(const jetfix::fix::ICEExecutionReportMsg &msg, OrderKey*, SecurityKey*);
};
} // namespace orderman
} // namespace bts
@@ -1,20 +0,0 @@
#include "IExecutionGateway.h"
#include "ICEExecutionGateway.h"
#include "GLBXExecutionGateway.h"
namespace bts {
namespace orderman {
std::unique_ptr<IExecutionGateway>
ExecutionGatewayFactory::create_gateway(const config::JetFIX::Connection& conn, trace::PerfLog& pl, md::SecurityOracle o)
{
if(conn.platform() == bts::config::JetFIX_Connection_JetFIXPlatform_ICE ||
conn.platform() == bts::config::JetFIX_Connection_JetFIXPlatform_SIMICE)
return std::make_unique<ICEExecutionGateway>(conn, pl, o);
else
return std::make_unique<GLBXExecutionGateway>(conn, pl, o);
}
} // namespace orderman
} // namespace bts
@@ -1,52 +0,0 @@
#pragma once
#include "lib/config/protos/jetfix.pb.h"
#include "lib/jetfix/codec/MessageDefinitions.h"
#include "lib/jetfix/common/OutFIXPtr.h"
#include "lib/md/SecurityOracle.h"
#include "lib/mercury/events/Update.h"
#include "lib/orderman/orderman_utils/orderman_common.h"
#include "lib/utils/bts_no_copy.h"
#include <memory>
namespace bts {
namespace trace {struct CorID;class PerfLog;}
namespace orderman {
class NewSecuritiesEvent;
class NewAdminDataEvent;
class ExecutionReport;
using OnGwStatusChange = std::function<void(bool)>;
using OnExeReport = std::function<void(ExecutionReport const &, trace::CorID const &)>;
using OnCancelReject = std::function<void(OrderKey, std::string const &)>;
// fix execution gateway for a single FIX session
class IExecutionGateway {
public:
IExecutionGateway() = default;
virtual ~IExecutionGateway() {}
virtual void start() = 0;
virtual void dispatch_incoming_fix_messages() = 0;
virtual void on_securities(const mercury::Update<NewSecuritiesEvent> &) = 0;
virtual void on_admin_data(const mercury::Update<NewAdminDataEvent> &) = 0;
virtual void send_fix(const jetfix::OutFIXPtr&, trace::CorID) = 0;
virtual OnExeReport& on_exe_report() = 0;
virtual OnGwStatusChange& on_gw_status_change() = 0;
virtual OnCancelReject &on_cancel_reject() = 0;
private:
BTS_NO_COPY(IExecutionGateway);
};
class ExecutionGatewayFactory
{
public:
static std::unique_ptr<IExecutionGateway> create_gateway(const config::JetFIX::Connection&, trace::PerfLog&, md::SecurityOracle);
};
} // namespace orderman
} // namespace bts
+1 -1
View File
@@ -143,7 +143,7 @@ void SODPosition::_zero_pos(Fill &pos, const Fill &fill, api::Side side) {
}
bool SODPosition::add_fill_to_sod_pos(const Fill &fill) {
if (_enabled && fill.fill_status() != api::orderman::Fill::FILL_STATUS_BUSTED && fill.timestamp().seconds() < _sod_time.tv_sec) {
if (_enabled && fill.timestamp().seconds() < _sod_time.tv_sec) {
if (!bts::admin::AdminServiceUtils::has_id(fill.internal_account_id())){
LOG(persist, Error, "SODPosition::add_fill_to_sod_pos Could not find "
"account_id for fill:{} account:{}",
@@ -15,7 +15,6 @@
#include "lib/orderman/orders/Order.h"
#include "lib/orderman/securities/ISecurityDB.h"
#include "lib/utils/inplace_function.h"
#include "lib/utils/thread_manager.h"
#include <algorithm>
#include <boost/algorithm/string/trim.hpp>
@@ -45,28 +44,12 @@ struct OrderManager::PImpl {
mercury::Actor::SubHandle stored_fills_sub;
OrderServicesData services_data;
mercury::Stream<OrderManagerReadyEvent> pub_ready;
std::thread background_thread;
std::atomic<bool> shutdown = false;
};
OrderManager::OrderManager(DynamicOrderRegistry const &b, trace::PerfLog &l,
md::SecurityOracle o)
: me(new PImpl(*this, b, l, o)) {
auto id_gen = &me->services_data.id_gen;
auto done = &me->shutdown;
me->background_thread =
threading::make_thread("oman_background", [id_gen, done]() {
while (!(*done)) {
id_gen->refill();
sleep_for(10ms);
}
});
}
OrderManager::~OrderManager() {
me->shutdown = true;
me->background_thread.join();
}
: me(new PImpl(*this, b, l, o)) {}
OrderManager::~OrderManager() {}
void OrderManager::init() {
subscribe<NewAdminDataEvent>(
@@ -80,13 +63,11 @@ void OrderManager::init() {
void OrderManager::on_admin_data(const mercury::Update<NewAdminDataEvent> &m) {
if (m.events) {
if (me->state == State::WAIT_ADMIN) {
LOG(OrderMan, Info,
"Order manager received admin data. Subscribing to security list "
"now ");
for (auto &osd : me->services_data.sessions)
osd->gw->on_admin_data(m);
"Order manager received admin data. Subscribing "
"to security list now ");
me->state = State::WAIT_SEC;
subscribe<NewSecuritiesEvent>([this](auto const &sec_update) {
this->on_securities(sec_update);
@@ -119,7 +100,7 @@ void OrderManager::on_securities(
// forward to execution gateways
for (auto &osd : me->services_data.sessions)
osd->gw->on_securities(update);
osd->gw.on_securities(update);
if (update.events) {
@@ -463,20 +444,19 @@ void OrderManager::init_order_services() {
// reject evets
auto s_ptr = s.get();
s->exe_report_pub = make_stream<NewExecutionReportEvent>(gw_name);
s->gw->on_exe_report() = [s_ptr, this](auto const &er, auto const &t) {
s->gw.on_exe_report() = [s_ptr, this](auto const &er, auto const &t) {
publish(s_ptr->exe_report_pub, &er, t);
};
s->gw_status_change_pub = make_stream<GatewayStatusChangeEvent>(gw_name);
s->gw->on_gw_status_change() = [s_ptr, this, gw_name](bool b) {
s->gw.on_gw_status_change() = [s_ptr, this, gw_name](bool b) {
publish(s_ptr->gw_status_change_pub, gw_name, b);
};
s->cancel_reject_pub = make_stream<CancelRejectEvent>(gw_name);
s->gw->on_cancel_reject() = [s_ptr, this](auto const &k,
auto const &msg) {
s->gw.on_cancel_reject() = [s_ptr, this](auto const &k, auto const &msg) {
publish(s_ptr->cancel_reject_pub, k, msg);
};
// handlers are ready so we can start processing fix events
s->gw->start();
s->gw.start();
reload_fix_buffer(*s);
}
@@ -559,7 +539,7 @@ void OrderManager::after_event() {
auto scoped_do_work = trace::log_scope(me->services_data.log, {},
"OrderManager::after_event");
fix_stream.close();
osd->gw->send_fix(osd->current_buffer, osd->current_trace);
osd->gw.send_fix(osd->current_buffer, osd->current_trace);
reload_fix_buffer(*osd);
}
}
@@ -584,7 +564,7 @@ void OrderManager::on_poll(trace::PerfLog &log) {
trace::log_scope(log, {}, "OrderManager::dispatch_incoming_fix_messages",
utils::TimeStamp::Interval::from_microseconds(2));
for (auto &osd : me->services_data.sessions)
osd->gw->dispatch_incoming_fix_messages();
osd->gw.dispatch_incoming_fix_messages();
}
void OrderManager::publish_order_def_update(
@@ -46,9 +46,6 @@ class OrderServices {
return ss.is_gateway_connected();
}
uint64_t gen_id() {
return _data->id_gen.next();
}
Governor &governor(SessionServices &ss) { return ss.governor(); }
void queue_fix(SessionServices &ss, jetfix::MessageTypes mt,
@@ -12,9 +12,7 @@ OrderServicesData::OrderServicesData(OrderManager &owner,
order_factory(sec_db, order_router, b),
last_timer_ev(
Timer::now(),
to<mercury::TimeStampStr>(datetime::FIX_timestamp(datetime::now()))),
id_gen("orderman_ids",5000)
{
to<mercury::TimeStampStr>(datetime::FIX_timestamp(datetime::now()))) {
auto &all_connections = config::get<config::JetFIX>().connection();
for (auto const &c : all_connections)
@@ -9,7 +9,7 @@
#include "lib/mercury/events/TimerEvent.h"
#include "lib/md/SecurityOracle.h"
#include "lib/orderman/actors/IExecutionGateway.h"
#include "lib/orderman/actors/ExecutionGateway.h"
#include "lib/orderman/events/ActivateOrderEvent.h"
#include "lib/orderman/events/BookUpdateEvent.h"
#include "lib/orderman/events/TickerUpdateEvent.h"
@@ -33,7 +33,6 @@
#include "lib/orderman/limiter/Limiter.h"
#include "lib/orderman/order_router/OrderRouter.h"
#include "lib/utils/datetime.h"
#include "lib/utils/Puid.h"
#include <boost/date_time/posix_time/posix_time.hpp>
@@ -52,10 +51,7 @@ struct SessionServicesData {
trace::PerfLog &log, md::SecurityOracle o)
: session(cfg.name()), gw_connected(false), cfg(cfg),
governor(cfg.max_order_msgs_per_window(), cfg.window_duration_msecs()),
gw(ExecutionGatewayFactory::create_gateway(cfg, log, o))
{
}
gw(cfg, log,o) {}
std::string session;
std::vector<jetfix::OutFIXPtr> free_buffers;
@@ -72,7 +68,7 @@ struct SessionServicesData {
Governor governor;
jetfix::OutFIXPtr current_buffer;
trace::CorID current_trace;
std::unique_ptr<IExecutionGateway> gw;
ExecutionGateway gw;
mercury::Stream<NewExecutionReportEvent> exe_report_pub;
mercury::Stream<GatewayStatusChangeEvent> gw_status_change_pub;
mercury::Stream<CancelRejectEvent> cancel_reject_pub;
@@ -109,8 +105,7 @@ class OrderServicesData {
mercury::Stream<OrderOpResultEvent> report_order_op_result_pub;
mercury::TimerEvent last_timer_ev;
std::vector<std::unique_ptr<SessionServicesData>> sessions;
utils::IDGenerator id_gen ;
SessionServicesData &get_session(std::string const &session_name) {
for (auto &s : sessions)
if (s->session == session_name)
@@ -57,14 +57,14 @@ class SessionServices {
_gateway_status_sub = src._gateway_status_sub;
return *this;
}
config::JetFIX::Connection const &session_cfg() const {
return _session_data->cfg;
}
protected:
std::string const &session_name() const { return _session_data->session; }
config::JetFIX::Connection const &session_cfg() const {
return _session_data->cfg;
}
void queue_fix(jetfix::MessageTypes mt, jetfix::FIXFragment const &f,
trace::CorID const &corid) {
auto &stream = _session_data->current_buffer->first_stream();
@@ -10,8 +10,7 @@
// order types
#include "lib/orderman/order_factory/DynamicOrderRegistry.h"
#include "lib/orderman/orders/DynamicOrder.h"
#include "lib/orderman/orders/GLBXNativeOrder.h"
#include "lib/orderman/orders/ICENativeOrder.h"
#include "lib/orderman/orders/NativeOrder.h"
#include "lib/orderman/orders/TimeBoxOrder.h"
#include "lib/orderman/orders/TriggerOrder.h"
#include "lib/orderman/orders/algo/AlgoWrapperOrder.h"
@@ -114,24 +113,6 @@ Order &OrderFactory::recover(api::orderman::OrderRecord const &rec) {
return order;
}
NativeOrder *OrderFactory::make_order(const api::Venue exchange) {
if (exchange == api::Venue::VENUE_ICE ||
exchange == api::Venue::VENUE_SIMICE)
return new ICENativeOrder();
else
return new GLBXNativeOrder();
}
NativeOrder *
OrderFactory::make_native_order(const api::orderman::OrderDefinition &def) {
auto secptr = me->sec_db.resolve(SecurityKey(def.security_key()));
if (secptr == nullptr)
return new GLBXNativeOrder(); // GLBX Native can handle unresolved
// securities
else
return make_order(secptr->exchange());
}
Order &OrderFactory::recreate_from_exe_report(ExecutionReport const &r) {
using namespace api::orderman;
@@ -140,7 +121,7 @@ Order &OrderFactory::recreate_from_exe_report(ExecutionReport const &r) {
case NATIVE_ORDER_TYPE_LIMIT:
case NATIVE_ORDER_TYPE_STOP:
case NATIVE_ORDER_TYPE_STOP_LIMIT: {
std::unique_ptr<NativeOrder> native_order(make_order(r.exchange));
auto native_order = std::make_unique<NativeOrder>();
native_order->_key = r.order_key;
native_order->_parent_key = null_order_key();
auto def = native_order->on_init_from_exe_report(
@@ -170,7 +151,7 @@ Order &OrderFactory::allocate(OrderKey k, OrderKey pk,
case CustomOrderDefinition::kStop:
case CustomOrderDefinition::kStopLimit:
case CustomOrderDefinition::kGlbxIceberg:
order_ptr.reset(make_native_order(def));
order_ptr.reset(new NativeOrder());
break;
case CustomOrderDefinition::kIceberg:
order_ptr.reset(
@@ -11,7 +11,6 @@ class ISecurityDB;
}
namespace orderman {
class Order;
class NativeOrder;
class DynamicOrderRegistry;
} // namespace orderman
namespace orderman {
@@ -46,8 +45,6 @@ class OrderFactory : public IOrderFactory {
private:
Order &allocate(OrderKey k, OrderKey pk,
api::orderman::OrderDefinition const &);
NativeOrder* make_order(const api::Venue exchange);
NativeOrder* make_native_order(const api::orderman::OrderDefinition& def);
struct PImpl;
std::unique_ptr<PImpl> me;
@@ -35,10 +35,6 @@ public:
mercury::TimeStampStr transact_time;
config::JetFIX::Connection const *cfg;
std::string msg;
api::Venue exchange;
int64_t ice_cl_ord_id;
int32_t ice_company_id;
std::string memo;
};
}}
@@ -7,7 +7,6 @@
#include "lib/jetfix/codec/i32_toa.h"
#include "lib/jetfix/codec/MessageDefinitions.h"
#include "lib/utils/bts_assert.h"
#include "lib/utils/base62.h"
namespace bts {
namespace api {class Security;}
@@ -18,8 +17,6 @@ constexpr int clordid_sz() {return 20;}
constexpr int price_sz() {return 17;}
constexpr int quantity_sz() {return 6;}
constexpr int max_show_sz() {return 6;}
constexpr int memo_sz() {return 12;}
constexpr int ice_orderid_sz() {return 12;}
inline void encode_clorid(OrderKey ok, SecurityKey sk,std::string *out) {
u32_toa(sk.value(),&((*out)[0]),clordid_sz()/2);
@@ -41,7 +38,8 @@ inline void decode_clorid(std::string const&in, OrderKey *ok, SecurityKey *sk)
template <class MSG>
OrderKey get_order_key(MSG const &msg)
{
{
bts_assert(msg.template has<jetfix::fix::ClOrdID> ());
OrderKey result;
SecurityKey dummy;
@@ -49,47 +47,4 @@ OrderKey get_order_key(MSG const &msg)
return result;
}
inline void encode_memo(OrderKey ok, SecurityKey sk, std::string *out)
{
auto ok_string = utils::to_base_62(ok.value());
auto sk_string = utils::to_base_62(sk.value());
bts_assert_msg(ok_string.size() == 6 && sk_string.size() == 6, "base62 encoding didn't work");
*out = ok_string + sk_string;
}
inline void decode_memo(const std::string& in, OrderKey* ok, SecurityKey* sk)
{
bts_assert(in.size() == memo_sz());
char buffer[memo_sz()/2+1];
buffer[memo_sz()/2] = 0;
std::memcpy(buffer,&in[0],memo_sz()/2);
*ok = OrderKey( utils::from_base_62(std::string(buffer)) );
std::memcpy(buffer,&in[memo_sz()/2],memo_sz()/2);
*sk = SecurityKey( utils::from_base_62(std::string(buffer)) );
}
template <class MSG>
std::string get_ice_order_id_string(const MSG& msg)
{
bts_assert(msg.template has<jetfix::fix::Int_OrderID>());
std::string oid_string(ice_orderid_sz(), ' ');
int64_t id = msg.template get<jetfix::fix::Int_OrderID>();
u64_toa(id, &(oid_string[0]), ice_orderid_sz() );
return oid_string;
}
template <class MSG>
std::string get_ice_clord_id_string(const MSG& msg)
{
bts_assert(msg.template has<jetfix::fix::Int_ClOrdID>());
std::string oid_string(ice_orderid_sz(), ' ');
int64_t id = msg.template get<jetfix::fix::Int_ClOrdID>();
u64_toa(id, &(oid_string[0]), ice_orderid_sz() );
return oid_string;
}
}}
-76
View File
@@ -1,76 +0,0 @@
#pragma once
#include "lib/orderman/orders/NativeOrder.h"
#include "lib/tracing/PerfLog.h"
#include <memory>
namespace bts {
namespace orderman {
struct RoutingRecord;
class NewExecutionReportEvent;
class CancelRejectEvent;
class GatewayStatusChangeEvent;
class ExecutionReport;
class GLBXNativeOrder : public NativeOrder {
public:
GLBXNativeOrder();
~GLBXNativeOrder() override;
api::orderman::OrderDefinition const &definition() const override;
void on_init_new(api::orderman::OrderDefinition const &,
const PreActivationOrderServices &) override;
void on_init_recovered(api::orderman::OrderRecord const &,
const PreActivationOrderServices &) override;
OrderOpResult on_activate(Price, Quantity, OrderServices &) override;
OrderOpResult on_update(Price, Quantity) override;
OrderOpResult on_update(api::orderman::Update const &) override;
OrderOpResult on_detach() override;
OrderOpResult on_cancel() override;
void on_attached(api::orderman::OrderDefinition const &new_parent) override;
api::orderman::OrderDefinition
on_init_from_exe_report(ExecutionReport const &,
const PreActivationOrderServices &) override;
void ignore_or_cancel(std::string const &,
api::orderman::OrderError,
OrderOpResult *out) ;
protected:
void warm_up_activate(OrderServicesData &, OrderServices &) override;
private:
struct PImpl;
std::unique_ptr<PImpl> me;
void on_exe_report(const NewExecutionReportEvent &);
void on_cancel_reject(const CancelRejectEvent &);
void on_gateway_status(const GatewayStatusChangeEvent &);
void report_state();
OrderOpResult _on_activate(log::Level reject_level,
log::Level transition_level, Price p, Quantity q,
bts::orderman::OrderServices &services);
void init_fix();
void add_exchange_order_id_to_fix();
void transition(log::Level,
api::orderman::OrderStatus new_state,
std::string const &msg);
void transition(api::orderman::OrderStatus new_state,
std::string const &msg);
void transition(api::orderman::OrderStatus new_state);
void transition_to_error(api::orderman::NativeOrderState::SubError sub_error,
std::string const &msg);
void update_working_position();
bool has_exchange_order_id();
Quantity position_contribution();
bool is_old_exe_report(api::orderman::NativeOrderState &,
const NewExecutionReportEvent &) const;
bool terminal_state(api::orderman::OrderStatus status) const;
api::orderman::NativeOrderState &
get_native_state(api::orderman::OrderState &);
};
} // namespace orderman
} // namespace bts
File diff suppressed because it is too large. Load diff
-82
View File
@@ -1,82 +0,0 @@
#pragma once
#include "lib/orderman/orders/NativeOrder.h"
#include "lib/tracing/PerfLog.h"
#include <memory>
namespace bts {
namespace orderman {
struct RoutingRecord;
class NewExecutionReportEvent;
class CancelRejectEvent;
class GatewayStatusChangeEvent;
class ExecutionReport;
class ICENativeOrder : public NativeOrder {
public:
ICENativeOrder();
~ICENativeOrder() override;
const api::orderman::OrderDefinition& definition() const override;
void on_init_new(const api::orderman::OrderDefinition&,
const PreActivationOrderServices&) override;
void on_init_recovered(const api::orderman::OrderRecord&,
const PreActivationOrderServices &) override;
OrderOpResult on_activate(Price, Quantity, OrderServices &) override;
OrderOpResult on_update(Price, Quantity) override;
OrderOpResult on_update(const api::orderman::Update&) override;
OrderOpResult on_detach() override;
OrderOpResult on_cancel() override;
void on_attached(const api::orderman::OrderDefinition &new_parent) override;
api::orderman::OrderDefinition
on_init_from_exe_report(const ExecutionReport &, const PreActivationOrderServices &) override;
void ignore_or_cancel(const std::string&, api::orderman::OrderError, OrderOpResult* out);
protected:
void warm_up_activate(OrderServicesData &, OrderServices &) override;
void init_recovered_common(const api::orderman::OrderRecord &,
const PreActivationOrderServices &);
private:
struct PImpl;
std::unique_ptr<PImpl> me;
void on_exe_report(const NewExecutionReportEvent &);
void on_cancel_reject(const CancelRejectEvent &);
void on_gateway_status(const GatewayStatusChangeEvent &);
void report_state();
OrderOpResult _on_activate(log::Level reject_level,
log::Level transition_level, Price p, Quantity q,
bts::orderman::OrderServices &services);
void init_fix();
void add_exchange_order_id_to_fix();
void transition(log::Level,
api::orderman::OrderStatus new_state,
const std::string& msg);
void transition(api::orderman::OrderStatus new_state,
const std::string& msg);
void transition(api::orderman::OrderStatus new_state);
void transition_to_error(api::orderman::NativeOrderState::SubError sub_error,
const std::string& msg);
void update_working_position();
bool has_exchange_order_id();
Quantity position_contribution();
bool is_old_exe_report(api::orderman::NativeOrderState &,
const NewExecutionReportEvent &) const;
bool terminal_state(api::orderman::OrderStatus status) const;
api::orderman::NativeOrderState &
get_native_state(api::orderman::OrderState &);
int64_t get_new_clordid();
int64_t get_clordid(uint64_t);
void setup_ids(const std::string& sender_compid);
void generate_update_ids(const std::string&);
void generate_cancel_ids(const std::string&);
};
} // namespace orderman
} // namespace bts
@@ -1,4 +1,4 @@
#include "GLBXNativeOrder.h"
#include "NativeOrder.h"
#include "lib/api/services/OrderService.pb.h"
#include "lib/config/config.h"
@@ -28,7 +28,7 @@ using namespace api::orderman;
OrderStatus map_external_status(NativeOrderStatus);
struct GLBXNativeOrder::PImpl {
struct NativeOrder::PImpl {
PImpl()
: services(nullptr), session_services(), sec(nullptr),
previous_position_contribution(0), definition(), state(),
@@ -72,14 +72,14 @@ struct GLBXNativeOrder::PImpl {
std::optional<std::pair<Price, Quantity>> buffered_update;
};
GLBXNativeOrder::GLBXNativeOrder() : me(new PImpl()) {}
NativeOrder::NativeOrder() : me(new PImpl()) {}
OrderDefinition const &GLBXNativeOrder::definition() const {
OrderDefinition const &NativeOrder::definition() const {
return me->definition;
}
void GLBXNativeOrder::on_init_new(OrderDefinition const &def,
const PreActivationOrderServices &serv) {
void NativeOrder::on_init_new(OrderDefinition const &def,
const PreActivationOrderServices &serv) {
// order was just created.
me->definition = def;
@@ -161,8 +161,8 @@ void GLBXNativeOrder::on_init_new(OrderDefinition const &def,
init_fix();
}
void GLBXNativeOrder::on_init_recovered(OrderRecord const &rec,
const PreActivationOrderServices &serv) {
void NativeOrder::on_init_recovered(OrderRecord const &rec,
const PreActivationOrderServices &serv) {
// order was recovered from our orders database or from an execution
// report
@@ -231,8 +231,8 @@ void GLBXNativeOrder::on_init_recovered(OrderRecord const &rec,
}
api::orderman::OrderDefinition
GLBXNativeOrder::on_init_from_exe_report(ExecutionReport const &er,
const PreActivationOrderServices &os) {
NativeOrder::on_init_from_exe_report(ExecutionReport const &er,
const PreActivationOrderServices &os) {
auto k = er.order_key;
OrderRecord orecord;
@@ -330,10 +330,10 @@ GLBXNativeOrder::on_init_from_exe_report(ExecutionReport const &er,
return orecord.def();
}
GLBXNativeOrder::~GLBXNativeOrder() {}
NativeOrder::~NativeOrder() {}
void GLBXNativeOrder::warm_up_activate(OrderServicesData &data,
OrderServices &services) {
void NativeOrder::warm_up_activate(OrderServicesData &data,
OrderServices &services) {
bts_assert(!me->services);
me->services = &services;
@@ -358,9 +358,9 @@ void GLBXNativeOrder::warm_up_activate(OrderServicesData &data,
}
OrderOpResult
GLBXNativeOrder::_on_activate(log::Level reject_level, log::Level transition_level,
Price p, Quantity q,
bts::orderman::OrderServices &services) {
NativeOrder::_on_activate(log::Level reject_level, log::Level transition_level,
Price p, Quantity q,
bts::orderman::OrderServices &services) {
me->state.set_price(p.value());
me->state.set_quantity(q.value());
me->state.set_filled_quantity(0);
@@ -467,8 +467,8 @@ GLBXNativeOrder::_on_activate(log::Level reject_level, log::Level transition_lev
return OrderOpResult{};
}
OrderOpResult GLBXNativeOrder::on_activate(Price p, Quantity q,
bts::orderman::OrderServices &services) {
OrderOpResult NativeOrder::on_activate(Price p, Quantity q,
bts::orderman::OrderServices &services) {
bts_assert(!me->services);
me->services = &services;
auto result = OrderOpResult{};
@@ -476,7 +476,7 @@ OrderOpResult GLBXNativeOrder::on_activate(Price p, Quantity q,
case ORDER_STATUS_INACTIVE: {
auto scoped_log =
services.log_scope("GLBXNativeOrder::on_activate", key().value());
services.log_scope("NativeOrder::on_activate", key().value());
// this is a brand new order
result = _on_activate(Warn, Info, p, q, services);
@@ -570,19 +570,19 @@ OrderOpResult GLBXNativeOrder::on_activate(Price p, Quantity q,
return result;
}
OrderOpResult GLBXNativeOrder::on_update(Price p, Quantity q) {
OrderOpResult NativeOrder::on_update(Price p, Quantity q) {
api::orderman::Update update;
update.set_price(p.value());
update.set_quantity(q.value());
return on_update(update);
}
OrderOpResult GLBXNativeOrder::on_update(api::orderman::Update const &update) {
OrderOpResult NativeOrder::on_update(api::orderman::Update const &update) {
auto p = Price(update.price());
auto q = Quantity(update.quantity());
auto scoped_log =
me->services->log_scope("GLBXNativeOrder::on_update", key().value());
me->services->log_scope("NativeOrder::on_update", key().value());
auto result = OrderOpResult{};
switch (me->state.status()) {
@@ -707,9 +707,9 @@ OrderOpResult GLBXNativeOrder::on_update(api::orderman::Update const &update) {
return result;
}
OrderOpResult GLBXNativeOrder::on_detach() { return OrderOpResult{}; }
OrderOpResult NativeOrder::on_detach() { return OrderOpResult{}; }
void GLBXNativeOrder::on_attached(
void NativeOrder::on_attached(
api::orderman::OrderDefinition const &new_parent) {
switch (me->state.status()) {
@@ -764,9 +764,9 @@ void GLBXNativeOrder::on_attached(
}
}
OrderOpResult GLBXNativeOrder::on_cancel() {
OrderOpResult NativeOrder::on_cancel() {
auto scoped_log =
me->services->log_scope("GLBXNativeOrder::on_cancel", key().value());
me->services->log_scope("NativeOrder::on_cancel", key().value());
auto result = OrderOpResult{};
switch (me->state.status()) {
@@ -822,7 +822,7 @@ OrderOpResult GLBXNativeOrder::on_cancel() {
return result;
}
bool GLBXNativeOrder::is_old_exe_report(
bool NativeOrder::is_old_exe_report(
api::orderman::NativeOrderState &native_state,
const NewExecutionReportEvent &er) const {
if (native_state.last_transact_time().size() !=
@@ -844,9 +844,9 @@ bool GLBXNativeOrder::is_old_exe_report(
return true;
}
void GLBXNativeOrder::on_exe_report(const NewExecutionReportEvent &er) {
void NativeOrder::on_exe_report(const NewExecutionReportEvent &er) {
auto scoped_log =
me->services->log_scope("GLBXNativeOrder::on_exe_report", key().value());
me->services->log_scope("NativeOrder::on_exe_report", key().value());
auto &state = me->state;
auto &native_state = get_native_state(state);
@@ -969,7 +969,7 @@ void GLBXNativeOrder::on_exe_report(const NewExecutionReportEvent &er) {
}
}
void GLBXNativeOrder::on_cancel_reject(const orderman::CancelRejectEvent &cr) {
void NativeOrder::on_cancel_reject(const orderman::CancelRejectEvent &cr) {
LOG(OrderMan, Warn, "Cancel reject received for order {}", key().value());
switch (me->state.status()) {
@@ -997,7 +997,7 @@ void GLBXNativeOrder::on_cancel_reject(const orderman::CancelRejectEvent &cr) {
}
}
void GLBXNativeOrder::on_gateway_status(const GatewayStatusChangeEvent &ev) {
void NativeOrder::on_gateway_status(const GatewayStatusChangeEvent &ev) {
if (ev.is_connected) {
switch (me->state.status()) {
case ORDER_STATUS_COMPLETED:
@@ -1057,7 +1057,7 @@ void GLBXNativeOrder::on_gateway_status(const GatewayStatusChangeEvent &ev) {
report_state();
}
void GLBXNativeOrder::update_working_position() {
void NativeOrder::update_working_position() {
if (me->sec) {
auto current_position = position_contribution();
auto previous_position = me->previous_position_contribution;
@@ -1082,12 +1082,12 @@ void GLBXNativeOrder::update_working_position() {
key().value(), me->definition.security_key());
}
void GLBXNativeOrder::report_state() {
void NativeOrder::report_state() {
update_working_position();
me->services->report_state(me->state);
}
void GLBXNativeOrder::init_fix() {
void NativeOrder::init_fix() {
bts_assert(me->sec);
using namespace jetfix;
@@ -1253,7 +1253,7 @@ void GLBXNativeOrder::init_fix() {
}
}
void GLBXNativeOrder::add_exchange_order_id_to_fix() {
void NativeOrder::add_exchange_order_id_to_fix() {
bts_assert(has_exchange_order_id());
me->update_encoding.add<jetfix::fix::OrderID>(me->exchange_order_id);
me->cancel_encoding.add<jetfix::fix::OrderID>(me->exchange_order_id);
@@ -1296,16 +1296,16 @@ OrderStatus map_external_status(NativeOrderStatus status) {
return ORDER_STATUS_ERROR;
}
bool GLBXNativeOrder::has_exchange_order_id() {
bool NativeOrder::has_exchange_order_id() {
return me->exchange_order_id.size();
}
void GLBXNativeOrder::transition(api::orderman::OrderStatus new_status,
void NativeOrder::transition(api::orderman::OrderStatus new_status,
std::string const &msg) {
transition(Info, new_status, msg);
}
void GLBXNativeOrder::transition(log::Level level,
void NativeOrder::transition(log::Level level,
api::orderman::OrderStatus new_status,
std::string const &msg) {
auto const &from = OrderStatus_Name(me->state.status());
@@ -1317,7 +1317,7 @@ void GLBXNativeOrder::transition(log::Level level,
me->state.set_last_msg(msg);
}
void GLBXNativeOrder::transition(api::orderman::OrderStatus new_status) {
void NativeOrder::transition(api::orderman::OrderStatus new_status) {
auto const &from = OrderStatus_Name(me->state.status());
auto const &to = OrderStatus_Name(new_status);
if (from != to)
@@ -1330,7 +1330,7 @@ void GLBXNativeOrder::transition(api::orderman::OrderStatus new_status) {
me->state.set_status(new_status);
}
void GLBXNativeOrder::transition_to_error(
void NativeOrder::transition_to_error(
api::orderman::NativeOrderState::SubError sub_error,
std::string const &msg) {
me->state.mutable_limit()->mutable_native_state()->set_sub_error_code(
@@ -1338,7 +1338,7 @@ void GLBXNativeOrder::transition_to_error(
transition(ORDER_STATUS_ERROR, msg);
}
Quantity GLBXNativeOrder::position_contribution() {
Quantity NativeOrder::position_contribution() {
switch (me->state.status()) {
case ORDER_STATUS_WORKING:
@@ -1363,7 +1363,7 @@ Quantity GLBXNativeOrder::position_contribution() {
return Quantity(0);
}
bool GLBXNativeOrder::terminal_state(api::orderman::OrderStatus status) const {
bool NativeOrder::terminal_state(api::orderman::OrderStatus status) const {
switch (status) {
case ORDER_STATUS_COMPLETED:
@@ -1389,7 +1389,7 @@ bool GLBXNativeOrder::terminal_state(api::orderman::OrderStatus status) const {
}
api::orderman::NativeOrderState &
GLBXNativeOrder::get_native_state(api::orderman::OrderState &st) {
NativeOrder::get_native_state(api::orderman::OrderState &st) {
switch (st.custom_case()) {
case OrderState::kMarket:
return *st.mutable_market()->mutable_native_state();
@@ -1410,7 +1410,7 @@ GLBXNativeOrder::get_native_state(api::orderman::OrderState &st) {
return *st.mutable_stop_limit()->mutable_native_state();
}
void GLBXNativeOrder::ignore_or_cancel(std::string const &msg,
void NativeOrder::ignore_or_cancel(std::string const &msg,
api::orderman::OrderError error,
OrderOpResult *out) {
if (parent_key() == null_order_key())
+60 -4
View File
@@ -2,19 +2,75 @@
#include "lib/api/services/OrderService.pb.h"
#include "lib/orderman/orders/Order.h"
#include "lib/tracing/PerfLog.h"
#include <memory>
namespace bts {
namespace orderman {
struct RoutingRecord;
class NewExecutionReportEvent;
class CancelRejectEvent;
class GatewayStatusChangeEvent;
class ExecutionReport;
class NativeOrder : public Order {
public:
NativeOrder() = default;
~NativeOrder() override {};
NativeOrder();
~NativeOrder() override;
api::orderman::OrderDefinition const &definition() const;
void on_init_new(api::orderman::OrderDefinition const &,
const PreActivationOrderServices &) override;
void on_init_recovered(api::orderman::OrderRecord const &,
const PreActivationOrderServices &) override;
OrderOpResult on_activate(Price, Quantity, OrderServices &) override;
OrderOpResult on_update(Price, Quantity) override;
OrderOpResult on_update(api::orderman::Update const &) override;
OrderOpResult on_detach() override;
OrderOpResult on_cancel() override;
void on_attached(api::orderman::OrderDefinition const &new_parent) override;
virtual api::orderman::OrderDefinition const &definition() const = 0;
api::orderman::OrderDefinition
virtual on_init_from_exe_report(ExecutionReport const &, const PreActivationOrderServices &) = 0;
on_init_from_exe_report(ExecutionReport const &,
const PreActivationOrderServices &);
protected:
void warm_up_activate(OrderServicesData &, OrderServices &) override;
private:
struct PImpl;
std::unique_ptr<PImpl> me;
void on_exe_report(const NewExecutionReportEvent &);
void on_cancel_reject(const CancelRejectEvent &);
void on_gateway_status(const GatewayStatusChangeEvent &);
void report_state();
OrderOpResult _on_activate(log::Level reject_level,
log::Level transition_level, Price p, Quantity q,
bts::orderman::OrderServices &services);
void init_fix();
void add_exchange_order_id_to_fix();
void transition(log::Level,
api::orderman::OrderStatus new_state,
std::string const &msg);
void transition(api::orderman::OrderStatus new_state,
std::string const &msg);
void transition(api::orderman::OrderStatus new_state);
void transition_to_error(api::orderman::NativeOrderState::SubError sub_error,
std::string const &msg);
void update_working_position();
bool has_exchange_order_id();
Quantity position_contribution();
bool is_old_exe_report(api::orderman::NativeOrderState &,
const NewExecutionReportEvent &) const;
bool terminal_state(api::orderman::OrderStatus status) const;
api::orderman::NativeOrderState &
get_native_state(api::orderman::OrderState &);
void ignore_or_cancel(std::string const &,
api::orderman::OrderError,
OrderOpResult *out) ;
};
} // namespace orderman
@@ -3065,7 +3065,7 @@ TEST_CASE ("spreader_perf_2legs", "[spreader]")
}
TEST_CASE ("spreader_perf_4legs", "[spreader]")
{
bool recomp = gen_rand(0,10) > 5;
bool recomp = false;//gen_rand(0,10) > 5;
bts::orderman::OrderKey order_key(0);
Price spreader_price = Price (40);
Quantity spreader_quantity = Quantity (250);
+129 -133
View File
@@ -1,4 +1,3 @@
#ifndef _WIN32
#include "Puid.h"
#include "../os/os.h"
@@ -8,17 +7,17 @@
#include <fstream>
#include <vector>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/filesystem.hpp>
#include <boost/interprocess/sync/file_lock.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/filesystem.hpp>
#include <iomanip>
#include <stdint.h>
#include <tbb/mutex.h>
#include <iomanip>
#include <time.h>
#include <stdint.h>
namespace bts {
namespace utils {
@@ -36,99 +35,93 @@ const std::string counter_file_name = "counter_file";
// relying on the fact that metadata changes (like renaming) are
// atomic to provide transactional updates to a counter file which is
// used to generate uuids.
//
// Write process (on Foo.txt):
// - Step W1: Acquire "write lock" on the existing file.
// - Step W2: Copy the old file in a new unique temporary file. (copy Foo.txt
// Foo.TmpNNNN.txt)
// - Step W3: Apply the writes to the new file (Foo.TmpNNNN.txt).
// - Step W4: Flush all the writes (for example those being remaining in the
// cache manager).
// - Step W5: Rename the old file in a new unique Alternate form (ren Foo.txt
// Foo.AltNNNN.txt)
// - Step W6: Rename the new file into the old file (ren Foo.TmpNNNN.txt
// Foo.txt)
// - Step W7: Delete the old Alternate file (del Foo.AltNNNN.txt). If this
// fails, simply ignore. The file will be deleted later during the next
// recovery.
//
// Write process (on Foo.txt):
// - Step W1: Acquire "write lock" on the existing file.
// - Step W2: Copy the old file in a new unique temporary file. (copy Foo.txt Foo.TmpNNNN.txt)
// - Step W3: Apply the writes to the new file (Foo.TmpNNNN.txt).
// - Step W4: Flush all the writes (for example those being remaining in the cache manager).
// - Step W5: Rename the old file in a new unique Alternate form (ren Foo.txt Foo.AltNNNN.txt)
// - Step W6: Rename the new file into the old file (ren Foo.TmpNNNN.txt Foo.txt)
// - Step W7: Delete the old Alternate file (del Foo.AltNNNN.txt). If this fails, simply ignore. The file will be deleted later during the next recovery.
// - Step W8: Release "write lock" on the existing file.
// Recovery from a crash during write (on Foo.txt):
// - Step R1: If Foo.txt is missing but we have both Foo.AltNNNN.txt and
// Foo.TmpNNNN.txt present, then we crashed between Step W5 and Step W6. Retry
// from Step W6.
// - Step R2: If Foo.txt is present but Foo.TmpNNNN.txt is also present, then we
// crashed before Step W5. Try to delete all Foo.TmpNNNN.txt files and ignore
// failures.
// - Step R3: If Foo.txt is present but Foo.AltNNNN.txt is also present, then we
// crashed between Step W6 and Step W7. Try to delete all Foo.AltNNNN.txt files
// and ignore failures.
// Recovery from a crash during write (on Foo.txt):
// - Step R1: If Foo.txt is missing but we have both Foo.AltNNNN.txt and Foo.TmpNNNN.txt present, then we crashed between Step W5 and Step W6. Retry from Step W6.
// - Step R2: If Foo.txt is present but Foo.TmpNNNN.txt is also present, then we crashed before Step W5. Try to delete all Foo.TmpNNNN.txt files and ignore failures.
// - Step R3: If Foo.txt is present but Foo.AltNNNN.txt is also present, then we crashed between Step W6 and Step W7. Try to delete all Foo.AltNNNN.txt files and ignore failures.
void init_store(std::string const &path, std::string const &lock_path,
std::string const &counter_path) {
if (!boost::filesystem::is_directory(path)) {
void init_store (std::string const &path,
std::string const &lock_path,
std::string const &counter_path)
{
if (!boost::filesystem::is_directory(path))
{
boost::filesystem::create_directories(path);
std::ofstream fs(lock_path.c_str());
std::ofstream fc(counter_path.c_str());
std::ofstream fs(lock_path.c_str ());
std::ofstream fc(counter_path.c_str ());
fc << 0;
}
}
std::string find_file(std::string const &path, std::string const &ending) {
std::string find_file (std::string const &path, std::string const &ending)
{
for (boost::filesystem::directory_iterator p =
boost::filesystem::directory_iterator(path);
p != boost::filesystem::directory_iterator(); p++) {
std::string fn(p->path().string());
boost::filesystem::directory_iterator (path);
p != boost::filesystem::directory_iterator (); p++)
{
std::string fn (p->path ().string ());
if (boost::algorithm::ends_with(fn, ending))
return fn;
}
return std::string();
return std::string ();
}
// boost::filesystem::copy_file is broken for C++ 11 unless one compiles boost
// with c++ 11. (See
// http://boost.2283326.n4.nabble.com/Filesystem-problems-with-g-std-c-0x-td2639716.html)
// with c++ 11. (See http://boost.2283326.n4.nabble.com/Filesystem-problems-with-g-std-c-0x-td2639716.html)
// so we provide our own.
void copy_file(std::string const &in, std::string const &out) {
std::fstream f(in.c_str(), std::fstream::in | std::fstream::binary);
void copy_file(std::string const&in, std::string const &out)
{
std::fstream f(in.c_str (), std::fstream::in|std::fstream::binary);
f << std::noskipws;
std::istream_iterator<unsigned char> begin(f);
std::istream_iterator<unsigned char> end;
std::fstream f2(out.c_str(), std::fstream::out | std::fstream::trunc |
std::fstream::binary);
std::fstream f2(out.c_str (), std::fstream::out|std::fstream::trunc|std::fstream::binary);
std::ostream_iterator<char> begin2(f2);
std::copy(begin, end, begin2);
}
uint32_t get_host_ip_uint32(std::string const &ip) {
uint32_t get_host_ip_uint32 (std::string const &ip)
{
std::vector<std::string> split_vec;
boost::algorithm::split(split_vec, ip, boost::algorithm::is_any_of("."));
bts_assert(split_vec.size() == 4);
boost::algorithm::split( split_vec, ip,boost::algorithm::is_any_of(".") );
bts_assert (split_vec.size () == 4);
uint32_t result = 0;
int idx = 0;
for (std::string &byte : split_vec) {
uint32_t this_byte = atoi(byte.c_str());
uint32_t this_byte = atoi (byte.c_str ());
this_byte = (this_byte << (idx++ * 8));
result += this_byte;
}
return result;
}
std::string &get_host_ip_string(std::string const &ip) {
std::string &get_host_ip_string (std::string const &ip)
{
static std::string result;
if (result.size() == 0) {
if (result.size () == 0) {
std::ostringstream result_stream;
bts_assert(ip.size());
bts_assert(ip != "127.0.0.1");
std::istringstream ip_str(ip);
bts_assert (ip.size ());
bts_assert (ip != "127.0.0.1");
std::istringstream ip_str (ip);
for (int i = 0; i < 4; i++) {
int b;
ip_str >> b;
ip_str.get();
ip_str.get ();
char high_nibble = (b & 0xf0) >> 4;
char low_nibble = b & 0x0f;
if (high_nibble >= 10)
@@ -141,13 +134,14 @@ std::string &get_host_ip_string(std::string const &ip) {
low_nibble += '0';
result_stream << high_nibble << low_nibble;
}
result = result_stream.str();
result = result_stream.str ();
}
return result;
}
uint64_t reserve_ids(std::string const &scope, int n_ids) {
tbb::mutex::scoped_lock l(lock);
uint64_t reserve_ids (std::string const &scope, int n_ids)
{
tbb::mutex::scoped_lock l (lock);
// we risk race conditions if the directory is not there.
// but that's OK, this is rare and easily manageable.
@@ -155,82 +149,83 @@ uint64_t reserve_ids(std::string const &scope, int n_ids) {
std::string lock_path = path + "/" + lock_file_name;
std::string counter_path = path + "/" + counter_file_name;
init_store(path, lock_path, counter_path);
init_store (path,lock_path, counter_path);
// W1
boost::interprocess::file_lock f_lock(lock_path.c_str());
boost::interprocess::scoped_lock<boost::interprocess::file_lock> scope_lock(
f_lock);
boost::interprocess::file_lock f_lock(lock_path.c_str ());
boost::interprocess::scoped_lock<boost::interprocess::file_lock> scope_lock (f_lock);
std::string tmp_file = find_file(path, ".tmp");
std::string alt_file = find_file(path, ".alt");
std::string counter_file = find_file(path, counter_file_name);
std::string tmp_file = find_file (path, ".tmp");
std::string alt_file = find_file (path, ".alt");
std::string counter_file = find_file (path, counter_file_name);
// r1?
if (counter_file.size() == 0 && tmp_file.size() && alt_file.size()) {
boost::filesystem::rename(tmp_file, counter_path);
boost::filesystem::remove(alt_file);
f_lock.unlock();
lock.unlock();
return reserve_ids(scope, n_ids);
if (counter_file.size () == 0 && tmp_file.size () && alt_file.size ()) {
boost::filesystem::rename (tmp_file,counter_path);
boost::filesystem::remove (alt_file);
f_lock.unlock ();
lock.unlock ();
return reserve_ids (scope,n_ids);
}
// r2
else if (counter_file.size() && tmp_file.size()) {
boost::filesystem::remove(tmp_file);
f_lock.unlock();
lock.unlock();
return reserve_ids(scope, n_ids);
else if (counter_file.size () && tmp_file.size ()) {
boost::filesystem::remove (tmp_file);
f_lock.unlock ();
lock.unlock ();
return reserve_ids (scope,n_ids);
}
// r3
else if (counter_file.size() && alt_file.size()) {
boost::filesystem::remove(alt_file);
f_lock.unlock();
lock.unlock();
return reserve_ids(scope, n_ids);
else if (counter_file.size () && alt_file.size ()) {
boost::filesystem::remove (alt_file);
f_lock.unlock ();
lock.unlock ();
return reserve_ids (scope,n_ids);
} else {
// W2, copy counter file to a temp file
tmp_file = path + "/" + Uuid().to_text_string() + ".tmp";
copy_file(counter_path, tmp_file);
tmp_file = path + "/" + Uuid ().to_text_string () + ".tmp";
copy_file (counter_path, tmp_file);
// W3, W4 update temp file, close and flush
uint64_t counter_value;
std::ifstream(tmp_file.c_str()) >> counter_value;
std::ofstream(tmp_file.c_str()) << counter_value + n_ids;
std::ifstream (tmp_file.c_str ()) >> counter_value;
std::ofstream (tmp_file.c_str ()) << counter_value + n_ids;
// W5, rename counter file to an alt file (renames are atomic)
alt_file = path + "/" + Uuid().to_text_string() + ".alt";
boost::filesystem::rename(counter_path, alt_file);
alt_file = path + "/" + Uuid ().to_text_string () + ".alt";
boost::filesystem::rename (counter_path, alt_file);
// W6, rename temp file to counter file
boost::filesystem::rename(tmp_file, counter_path);
// W6, rename temp file to counter file
boost::filesystem::rename (tmp_file,counter_path);
// W7 delete alt file
boost::filesystem::remove(alt_file);
boost::filesystem::remove (alt_file);
return counter_value;
}
}
std::vector<uint64_t> gen_ids(std::string const &scope, int n_ids) {
auto counter_value = reserve_ids(scope, n_ids);
std::vector<uint64_t> gen_ids (std::string const &scope, int n_ids)
{
auto counter_value = reserve_ids (scope,n_ids);
std::vector<uint64_t> result;
for (int i = 0; i < n_ids; i++)
result.push_back(counter_value + i);
result.push_back (counter_value + i);
return result;
}
static char base_62_alphabet[] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c',
'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C',
'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
static char base_62_alphabet [] = {
'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f',
'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
'w','x','y','z','A','B','C','D','E','F','G','H','I','J','K','L',
'M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'
};
std::string to_base_62(uint32_t src) {
std::string out(6, ' ');
for (int i = 5; i >= 0; i--) {
std::string to_base_62 (uint32_t src)
{
std::string out (6, ' ');
for (int i=5; i >= 0;i--) {
int r = src % 62;
out[i] = base_62_alphabet[r];
src = src / 62;
@@ -238,46 +233,47 @@ std::string to_base_62(uint32_t src) {
return out;
}
void to_base_62(std::vector<uint32_t> const &id_vec, std::vector<char> *out) {
for (auto src : id_vec)
for (int i = 5; i >= 0; i--) {
void to_base_62 (std::vector<uint32_t> const &id_vec, std::vector<char> *out)
{
for (auto src : id_vec)
for (int i=5; i >= 0;i--) {
int r = src % 62;
out->push_back(base_62_alphabet[r]);
out->push_back (base_62_alphabet[r]);
src = src / 62;
}
}
uint64_t gen_id(std::string const &scope) {
std::vector<uint64_t> result = gen_ids(scope, 1);
uint64_t gen_id (std::string const &scope)
{
std::vector<uint64_t> result = gen_ids (scope, 1);
return result[0];
}
std::vector<Puid> gen_puids(std::string const &scope, int n_puids) {
std::vector<Puid> gen_puids (std::string const &scope, int n_puids)
{
// first generate a series of unique uint32 numbers (For this machine)
std::vector<uint64_t> ids = gen_ids(scope, n_puids);
std::vector<uint64_t> ids = gen_ids (scope, n_puids);
// now add the host ip and a timer string to the generated id to
// guarantee uniqueness across machines
uint32_t ip = get_host_ip_uint32(os::default_host_ip());
std::string encoded_ip(to_base_62(ip));
uint32_t seconds = time(NULL);
std::string encoded_time(to_base_62(seconds));
uint32_t ip = get_host_ip_uint32 (os::default_host_ip ());
std::string encoded_ip (to_base_62 (ip));
uint32_t seconds = time (NULL);
std::string encoded_time (to_base_62 (seconds));
std::vector<Puid> result;
for (uint32_t id : ids) {
std::ostringstream s;
s << encoded_ip << "-" << encoded_time << "-" << to_base_62(id);
result.push_back(s.str());
s << encoded_ip << "-" << encoded_time << "-" << to_base_62 (id);
result.push_back (s.str ());
}
return result;
}
Puid gen_puid(std::string const &scope) {
return *(gen_puids(scope, 1).begin());
Puid gen_puid (std::string const &scope)
{
return *(gen_puids (scope,1).begin ());
}
} // namespace utils
} // namespace bts
#endif
}}
+9 -67
View File
@@ -1,12 +1,10 @@
#pragma once
#include "bts_export.h"
#include "lib/utils/bts_assert.h"
#include <mutex>
#include <stdint.h>
#include <string>
#include <vector>
#include <stdint.h>
namespace bts {
namespace utils {
@@ -21,77 +19,21 @@ typedef std::string Puid;
// machine's ip, the unix time (seconds since 1970) and a machine
// unique counter. id's are 20 bytes long and can contain [a-z], [A-Z]
// [0-9] and -
BTS_EXPORT std::vector<Puid> gen_puids(std::string const &scope, int n_puids);
BTS_EXPORT Puid gen_puid(std::string const &scope);
BTS_EXPORT std::vector<Puid> gen_puids (std::string const &scope, int n_puids);
BTS_EXPORT Puid gen_puid (std::string const &scope);
// generate machine unique ids (no guarantees of uniqueness across
// machines)
BTS_EXPORT std::vector<uint64_t> gen_ids(std::string const &scope, int n_ids);
BTS_EXPORT std::vector<uint64_t> gen_ids (std::string const &scope, int n_ids);
// Similar to the above but instead of copying the ids to a vector
// this simply returns the first free id (x) and skips ahead by n_ids
// so that the next gen_id call will will be x+n_ids
BTS_EXPORT uint64_t reserve_ids(std::string const &scope, int n_ids);
BTS_EXPORT uint64_t reserve_ids (std::string const &scope, int n_ids);
// generate a single id
BTS_EXPORT uint64_t gen_id(std::string const &scope);
BTS_EXPORT uint64_t gen_id (std::string const &scope);
// convert a uint32 to a 6 byte human readeable string containing only
// alpha numerical characters.
BTS_EXPORT std::string to_base_62(uint32_t id);
BTS_EXPORT void to_base_62(std::vector<uint32_t> const &ids,
std::vector<char> *out);
#ifndef _WIN32
class BTS_EXPORT IDGenerator {
public:
IDGenerator(std::string const &scope, uint32_t batch_size)
: _batch_size(batch_size), _next(0), _end(0), _scope(scope), _lock() {
bts_assert((int)batch_size > 0);
refill();
}
// next should only be called from a single thread
uint64_t next() {
if (_remaning() == 0) {
std::lock_guard _(_lock);
if (!_next_block.has_value())
_get_next_block();
bts_assert(_next_block.has_value());
_next = _next_block.value().first;
_end = _next_block.value().second;
_next_block.reset();
}
bts_assert(_remaning() > 0);
return _next++;
}
// refill can be called from any thread
void refill() {
std::lock_guard _(_lock);
if (!_next_block.has_value())
_get_next_block();
}
private:
uint64_t _remaning() {
bts_assert(_end >= _next);
return _end - _next;
}
void _get_next_block() {
auto block_start = reserve_ids(_scope, _batch_size);
auto block_end = block_start + _batch_size;
_next_block = std::make_pair(block_start, block_end);
}
const uint32_t _batch_size;
uint64_t _next;
uint64_t _end;
const std::string _scope;
std::mutex _lock;
std::optional<std::pair<uint64_t, uint64_t>> _next_block;
};
#endif
} // namespace utils
} // namespace bts
BTS_EXPORT std::string to_base_62 (uint32_t id);
BTS_EXPORT void to_base_62 (std::vector<uint32_t> const &ids, std::vector<char> *out);
}}
-46
View File
@@ -1,46 +0,0 @@
#pragma once
#include <utility>
#include <memory>
#include <algorithm>
#include <cmath>
#include "lib/utils/bts_assert.h"
namespace bts {
namespace utils {
static char base_62_alphabet [] =
{
'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f',
'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
'w','x','y','z','A','B','C','D','E','F','G','H','I','J','K','L',
'M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'
};
inline std::string to_base_62 (uint32_t src)
{
std::string out (6, ' ');
for (int i=5; i >= 0; i--)
{
int r = src % 62;
out[i] = base_62_alphabet[r];
src = src / 62;
}
return out;
}
inline uint32_t from_base_62 (const std::string& src)
{
bts_assert_msg(src.size() == 6, "bad base62 hash");
uint32_t out = 0;
for (int i=5; i >= 0; i--)
{
uint32_t idx = std::distance(&base_62_alphabet[0], std::find(&base_62_alphabet[0], &base_62_alphabet[61], src[i]));
out += idx * pow(62, 5-i);
}
return out;
}
}}
+8
View File
@@ -350,6 +350,14 @@ bool is_local_time_sunday() {
auto now = local_now();
return now.date().day_of_week() == boost::date_time::Sunday;
}
bool is_local_time_near_sunday_sunday() {
auto now = local_now();
auto day = now.date().day_of_week();
auto hour = now.time_of_day().hours();
return
day == boost::date_time::Sunday
|| ( day == boost::date_time::Monday && hour < 6);
}
bool is_local_time_between(int hh_start, int mm_start, int hh_end, int mm_end) {
using namespace boost::posix_time;
auto now = local_now();
+1
View File
@@ -86,6 +86,7 @@ extern "C" BTS_EXPORT LLDateTime ll_from_parts(int year, int month, int day, int
BTS_EXPORT LLDateTime ll_from_date(const Date& date);
bool is_local_time_sunday();
bool is_local_time_near_sunday_sunday();
bool is_local_time_between(int hh_start, int mm_start, int hh_end, int mm_end);
#ifndef NO_CPP0X
-55
View File
@@ -1,55 +0,0 @@
#ifndef _WIN32
#include "../Puid.h"
#include "catch/catch.hpp"
namespace bts {
TEST_CASE("IDGenerator", "[utils]") {
SECTION("1") {
utils::IDGenerator gen("test",1);
auto start = gen.next();
for (int i = 0; i < 10;i++) {
auto previous_start = start;
start = gen.next();
REQUIRE( start == previous_start + 1);
}
}
SECTION("10") {
utils::IDGenerator gen("test",4);
auto start = gen.next();
for (int i = 0; i < 10;i++) {
auto previous_start = start;
start = gen.next();
REQUIRE( start == previous_start + 1);
}
}
SECTION("10_interference") {
utils::IDGenerator gen("test",4);
auto start = gen.next();
auto previous_start = start;
auto interferance = utils::reserve_ids("test", 3);
previous_start = start;
start = gen.next();
REQUIRE( start == previous_start + 1);
previous_start = start;
start = gen.next();
REQUIRE( start == previous_start + 1);
previous_start = start;
start = gen.next();
REQUIRE( start == previous_start + 1);
previous_start = start;
start = gen.next();
REQUIRE( interferance + 3 == start);
previous_start = start;
start = gen.next();
REQUIRE( start == previous_start + 1);
}
}
}//ns
#endif
+1 -1
View File
@@ -6,7 +6,7 @@ namespace cmd {
int RunSim::execute(std::vector<std::string> const &)
{
sim::start_exchange_sim(api::Venue::VENUE_SIM, nullptr);
sim::start_exchange_sim(nullptr);
return 0;
}
+6 -18
View File
@@ -10,7 +10,6 @@
#include <fstream>
#include "lib/os/os.h"
#include "lib/domain_model/Security.pb.h"
#include "lib/config/protos/Ports.pb.h"
#include "lib/config/protos/ExchangeSimCfg.pb.h"
#include "lib/config/config.h"
@@ -126,31 +125,20 @@ struct MDPlayer : md::IRelayWriter
};
int start_exchange_sim(bts::api::Venue venue, md::MBOWriter* mbo)
int start_exchange_sim(md::MBOWriter* mbo)
{
try
{
auto str_settings = std::string(cfg);
auto venue_string = api::Venue_Name(venue);
boost::replace_all(str_settings,"$BTS_DATA_PATH", os::bts_data_path() + "_" + venue_string);
std::string port_string;
switch(venue)
{
case api::VENUE_SIM:
port_string = std::to_string(config::get<config::Ports>().glbx_sim_fix_port());
break;
case api::VENUE_SIMICE:
port_string = std::to_string(config::get<config::Ports>().ice_sim_fix_port());
break;
default:
bts_assert_msg(false, "Not a valid sim venue");
}
boost::replace_all(str_settings,"$EXCHANGE_SIM_FIX_PORT", port_string);
boost::replace_all(str_settings,"$BTS_DATA_PATH", os::bts_data_path());
boost::replace_all(str_settings,"$EXCHANGE_SIM_FIX_PORT",
std::to_string(
config::get<config::Ports>().exchange_sim_fix_port()));
std::istringstream str{str_settings};
FIX::SessionSettings settings( str );
ex_sim::ExchangeSimApplication application( venue, mbo );
ex_sim::ExchangeSimApplication application(mbo);
FIX::FileStoreFactory storeFactory( settings );
FIX::FileLogFactory logFactory( settings );
FIX::SocketAcceptor acceptor( application, storeFactory, settings, logFactory );
+1 -2
View File
@@ -1,12 +1,11 @@
#pragma once
#include <memory>
#include "lib/domain_model/Security.pb.h"
namespace bts {
namespace md { class MBOWriter; }
namespace sim {
int start_exchange_sim(bts::api::Venue, md::MBOWriter*);
int start_exchange_sim(md::MBOWriter*);
}}
@@ -106,19 +106,15 @@ inline FIX::OrderID exchange_key(const std::string &clOrdID) {
}
struct ExchangeSimApplication::PImpl {
PImpl(bts::api::Venue venue, md::MBOWriter* mbo)
: venue(venue),
producer(co2::PLATFORM_SIM),
md_sn(1),
PImpl(md::MBOWriter *mbo)
: producer(co2::PLATFORM_SIM), md_sn(1),
timer(utils::Dispatcher::background(), 200,
[=]() { producer.heartbeat(); }),
do_merge_with_md(config::get<config::ExchangeSim>().merge_with_md()),
store(new persistence::SqliteStore("ex_sim_orders_" + api::Venue_Name(venue))),
lock(),
store(new persistence::SqliteStore("ex_sim_orders")), lock(),
mbo(mbo) {}
IDGenerator m_generator;
bts::api::Venue venue;
md::MDProducer producer;
std::map<std::string, MDConsumerRec> md_consumer_recs;
std::map<std::string, md::MDProducerHandle> md_producer_handles;
@@ -131,7 +127,8 @@ struct ExchangeSimApplication::PImpl {
md::MBOWriter *mbo;
};
ExchangeSimApplication::ExchangeSimApplication(bts::api::Venue venue, md::MBOWriter* mbo) : me(new PImpl(venue, mbo)) {
ExchangeSimApplication::ExchangeSimApplication(md::MBOWriter *mbo)
: me(new PImpl(mbo)) {
auto previous_book = me->store->retrieve_all();
auto all = me->store->retrieve_all()["books"];
@@ -555,7 +552,7 @@ void ExchangeSimApplication::update_md(std::string const &sec_desc) {
}
std::string get_sim_sec_desc(api::Security const &src_sec) {
return std::string("SIM:") + securities::descriptor(src_sec);
return std::string("SIM:") + src_sec.glbx().security_desc();
}
void negate_id(api::Security *sec) {
@@ -579,28 +576,18 @@ void ExchangeSimApplication::persist_book(OrderBook const &b) {
void ExchangeSimApplication::on_new_security(api::Security const &s) {
std::lock_guard<std::mutex> l(me->lock);
if (!s.has_synthetic()) {
md::with_security_like(s, [this, s](auto &fs)
{
auto s2 = s;
if(s.exchange() == api::VENUE_GLBX && me->venue == api::VENUE_SIM)
{
*s2.mutable_glbx()->mutable_security_desc() = get_sim_sec_desc(s);
s2.set_exchange(api::VENUE_SIM);
}
else if(me->venue == api::VENUE_ICE && me->venue == api::VENUE_SIMICE)
{
*s2.mutable_ice()->mutable_security_desc() = get_sim_sec_desc(s);
s2.set_exchange(api::VENUE_SIMICE);
}
else
return;
md::with_security_like(s, [this, s](auto &fs) {
auto s2 = s;
*s2.mutable_glbx()->mutable_security_desc() = get_sim_sec_desc(s);
s2.set_exchange(api::VENUE_SIM);
negate_id(&s2);
md::convert_security(s2, fs, true);
md::MDProducerHandle handle = me->producer.add_security(fs);
auto sec_desc = securities::descriptor(s2);
me->md_producer_handles.insert(make_pair(sec_desc, handle));
me->md_consumer_recs.insert(make_pair(securities::descriptor(s),
MDConsumerRec{s2, utils::TimeStamp::now()}));
me->md_consumer_recs.insert(
make_pair(s.glbx().security_desc(),
MDConsumerRec{s2, utils::TimeStamp::now()}));
});
}
}
@@ -667,9 +654,8 @@ void ExchangeSimApplication::on_depth(
if (!me->do_merge_with_md)
return;
auto it = me->md_consumer_recs.find(securities::descriptor(sec));
if(it == me->md_consumer_recs.end())
return;
auto it = me->md_consumer_recs.find(sec.glbx().security_desc());
bts_assert(it != me->md_consumer_recs.end());
auto &matcher = me->matchers[get_sim_sec_desc(sec)];
Book previous_md_book = matcher.get_book();
@@ -689,7 +675,7 @@ void ExchangeSimApplication::on_depth(
// from the differences between current_md_book and previous_md_book
// we generate a set of orders that we apply to our order book
merge_with_order_book(securities::descriptor(it->second.security),
merge_with_order_book(it->second.security.glbx().security_desc(),
previous_md_book, current_md_book);
// pass on implied market unchanged
@@ -40,7 +40,6 @@ GCC_DIAG_OFF("-Wignored-qualifiers")
#include <quickfix/fix42/NewOrderSingle.h>
#include <quickfix/fix42/OrderCancelRequest.h>
#include "server/sparkd/exchange_sim/IMDPlayerObserver.h"
#include "lib/domain_model/Security.pb.h"
namespace bts {
namespace api {class Security;}
@@ -56,7 +55,7 @@ class ExchangeSimApplication
public FIX::MessageCracker
{
public:
ExchangeSimApplication(bts::api::Venue venue, md::MBOWriter*);
ExchangeSimApplication(md::MBOWriter*);
~ExchangeSimApplication();
void merge_with_md_book();
@@ -14,20 +14,13 @@ namespace md {
namespace ice {
template <>
double double_of_price<onixs_ice::Rational>(const onixs_ice::Rational& price, int8_t denominator)
double double_of_price<onixs_ice::Rational>(const onixs_ice::Rational& price, int8_t display_factor)
{
UNUSED(denominator);
UNUSED(display_factor);
double dbl = price.convertTo<double>();
return dbl;
}
template<>
void ICEListener::set_security_specific<onixs_ice::FuturesProductDefinition>(const onixs_ice::FuturesProductDefinition& def,
FixedSecurity& fsec)
{
fsec.cash_per_point = double_of_price(def.tickValue, fsec.ice_price_denominator);
//fsec.cash_per_point = def.tickValue;
}
ICEListener::ICEListener(ICESecurityIndex& index, MDProducer& producer, const std::vector<MDProducerChannel> channels) :
_index(index),
@@ -42,21 +35,20 @@ ICEListener::~ICEListener() {}
std::string ICEListener::parse_contract_symbol(const std::string& sym)
{
auto end = sym.find(' ');
if(end == std::string::npos)
return sym;
else
return sym.substr(0, end);
const auto&& res = sym.substr(0, sym.find(' '));
return res;
}
//
//State change
void ICEListener::onHandlerStateChange(const onixs_ice::HandlerStateChange&)
void ICEListener::onHandlerStateChange(const onixs_ice::HandlerStateChange& )
{
//TODO
}
void ICEListener::onMarketStateChange(const onixs_ice::MarketStateChange& , const onixs_ice::MessageInfo&)
void ICEListener::onMarketStateChange(const onixs_ice::MarketStateChange& , const onixs_ice::MessageInfo& )
{
//TODO
}
//
@@ -92,12 +84,18 @@ void ICEListener::onNewExpiry(const onixs_ice::NewExpiry& msg, bool& is_interest
void ICEListener::onFuturesStrategyDefinition(const onixs_ice::FuturesStrategyDefinition& def, bool& is_interested)
{
on_uds_future_spread(def, is_interested);
//TODO need to find out how to produce data for testing
//on_uds_future_spread(def, is_interested);
UNUSED(def);
UNUSED(is_interested);
}
//This is only for UDS
void ICEListener::onNewFuturesStrategyDefinition(const onixs_ice::NewFuturesStrategyDefinition& msg, bool& is_interested, const onixs_ice::MessageInfo& )
{
on_uds_future_spread(msg, is_interested);
//TODO need to find out how to produce data for testing
//on_uds_future_spread(msg, is_interested);
UNUSED(msg);
UNUSED(is_interested);
}
void ICEListener::onOptionsProductDefinition(const onixs_ice::OptionsProductDefinition& msg, bool& is_interested)
@@ -124,49 +122,19 @@ void ICEListener::onNewOptionsStrategyDefinition(const onixs_ice::NewOptionsStra
}
//
// Gap Recovery -- This is not necessary if we subscribe to the onOrderBookUpdated callback, they handle the breaks transparently
void ICEListener::onMarketSnapshot(const onixs_ice::MarketSnapshot& msg, const onixs_ice::MessageInfo& msg_info)
{
UNUSED(msg);
UNUSED(msg_info);
auto* data = _index.get_security(msg.marketId);
if (data != nullptr)
{
bts_assert(data->id == msg.marketId);
auto ts = utils::TimeStamp::now();
auto settle_denominator = data->handle.security().ice_settle_denominator;
data->handle.update_settlement( ts, convert_price(msg.settlementPrice, settle_denominator), date_of_timestamp(msg.settlePriceDateTime) );
LOG(md,Diag,"OnixSICE Got Market Snap : {} - {}", std::to_string(data->id), std::to_string(msg.settlementPrice));
auto deal_denominator = data->handle.security().ice_deal_denominator;
data->handle.update_opening( ts, double_of_price(msg.openingPrice, deal_denominator), datetime::today() );
data->handle.update_session_high( ts, double_of_price(msg.high, deal_denominator) );
data->handle.update_session_low( ts, double_of_price(msg.low, deal_denominator) );
data->handle.set_last_trade( ts, pricesize_of_price_size(msg.lastTradePrice, deal_denominator, msg.lastTradeQuantity),
ll_of_timestamp(msg.lastTradeDateTime), msg.volume );
}
}
void ICEListener::onMarketStatistics(const onixs_ice::MarketStatistics& msg, const onixs_ice::MessageInfo& msg_info)
{
UNUSED(msg_info);
auto* data = _index.get_security(msg.marketId);
if (data != nullptr)
{
bts_assert(data->id == msg.marketId);
data->handle.set_total_volume(msg.volume);
}
}
// Gap Recovery -- This is not necessary if we subscribe to the onOrderBookUpdated callback, they handle the breaks transparently
void ICEListener::onMarketSnapshotOrder(const onixs_ice::MarketSnapshotOrder& msg, const onixs_ice::MessageInfo& msg_info)
{
UNUSED(msg);
UNUSED(msg_info);
}
// Gap Recovery -- This is not necessary if we subscribe to the onOrderBookUpdated callback, they handle the breaks transparently
void ICEListener::onMarketSnapshotPriceLevel(const onixs_ice::MarketSnapshotPriceLevel& msg, const onixs_ice::MessageInfo& msg_info)
{
UNUSED(msg);
@@ -183,7 +151,7 @@ void ICEListener::onOrderBookUpdated(const onixs_ice::OrderBook& onixs_book, con
if (data == nullptr)
return;
bts_assert(data->id == onixs_book.marketId());
auto denominator = data->handle.security().ice_price_denominator;
auto display_factor = data->handle.security().display_factor;
// Overwrite all entries every time
size_t bids_size = onixs_book.bids().size();
@@ -201,21 +169,20 @@ void ICEListener::onOrderBookUpdated(const onixs_ice::OrderBook& onixs_book, con
{
auto& bid = onixs_book.bids()[x];
if(x < COCONUT_MAX_DEPTH)
dbids[x] = pricesize_of_price_size(bid.price, denominator, bid.quantity - bid.impliedQuantity);
dbids[x] = pricesize_of_price_size(bid.price, display_factor, bid.quantity - bid.impliedQuantity);
if(x < COCONUT_MAX_IMPLIED_DEPTH)
ibids[x] = pricesize_of_price_size(bid.price, denominator, bid.impliedQuantity);
ibids[x] = pricesize_of_price_size(bid.price, display_factor, bid.impliedQuantity);
}
for (size_t x = 0; x < asks_size; ++x)
{
auto& ask = onixs_book.offers()[x];
if(x < COCONUT_MAX_DEPTH)
dasks[x] = pricesize_of_price_size(ask.price, denominator, ask.quantity - ask.impliedQuantity);
dasks[x] = pricesize_of_price_size(ask.price, display_factor, ask.quantity - ask.impliedQuantity);
if(x < COCONUT_MAX_IMPLIED_DEPTH)
iasks[x] = pricesize_of_price_size(ask.price, denominator, ask.impliedQuantity);
iasks[x] = pricesize_of_price_size(ask.price, display_factor, ask.impliedQuantity);
}
data->handle.update_books(TimeStamp::now(), dbids, dasks, ibids, iasks, (uint32_t) msg_info.sequenceNumber);
}
}
//
// Trades
@@ -232,13 +199,12 @@ AggressorSide map_aggressor(onixs_ice::AggressorSide::Enum agside)
}
}
void on_trade(ICESecurityData* data, const onixs_ice::Price& price, int size,
onixs_ice::AggressorSide::Enum agside, const onixs_ice::DateTime& onixs_date, bool from_spread)
void on_trade(ICESecurityData* data, const onixs_ice::Price& price, int size, onixs_ice::AggressorSide::Enum agside, const onixs_ice::DateTime& onixs_date)
{
auto ts = utils::TimeStamp::now();
PriceSize ps = pricesize_of_price_size(price, data->handle.security().ice_deal_denominator, size);
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, map_aggressor(agside), 0u, from_spread);
data->handle.add_trade(ts, ps, date, map_aggressor(agside), size);
}
void ICEListener::onTrade(const onixs_ice::Trade& msg, const onixs_ice::MessageInfo& )
@@ -250,7 +216,7 @@ void ICEListener::onTrade(const onixs_ice::Trade& msg, const onixs_ice::MessageI
auto size = msg.quantity;
auto price = msg.price;
onixs_ice::AggressorSide::Enum agside = msg.aggressorSide;
on_trade(data, price, size, agside, msg.transactDateTime, msg.isSystemPricedLeg);
on_trade(data, price, size, agside, msg.transactDateTime);
}
}
@@ -298,12 +264,10 @@ void ICEListener::onSettlementPrice(const onixs_ice::SettlementPrice& msg, const
if (data != nullptr)
{
bts_assert(data->id == msg.marketId);
auto ts = utils::TimeStamp::now();
auto price = msg.settlementPrice;
auto time = msg.dateTime;
auto denominator = data->handle.security().ice_settle_denominator;
LOG(md,Diag,"OnixSICE Got Settlement: {} - {}", std::to_string(data->id), std::to_string(price));
data->handle.update_settlement(ts, convert_price(price, denominator), date_of_timestamp(time));
onixs_ice::Price price = msg.settlementPrice;
onixs_ice::DateTime time = msg.dateTime;
auto display_factor = data->handle.security().display_factor;
data->handle.update_settlement(utils::TimeStamp::now(), convert_price(price, display_factor), date_of_timestamp(time));
}
}
@@ -321,8 +285,8 @@ void ICEListener::onOpenPrice(const onixs_ice::OpenPrice& msg, const onixs_ice::
bts_assert(data->id == msg.marketId);
onixs_ice::Price price = msg.openPrice;
onixs_ice::DateTime time = msg.dateTime;
auto denominator = data->handle.security().ice_deal_denominator;
data->handle.update_opening( utils::TimeStamp::now(), double_of_price(price, denominator), date_of_timestamp(time));
auto display_factor = data->handle.security().display_factor;
data->handle.update_opening( utils::TimeStamp::now(), double_of_price(price, display_factor), date_of_timestamp(time));
}
}
@@ -334,8 +298,8 @@ void ICEListener::onClosePrice(const onixs_ice::ClosePrice& msg, const onixs_ice
bts_assert(data->id == msg.marketId);
onixs_ice::Price price = msg.closePrice;
onixs_ice::DateTime time = msg.dateTime;
auto denominator = data->handle.security().ice_deal_denominator;
data->handle.update_closing( utils::TimeStamp::now(), double_of_price(price, denominator), date_of_timestamp(time));
auto display_factor = data->handle.security().display_factor;
data->handle.update_closing( utils::TimeStamp::now(), double_of_price(price, display_factor), date_of_timestamp(time));
}
}
@@ -346,16 +310,11 @@ void ICEListener::onEndOfDayMarketSummary(const onixs_ice::EndOfDayMarketSummary
{
bts_assert(data->id == msg.marketId);
onixs_ice::DateTime time = msg.dateTime;
auto ts = utils::TimeStamp::now();
auto settle_denominator = data->handle.security().ice_settle_denominator;
data->handle.update_settlement( ts, convert_price(msg.settlementPrice, settle_denominator), date_of_timestamp(time) );
LOG(md,Warn,"OnixSICE Got EOD Market : {} - {}", std::to_string(data->id), std::to_string(msg.settlementPrice));
auto deal_denominator = data->handle.security().ice_deal_denominator;
data->handle.update_opening( ts, double_of_price(msg.openingPrice, deal_denominator), date_of_timestamp(time) );
data->handle.update_session_high( ts, double_of_price(msg.high, deal_denominator) );
data->handle.update_session_low( ts, double_of_price(msg.low, deal_denominator) );
auto display_factor = data->handle.security().display_factor;
data->handle.update_opening( utils::TimeStamp::now(), double_of_price(msg.openingPrice, display_factor), date_of_timestamp(time) );
data->handle.update_session_high( utils::TimeStamp::now(), double_of_price(msg.high, display_factor) );
data->handle.update_session_low( utils::TimeStamp::now(), double_of_price(msg.low, display_factor) );
data->handle.update_settlement( utils::TimeStamp::now(), convert_price(msg.settlementPrice, display_factor), date_of_timestamp(time) );
}
}
@@ -21,7 +21,7 @@ namespace ice {
class ICEListener :
public onixs_ice::ExchangeListener, //One Thread
public onixs_ice::HandlerStateChangeListener, //One thread
public onixs_ice::OrderBookUpdateListener, //One thread
public onixs_ice::OrderBookUpdateListener, //One thread //TODO?
public onixs_ice::FeedListener, //Multi thread
public onixs_ice::ErrorListener, //Multi thread
public onixs_ice::WarningListener //Multi thread
@@ -85,7 +85,6 @@ public:
void onOpenPrice(const onixs_ice::OpenPrice& msg, const onixs_ice::MessageInfo& msgInfo) override;
void onClosePrice(const onixs_ice::ClosePrice& msg, const onixs_ice::MessageInfo& msgInfo) override;
void onEndOfDayMarketSummary(const onixs_ice::EndOfDayMarketSummary& msg, const onixs_ice::MessageInfo& msgInfo) override;
void onMarketStatistics(const onixs_ice::MarketStatistics& msg, const onixs_ice::MessageInfo& msgInfo) override;
// Feed
void onMulticastMessageBlockBegin(onixs_ice::FeedId feedId, const onixs_ice::MessageInfo& msgInfo) override;
@@ -105,8 +104,6 @@ private:
template<typename Definition>
void set_security_common(const Definition& def, FixedSecurity& fsec);
template<typename Definition>
void set_security_specific(const Definition& def, FixedSecurity& fsec);
template<typename Definition>
void on_future(const Definition& def, bool& is_interested);
template<typename Definition>
void on_uds_future_spread(const Definition& def, bool& is_interested);
@@ -124,12 +121,9 @@ private:
SecurityFilterAction filter_security(int exchange_id, const Definition& def)
{
if (_index.has_security(exchange_id))
{
LOG(md,Warn, "Duplicate exchange ID {} - {}", std::to_string(exchange_id), def.contractSymbol);
return SKIP;
}
if(_symbol_filter.count("*") > 0)
return ADD;
// if(_symbol_filter.count("*") > 0)
// return ADD;
return _symbol_filter.count( parse_contract_symbol(def.contractSymbol) ) > 0 ? ADD : SKIP;
}
void flush_books();
@@ -147,25 +141,16 @@ void ICEListener::set_security_common(const Definition& def, FixedSecurity& fsec
{
fsec.numeric_id = def.marketId;
std::string sym = parse_contract_symbol(def.contractSymbol);
if(!sym.empty())
{
fsec.symbol( sym );
fsec.security_desc(def.contractSymbol);
}
else
{
auto id = std::to_string(def.marketId);
fsec.symbol(id);
fsec.security_desc(id);
}
fsec.symbol( sym );
//fsec.security_desc(def.marketDesc);
fsec.security_desc(def.contractSymbol);
fsec.exchange = api::Venue::VENUE_ICE;
fsec.display_factor = 0.0;
fsec.ice_price_denominator = (int8_t)(def.orderPriceDenominator - '0');
fsec.ice_deal_denominator = (int8_t)(def.dealPriceDenominator - '0');
fsec.ice_settle_denominator = (int8_t)(def.settlePriceDenominator - '0');
double min_tick = double_of_price(def.incrementPrice, fsec.ice_price_denominator);
fsec.low_tick = fsec.high_tick = min_tick;
fsec.price_break = 0.0;
fsec.display_factor = (int8_t)(def.orderPriceDenominator - '0');
fsec.ice_deal_display_factor = (int8_t)(def.dealPriceDenominator - '0');
fsec.ice_settle_display_factor = (int8_t)(def.settlePriceDenominator - '0');
double min_tick = double_of_price(def.incrementPrice, fsec.display_factor);
fsec.low_tick = fsec.high_tick = min_tick;
fsec.price_break = 0.;
fsec.ice_market_description(def.marketDesc);
fsec.ice_cleared_alias(def.clearedAlias);
@@ -175,10 +160,6 @@ void ICEListener::set_security_common(const Definition& def, FixedSecurity& fsec
fsec.mic_code(def.micCode);
}
template<typename Definition>
void ICEListener::set_security_specific(const Definition&, FixedSecurity& ) {}
template<typename Definition>
void ICEListener::on_future(const Definition& def, bool& is_interested)
{
@@ -188,7 +169,7 @@ void ICEListener::on_future(const Definition& def, bool& is_interested)
FixedFutureSecurity fsec;
set_security_common(def, fsec);
set_security_specific(def, fsec);
//fsec.cash_per_point = double_of_price(def.tickValue, fsec.display_factor);
fsec.expiration_year = def.maturityYear;
fsec.expiration_month = def.maturityMonth;
@@ -16,25 +16,25 @@ namespace md {
namespace ice {
template <typename OnixPrice>
double double_of_price(const OnixPrice& price, int8_t denominator)
double double_of_price(const OnixPrice& price, int8_t display_factor)
{
double dbl = price / pow10(denominator);
double dbl = price / pow10(display_factor);
return dbl;
}
template <typename OnixsPrice>
IntPrice convert_price(const OnixsPrice& price, int8_t denominator)
IntPrice convert_price(const OnixsPrice& price, int8_t display_factor)
{
double dbl = double_of_price<OnixsPrice>(price, denominator);
double dbl = double_of_price<OnixsPrice>(price, display_factor);
const int PRECISION = 7; //TODO config::get<bts::JetFIX>().connection() case ICE
auto intpx = md::IntPrice_from_double<PRECISION>(dbl);
return intpx;
}
template <typename OnixsPrice>
inline PriceSize pricesize_of_price_size(const OnixsPrice& price, int8_t denominator, Size size)
inline PriceSize pricesize_of_price_size(const OnixsPrice& price, int8_t display_factor, Size size)
{
auto intpx = convert_price<OnixsPrice>(price, denominator);
auto intpx = convert_price<OnixsPrice>(price, display_factor);
PriceSize result({intpx.mantissa(), (int8_t)(intpx.exponent())}, size);
return result;
}
@@ -73,30 +73,11 @@ onixs_ice::MarketSubscriptions market_subcription_for_channel(const ICEChannel&
for(const auto& x : chan.market_types)
{
//onixs_ice::MarketSubType::NonImplied
if(x == 26)
{
onixs_ice::MarketSubscription futures(x, onixs_ice::MarketSubType::NonImplied, onixs_ice::SecurityType::Futures, onixs_ice::BookDepth::FOD);
subs.push_back(futures);
}
else
{
onixs_ice::MarketSubscription futures(x, onixs_ice::MarketSubType::FullImplied, onixs_ice::SecurityType::Futures, onixs_ice::BookDepth::FOD);
subs.push_back(futures);
}
onixs_ice::MarketSubscription futures(x, onixs_ice::MarketSubType::FullImplied, onixs_ice::SecurityType::Futures, onixs_ice::BookDepth::FOD);
onixs_ice::MarketSubscription spreads(x, onixs_ice::MarketSubType::FullImplied, onixs_ice::SecurityType::UdsFuturesMarkets, onixs_ice::BookDepth::FOD);
subs.push_back(futures);
subs.push_back(spreads);
}
for(const auto& x : chan.uds_market_types)
{
if(x == 26)
{
onixs_ice::MarketSubscription spreads(x, onixs_ice::MarketSubType::NonImplied, onixs_ice::SecurityType::UdsFuturesMarkets, onixs_ice::BookDepth::FOD);
subs.push_back(spreads);
}
else
{
onixs_ice::MarketSubscription spreads(x, onixs_ice::MarketSubType::FullImplied, onixs_ice::SecurityType::UdsFuturesMarkets, onixs_ice::BookDepth::FOD);
subs.push_back(spreads);
}
}
return subs;
}
@@ -137,16 +118,7 @@ void ICEMain::start(std::vector<UserSymbol>& symbols)
LOG(md,Info, "ICE: Init Handler {}", pair.first.to_string());
sleep_for(16s);
onixs_ice::MarketSubscriptions subs = market_subcription_for_channel(pair.first);
try
{
pair.second->start(subs);
}
catch (std::exception& e)
{
LOG(md,Error,"handler->start ONIXSERROR {}", std::string(e.what()));
throw;
}
pair.second->start(subs);
}
LOG(md,Info, "** ICE Publisher started **");
}
@@ -228,9 +200,8 @@ unique_ptr<onixs_ice::Handler> ICEMain::prepare_handler(const ICEChannel& channe
auto handler = unique_ptr<onixs_ice::Handler>(new onixs_ice::Handler(settings));
return handler;
}
catch (std::exception& e)
{
LOG(md,Error,"handler create ONIXSERROR {}", std::string(e.what()));
catch (std::exception& e) {
LOG(md,Error,"ONIXSERROR{}", std::string(e.what()));
throw;
}
}
@@ -250,20 +221,13 @@ unique_ptr<ICEListener> ICEMain::prepare_listener(onixs_ice::Handler& handler, c
for (auto& symbol : channel.symbols)
listener->add_filter_symbol(symbol.symbol());
try
{
handler.registerExchangeListener(listener.get());
handler.registerFeedListener(listener.get());
handler.registerOrderBookUpdateListener(listener.get());
handler.registerErrorListener(listener.get());
handler.registerWarningListener(listener.get());
handler.registerHandlerStateChangeListener(listener.get());
}
catch (std::exception& e)
{
LOG(md,Error,"handler register ONIXSERROR {}", std::string(e.what()));
throw;
}
handler.registerExchangeListener(listener.get());
handler.registerFeedListener(listener.get());
handler.registerOrderBookUpdateListener(listener.get());
handler.registerErrorListener(listener.get());
handler.registerWarningListener(listener.get());
handler.registerHandlerStateChangeListener(listener.get());
return listener;
}
@@ -25,10 +25,11 @@ using std::size_t;
namespace bts {
namespace md {
MDP3Main::MDP3Main() :
MDP3Main::MDP3Main(MBOWriter* mbo) :
_index(),
_recorder ({ utils::Dispatcher::current(), [=](ExchangeKey k) { return SecurityKey(_index.get_key(k.value())); } }),
_producer(PLATFORM_MDP3ONIXS, _recorder ),
_producer(PLATFORM_MDP3ONIXS, _recorder),
_mbo(mbo),
// _settlement_recorder(PLATFORM_MDP3ONIXS),
_engines(),
_handlers(),
@@ -117,8 +118,7 @@ map<string, unique_ptr<onixs::FeedEngine>> create_feed_engines(const vector<CMEC
return result;
}
onixs::SessionSettings session_settings_for_channel(const string& channel_id, MBOWriter* mbo) {
const auto& options = channel_settings_for(channel_id);
onixs::SessionSettings session_settings_for_channel(const CMEOptions::CMEChannel& options, MBOWriter* mbo) {
onixs::SessionSettings settings;
if (mbo) {
@@ -139,38 +139,63 @@ onixs::SessionSettings session_settings_for_channel(const string& channel_id, MB
settings.joinRecovery(onixs::JoinRecoveryOptions::Disabled);
settings.gapAndErrorHandling(onixs::GapAndErrorHandlingOptions::ContinueProcessing);
}
// if (options.sunday_pre_open() && datetime::is_local_time_sunday()) {
// LOG(md,Info,"Setting pre-open flag for channel {}", channel_id);
// settings.joinRecovery(onixs::JoinRecoveryOptions::Disabled);
// }
return settings;
}
void MDP3Main::start(std::vector<UserSymbol>& symbols, MBOWriter* mbo) {
void MDP3Main::start(std::vector<UserSymbol>& symbols) {
await_cme_config();
initialize();
const auto& channels = parse_channels(symbols);
_engines = create_feed_engines(channels);
for (const auto& channel : channels) {
unique_ptr<onixs::Handler> phandler = prepare_handler(channel.id, mbo);
_listeners.push_back(prepare_listener(*phandler, channel, mbo));
_handlers.insert(std::make_pair(channel.id, move(phandler)));
unique_ptr<onixs::Handler> phandler = prepare_handler(channel.id);
_listeners.push_back(prepare_listener(*phandler, channel));
_handlers.insert(std::make_pair(channel.id, ChannelHandler{ false, move(phandler)} ));
std::stringstream symstr;
for (const auto& sym : channel.symbols) { symstr << sym.symbol() << "-" << SecurityType_Name(sym.type()) << " "; }
LOG(md,Info, "CME: Initialized channel {} ({})",channel.id,symstr.str());
}
for (auto& pair : _handlers) {
onixs::SessionSettings settings = session_settings_for_channel(pair.first, mbo);
pair.second->start(settings);
}
start_handlers();
LOG(md,Info, "** CME MDP3 Publisher started **");
}
bool should_start(const CMEOptions::CMEChannel& options) {
if (options.sunday_pre_open() &&
datetime::is_local_time_near_sunday_sunday() ) {
return false;
}
return true;
}
void MDP3Main::start_handlers() {
size_t count = 0;
for (auto& pair : _handlers) {
const auto& options = channel_settings_for(pair.first);
if (!pair.second.started && should_start(options)) {
onixs::SessionSettings settings = session_settings_for_channel(options, _mbo);
pair.second.handler->start(settings);
pair.second.started = true;
LOG(md,Info, "Started handler {}", pair.first);
}
if(pair.second.started) ++count;
}
if (count != _handlers.size()) {
// If some handlers were not started try again later
utils::Dispatcher::current().post([this]() { start_handlers(); }, /*1 hour*/ 60*60*1000);
}
}
void MDP3Main::send_heartbeats() {
for (const auto& listener: _listeners)
for (const auto& listener: _listeners) {
listener->heartbeat();
// utils::DispatcherTimer settlement_timer(disp, 100, [&]() {
// _settlement_recorder.do_work();
// });
// settlement_timer.start();
}
}
void MDP3Main::initialize() {
@@ -197,7 +222,7 @@ void MDP3Main::initialize() {
// //
// Initialize HandlerSettings and allocate the channel Handler
unique_ptr<onixs::Handler> MDP3Main::prepare_handler(const string& channel_id, MBOWriter* mbo) {
unique_ptr<onixs::Handler> MDP3Main::prepare_handler(const string& channel_id) {
const auto& pub_options = config::get<PublisherOptions>();
const auto& options = channel_settings_for(channel_id);
LOG(md,Info,"Loaded channel options for channel {}:\n{}",channel_id ,options.DebugString());
@@ -210,7 +235,7 @@ unique_ptr<onixs::Handler> MDP3Main::prepare_handler(const string& channel_id, M
settings.bookManagement().directBooks().maintain(true);
settings.bookManagement().impliedBooks().maintain(true);
settings.bookManagement().consolidatedBooks().maintain(false);
if (options.validate_mbo() && mbo != nullptr) {
if (options.validate_mbo() && _mbo != nullptr) {
settings.bookManagement().mboBooks().maintain(true);
}
@@ -340,14 +365,14 @@ unique_ptr<onixs::Handler> MDP3Main::prepare_handler(const string& channel_id, M
//
// Create a listener for this channel and register callbacks
unique_ptr<MDP3Listener> MDP3Main::prepare_listener(onixs::Handler& handler, const CMEChannel& channel, MBOWriter* mbo) {
unique_ptr<MDP3Listener> MDP3Main::prepare_listener(onixs::Handler& handler, const CMEChannel& channel) {
// We need to get a handler to the producer channels so we can produce heartbeats
vector<MDProducerChannel> producer_channels;
for (auto& symbol : channel.symbols) {
producer_channels.push_back(_producer.get_channel(symbol.symbol().c_str(), symbol.type(), symbol.exchange()));
}
unique_ptr<MDP3Listener> listener(new MDP3Listener(_index, _producer, mbo, producer_channels));
unique_ptr<MDP3Listener> listener(new MDP3Listener(_index, _producer, _mbo, producer_channels));
for (auto& symbol : channel.symbols) {
listener->add_filter_symbol(symbol.symbol());
}
@@ -26,18 +26,26 @@ struct CMEChannel;
* There is a single listener for all callbacks which maps the exchange id to the MDProducerHandle and writes
* the data to it.
*/
struct ChannelHandler {
bool started;
std::unique_ptr<onixs::Handler> handler;
};
class MDP3Main : public IMDPlatform
{
public:
MDP3Main();
MDP3Main(MBOWriter*);
~MDP3Main();
void start(std::vector<UserSymbol>&, MBOWriter*);
void start(std::vector<UserSymbol>&);
void send_heartbeats() override;
void initialize();
std::unique_ptr<onixs::Handler> prepare_handler(const std::string& channel, MBOWriter*);
std::unique_ptr<MDP3Listener> prepare_listener(onixs::Handler& handler, const CMEChannel& channel, MBOWriter*);
std::unique_ptr<onixs::Handler> prepare_handler(const std::string& channel);
std::unique_ptr<MDP3Listener> prepare_listener(onixs::Handler& handler, const CMEChannel& channel);
void start_handlers();
private:
BTS_NO_COPY(MDP3Main);
@@ -45,9 +53,10 @@ private:
CMESecurityIndex _index;
SecurityIDRecorder _recorder;
MDProducer _producer;
MBOWriter* _mbo;
// co2::SettlementRecorder _settlement_recorder;
std::map<std::string, std::unique_ptr<onixs::FeedEngine>> _engines;
std::map<std::string, std::unique_ptr<onixs::Handler>> _handlers;
std::map<std::string, ChannelHandler> _handlers;
std::vector<std::unique_ptr<MDP3Listener>> _listeners;
std::vector<std::unique_ptr<onixs::TcpRecoveryService>> _recovery;
};
+4 -5
View File
@@ -76,9 +76,9 @@ void run_onixs(MBOWriter* mbo) {
get_system_md_symbols(api::VENUE_GLBX, api::SECURITYTYPE_UNSET, &cme_symbols);
if(cme_symbols.size() > 0)
{
MDP3Main* main = new MDP3Main();
MDP3Main* main = new MDP3Main(mbo);
std::shared_ptr<IMDPlatform> ptr(main);
main->start(cme_symbols, mbo);
main->start(cme_symbols);
platforms.push_back(ptr);
}
@@ -152,9 +152,8 @@ void run_market_datapublishers(MBOWriter* mbo) {
}));
if (config::get<MarketDataConfig>().use_sim()) {
threading::make_thread("ExchangeSimGLBX", [mbo]() { sim::start_exchange_sim(api::Venue::VENUE_SIM, mbo); }).detach();
//threading::make_thread("ExchangeSimICE", [mbo]() { sim::start_exchange_sim(api::Venue::VENUE_SIMICE, mbo); }).detach();
//TODO I'll need Eric's help to disambiguate replay / relay here
threading::make_thread("ExchangeSim", [mbo]() { sim::start_exchange_sim(mbo); })
.detach();
}
boot_sleep();
}
Loaded 100 of 115 files, more files were not shown because too many files have changed in this diff. Show more