Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd5c680155 |
No files matched your search
+1
-1
@@ -7,7 +7,7 @@ zola_path=$(readlink -f "../../externals/linux/bin/zola/zola")
|
||||
|
||||
mkdir -p $temp_path
|
||||
cp -r ./* $temp_path
|
||||
|
||||
cp -r ../../src/sdk/doc/* $temp_path/content/bts_spark_sdk/Server/
|
||||
|
||||
cd $temp_path
|
||||
$zola_path build -u '/docs/' -o $1 >$tmpfile 2>&1
|
||||
|
||||
@@ -97,7 +97,7 @@ namespace mbts.spark {
|
||||
|
||||
public event Action visible_columns_changed;
|
||||
|
||||
public IEnumerable<ColumnType> visible_column_types =>
|
||||
public IEnumerable<ColumnType> visible_columns =>
|
||||
columns.Where(c => c.settings.show)
|
||||
.Select(c => c.column_type);
|
||||
|
||||
@@ -253,7 +253,6 @@ namespace mbts.spark {
|
||||
#endregion
|
||||
|
||||
Column[] columns { get; set; } = new Column[0];
|
||||
IEnumerable<Column> _visible_columns => columns.Where(c => c.settings.show);
|
||||
|
||||
public void drag_out_of_bounds() =>
|
||||
_tactile_adorner?.drag_out_of_bounds();
|
||||
@@ -331,7 +330,7 @@ namespace mbts.spark {
|
||||
|
||||
#region Column Utility Methods
|
||||
Column _column_for_point(Point point) =>
|
||||
_visible_columns.FirstOrDefault(c => c.x_right > point.X, columns.Length > 0 ? columns[columns.Length - 1] : Column.Empty);
|
||||
columns.FirstOrDefault(c => c.x_right > point.X, columns.Length > 0 ? columns[columns.Length - 1] : Column.Empty);
|
||||
|
||||
double _column_start(ColumnType col_type) =>
|
||||
columns.TakeWhile(c => c.column_type != col_type).Sum(c => c.settings.width);
|
||||
@@ -914,4 +913,4 @@ namespace mbts.spark {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,14 +38,6 @@ namespace mbts.spark {
|
||||
font_weight = FontWeights.SemiBold.ToOpenTypeWeight()
|
||||
};
|
||||
|
||||
public static LadderColumnSettings DefaultPiqColumnSettings => new LadderColumnSettings {
|
||||
show = false,
|
||||
width = 50,
|
||||
font_family = "Segoe UI",
|
||||
font_size = 10,
|
||||
font_weight = FontWeights.SemiBold.ToOpenTypeWeight()
|
||||
};
|
||||
|
||||
[ProtoMember(1)]
|
||||
public bool show { get; set; }
|
||||
[ProtoMember(2)]
|
||||
@@ -258,7 +250,7 @@ namespace mbts.spark {
|
||||
ask_column = LadderColumnSettings.Default,
|
||||
price_column = LadderColumnSettings.Default,
|
||||
last_column = LadderColumnSettings.Default,
|
||||
piq_column = LadderColumnSettings.DefaultPiqColumnSettings;
|
||||
piq_column = LadderColumnSettings.Default;
|
||||
orders_column.background = BTSColors.LadderSpecial.default_column_background;
|
||||
bid_column.foreground = 0xFFFFFF;
|
||||
bid_column.background = BTSColors.MarketData.bid;
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace mbts.spark {
|
||||
InitializeComponent();
|
||||
_column_headers_presenter.Columns = new GridViewColumnCollection();
|
||||
_ladder.visible_columns_changed += () => _column_headers_presenter.Columns.SetItems(
|
||||
_ladder.visible_column_types.Select(t => ColumnFactory.create(_ladder, t)));
|
||||
_ladder.visible_columns.Select(t => ColumnFactory.create(_ladder, t)));
|
||||
this.vm = vm;
|
||||
DataContext = vm;
|
||||
DataContextChanged += datacontext_changed;
|
||||
|
||||
@@ -35,7 +35,6 @@ namespace mbts.co2
|
||||
public readonly IntPtr hot;
|
||||
public readonly IntPtr cold_data;
|
||||
public readonly IntPtr cold_header;
|
||||
private readonly IntPtr unused_mbo;
|
||||
}
|
||||
|
||||
[DllImport("libspark")]
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace bts.tests
|
||||
return securities;
|
||||
}
|
||||
|
||||
[Test(Timeout = 30)]
|
||||
[Test(Timeout = 30)]
|
||||
public async Task test_position_limits() {
|
||||
string test_symbol = "CL";
|
||||
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using bts.api.core;
|
||||
using bts.md;
|
||||
using CommandLine;
|
||||
using System.Linq;
|
||||
|
||||
namespace bts {
|
||||
|
||||
[Verb("mbo", HelpText="MBO diagnostic command")]
|
||||
public class MBOCommandOptions {
|
||||
[Option('k', "key", Required = true)]
|
||||
public UInt32 key { get; set; }
|
||||
|
||||
[Option('s', "side", Default = api.Side.Undefined)]
|
||||
public api.Side side { get; set; }
|
||||
}
|
||||
|
||||
public class MBOCommand {
|
||||
public static int Run(MBOCommandOptions o) {
|
||||
dump_mbo(o.key, o.side);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dump_mbo(UInt32 key, api.Side side) {
|
||||
using (var ctx = new ServiceContext()) {
|
||||
var mbo = ctx.locate<MBOService>();
|
||||
var data = mbo.get_orders_for_security(new MBOSecurityQuery { SecurityId = key });
|
||||
|
||||
Console.WriteLine($"Order data for {data.SecurityId}");
|
||||
IEnumerable<OrderPosition> orders = data.Bid;
|
||||
switch(side) {
|
||||
case api.Side.Undefined:
|
||||
orders = data.Ask.Concat(data.Bid);
|
||||
break;
|
||||
case api.Side.Buy:
|
||||
orders = data.Bid;
|
||||
break;
|
||||
case api.Side.Sell:
|
||||
orders = data.Ask;
|
||||
break;
|
||||
}
|
||||
var price = 0.0;
|
||||
foreach(var e in orders) {
|
||||
if (e.Price != price) {
|
||||
price = e.Price;
|
||||
Console.WriteLine("================");
|
||||
}
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
using bts.api;
|
||||
using bts.api.core;
|
||||
using bts.api.orderman;
|
||||
using bts.co2;
|
||||
using bts.test;
|
||||
using CommandLine;
|
||||
using mbts.co2;
|
||||
using mbts.config;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace bts {
|
||||
|
||||
[Verb("orderstress", HelpText = "Create a bunch of orders")]
|
||||
public class OrderStressOptions {
|
||||
// Maybe options to create fewer orders or sleep
|
||||
|
||||
[Option('s', "sleep", HelpText = "Sleep ms between order submission", Default = 100)]
|
||||
public int sleep { get; set; }
|
||||
|
||||
[Option('d', "depth", HelpText = "How many orders per side", Default = 10u)]
|
||||
public uint depth { get; set; }
|
||||
|
||||
[Option('q', "quanityt", HelpText = "Order quantity", Default = 1u)]
|
||||
public uint quantity { get; set; }
|
||||
};
|
||||
|
||||
public struct Market {
|
||||
public SecurityImmutable security;
|
||||
public IntPrice? bid;
|
||||
public IntPrice? ask;
|
||||
}
|
||||
|
||||
public static class OrderStress {
|
||||
static IEnumerable<Market> all_markets(ServiceContext ctx) {
|
||||
var channels =
|
||||
UserSymbol.get_all()
|
||||
.Select(u =>
|
||||
new SecurityChannel() {
|
||||
Time = 0,
|
||||
Flags = (int)(MDRequest.Types.Flags.Direct | MDRequest.Types.Flags.Implied),
|
||||
Type = u.type,
|
||||
Symbol = u.symbol,
|
||||
Exchange = u.exchange
|
||||
}
|
||||
);
|
||||
var request = new MDRequest() { Host = "system_test" };
|
||||
request.Channels.AddRange(channels);
|
||||
|
||||
var relay = ctx.locate<MarketDataRelay>();
|
||||
System.Threading.Thread.Sleep(100);
|
||||
var result = relay.requestmd(request);
|
||||
|
||||
foreach (var ch in result.Channels) {
|
||||
foreach (var update in ch.Updates) {
|
||||
if (update.Security != null) {
|
||||
var m = new Market() {
|
||||
security = new SecurityImmutable(update.Security),
|
||||
bid = best(
|
||||
(a,b) => a > b ? a : b,
|
||||
update.Direct?.Bids?.FirstOrDefault(), update.Implied?.Bids?.FirstOrDefault()),
|
||||
ask = best(
|
||||
(a,b) => a < b ? a : b,
|
||||
update.Direct?.Asks?.FirstOrDefault(), update.Implied?.Asks?.FirstOrDefault())
|
||||
};
|
||||
if (m.bid.HasValue || m.ask.HasValue) {
|
||||
yield return m;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static IntPrice? best(Func<IntPrice, IntPrice,IntPrice> comp, params PriceSizeMessage[] ps) {
|
||||
IntPrice? result = null;
|
||||
foreach (var p in ps) {
|
||||
if (p != null) {
|
||||
var ip = new IntPrice(p.Mantissa, (sbyte)p.Exponent);
|
||||
if (result == null) {
|
||||
result = ip;
|
||||
}
|
||||
else {
|
||||
result = comp(result.Value, ip);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static Create mkorder(uint security, double price, uint size, Side side) {
|
||||
return new Create {
|
||||
Price = price,
|
||||
Quantity = size,
|
||||
NewOrder = new OrderDefinition {
|
||||
SecurityKey = security,
|
||||
Side = side,
|
||||
TimeInForce = TimeInForce.Day,
|
||||
ManualOrderIndicator = ManualOrderIndicator.Yes,
|
||||
CtiCode = CTICode.CtiCode1,
|
||||
CustomerOrFirm = CustomerOrFirm.Firm,
|
||||
AccountId = 1,
|
||||
UserId = 1,
|
||||
CustomDef = new CustomOrderDefinition {
|
||||
Limit = new LimitOrderDefinition()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static int Run(OrderStressOptions o) {
|
||||
|
||||
var ctx = new ServiceContext();
|
||||
ConsoleEx.WriteLine("Please log in to Spark", ConsoleColor.Yellow);
|
||||
ConsoleEx.Write("Username: ", ConsoleColor.Yellow);
|
||||
var name = Console.ReadLine();
|
||||
ConsoleEx.Write("Password: ", ConsoleColor.Yellow);
|
||||
var pw = Console.ReadLine();
|
||||
|
||||
var login_result = ctx.login(name, pw);
|
||||
if (!login_result.Result.success) {
|
||||
ConsoleEx.WriteLine("Invalid Credentials", ConsoleColor.Red);
|
||||
}
|
||||
|
||||
if (Configuration.get<config.DeploymentType>().type.ToUpper() == "PROD") {
|
||||
ConsoleEx.WriteLine("Refusing to run on production system", ConsoleColor.Red);
|
||||
return -1;
|
||||
}
|
||||
|
||||
var orders = ctx.locate<OrderService>();
|
||||
foreach (var m in all_markets(ctx)) {
|
||||
ConsoleEx.WriteLine(m.security.security_desc(), ConsoleColor.White);
|
||||
var tick = m.security.ContractSpec.LowTick;
|
||||
if (m.ask.HasValue) {
|
||||
for (var x = 0; x < o.depth; ++x) {
|
||||
var price = m.ask.Value.price() + (tick * x);
|
||||
ConsoleEx.WriteLine($"Sell {o.quantity} at {price}", ConsoleColor.Red);
|
||||
orders.create_order_async(mkorder(m.security.Id, price, o.quantity, Side.Sell));
|
||||
System.Threading.Thread.Sleep(o.sleep);
|
||||
}
|
||||
}
|
||||
if (m.bid.HasValue) {
|
||||
// start at bid and place 1 order at 10 levels
|
||||
for (var x=0; x < o.depth; ++x) {
|
||||
var price = m.bid.Value.price() - (tick * x);
|
||||
ConsoleEx.WriteLine($"Buy {o.quantity} at {price}", ConsoleColor.Blue);
|
||||
orders.create_order_async(mkorder(m.security.Id, price, o.quantity, Side.Buy));
|
||||
System.Threading.Thread.Sleep(o.sleep);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,9 +17,16 @@ namespace bts {
|
||||
[Option(nameof(admin))]
|
||||
public bool admin { get; set; }
|
||||
|
||||
[Option(nameof(mbo))]
|
||||
public bool mbo { get; set; }
|
||||
|
||||
[Option("key")]
|
||||
public UInt32 key { get; set; }
|
||||
|
||||
[Option("side")]
|
||||
public api.Side side { get; set; }
|
||||
}
|
||||
|
||||
[Verb("servicetest", HelpText="Scratch space for testing services")]
|
||||
public class ServiceTest {
|
||||
public static int Run(ServiceTestOptions o) {
|
||||
if (o.synthetic) {
|
||||
@@ -31,6 +38,9 @@ namespace bts {
|
||||
if (o.admin) {
|
||||
admin_test();
|
||||
}
|
||||
if (o.mbo) {
|
||||
mbo_test(o);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -41,6 +51,25 @@ namespace bts {
|
||||
return "";
|
||||
}
|
||||
|
||||
private static void mbo_test(ServiceTestOptions o) {
|
||||
var key = o.key;
|
||||
var side = o.side;
|
||||
using (var ctx = new ServiceContext()) {
|
||||
var mbo = ctx.locate<MBOService>();
|
||||
var data = mbo.get_orders_for_security(new MBOSecurityQuery { SecurityId = key });
|
||||
|
||||
Console.WriteLine($"Order data for {data.SecurityId}");
|
||||
var vector = side == api.Side.Buy ? data.Bid : data.Ask;
|
||||
var price = 0.0;
|
||||
foreach(var e in vector) {
|
||||
if (e.Price != price) {
|
||||
price = e.Price;
|
||||
Console.WriteLine("================");
|
||||
}
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void synthetic_test() {
|
||||
using (var ctx = new ServiceContext()) {
|
||||
|
||||
@@ -13,48 +13,47 @@ using System.Reflection;
|
||||
namespace sparkcmd {
|
||||
class Program {
|
||||
|
||||
// static object option<T>(Func<T,int> run) {return run;}
|
||||
// static Type argType(object arg) {
|
||||
// return arg.GetType().GetGenericArguments().First();
|
||||
// }
|
||||
// static int Run(Func<IEnumerable<Error>,int> on_error, params object[] args) {
|
||||
// var types = args.Select(argType).ToArray();
|
||||
// var parse = CommandLine.Parser.Default.GetType().GetMethod("ParseArguments", BindingFlags.Public).MakeGenericMethod(types);
|
||||
// return 3;
|
||||
// }
|
||||
static object option<T>(Func<T, int> run) { return run; }
|
||||
static Type argType(object arg) {
|
||||
return arg.GetType().GetGenericArguments().First();
|
||||
}
|
||||
static int Run(Func<IEnumerable<Error>, int> on_error, params Type[] runners) {
|
||||
var run_methods =
|
||||
runners
|
||||
.Select(r => r.GetMethod("Run", BindingFlags.Static | BindingFlags.Public))
|
||||
.ToList();
|
||||
var args =
|
||||
run_methods
|
||||
.Select(m => m.GetParameters().First().GetType());
|
||||
|
||||
var parser = Parser.Default.GetType().GetMethod("ParseArguments", new[] { typeof(IEnumerable<string>) });
|
||||
|
||||
//var types = args.Select(argType).ToArray();
|
||||
//var parse = CommandLine.Parser.Default.GetType().GetMethod("ParseArguments", BindingFlags.Public).MakeGenericMethod(types);
|
||||
return 3;
|
||||
}
|
||||
static int Main(string[] args) {
|
||||
mbts.utils.BTSNativeMethods.provide_command_line(args, args.Length);
|
||||
// note: this can be made to infer the options type list from the list of delegates
|
||||
return Parser.Default
|
||||
.ParseArguments<
|
||||
ConfigcheckOptions,
|
||||
ScriptClientOptions,
|
||||
TailServiceOptions,
|
||||
ServiceTestOptions,
|
||||
SettingsManagerOptions,
|
||||
TestCommandOptions,
|
||||
OrderStressOptions,
|
||||
MBOCommandOptions
|
||||
>(args)
|
||||
.MapResult<
|
||||
ConfigcheckOptions,
|
||||
ScriptClientOptions,
|
||||
TailServiceOptions,
|
||||
ServiceTestOptions,
|
||||
SettingsManagerOptions,
|
||||
TestCommandOptions,
|
||||
OrderStressOptions,
|
||||
MBOCommandOptions,
|
||||
int>(
|
||||
Configcheck.Run,
|
||||
ScriptClientCommand.Run,
|
||||
TailService.Run,
|
||||
ServiceTest.Run,
|
||||
SettingsManagerCommand.Run,
|
||||
TestCommand.Run,
|
||||
OrderStress.Run,
|
||||
MBOCommand.Run,
|
||||
errors => 1);
|
||||
|
||||
//return Parser.Default
|
||||
//.ParseArguments<ConfigcheckOptions,ScriptClientOptions,TailServiceOptions,ServiceTestOptions,SettingsManagerOptions,TestCommandOptions>(args)
|
||||
//.MapResult<ConfigcheckOptions,ScriptClientOptions,TailServiceOptions,ServiceTestOptions,SettingsManagerOptions,TestCommandOptions,int>(
|
||||
// Configcheck.Run,
|
||||
// ScriptClientCommand.Run,
|
||||
// TailService.Run,
|
||||
// ServiceTest.Run,
|
||||
// SettingsManagerCommand.Run,
|
||||
// TestCommand.Run,
|
||||
// errors => 1);
|
||||
|
||||
return Run(
|
||||
errors => 1,
|
||||
typeof(Configcheck),
|
||||
typeof(ScriptClientCommand),
|
||||
typeof(TailService),
|
||||
typeof(ServiceTest),
|
||||
typeof(SettingsManagerCommand),
|
||||
typeof(TestCommand));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,21 @@
|
||||
<license version="1.0">
|
||||
<type>production</type>
|
||||
<customer>
|
||||
<name>Blue Trading Systems OF 9420-2</name>
|
||||
<name>Blue Trading Systems</name>
|
||||
</customer>
|
||||
<period>
|
||||
<since>2019-05-02</since>
|
||||
<till>2020-05-13</till>
|
||||
<since>2018-08-30</since>
|
||||
<till>2019-10-16</till>
|
||||
</period>
|
||||
<dotNetProducts>
|
||||
<product id="41" name="FIX Analyser" />
|
||||
</dotNetProducts>
|
||||
<dotNetCheckSum>6O68+aAtrLqRaXxY9hLigajhC2ZunVeIev3NbyEXFjHk61WFrNmRTjy6tEduDtFUvGXvS6VUW3VXASaMTLrRgYteZBzfp7+dFTfVIVbzv6cn7c7dnSxWCGO5zPrjXw9cxMXlFz9cshyue6U/DRR5J36ThOhgt2kpY/OP9cgXWJo=</dotNetCheckSum>
|
||||
<products>
|
||||
<product id="1" name="OnixS FIX Engine for C++" />
|
||||
<product id="4" name="CME Market Data Handler for C++" />
|
||||
<product id="7" name="ICE iMpact Multicast Price Feed Handler for C++" />
|
||||
<product id="67" name="Eurex Market and Reference Data Interfaces (EMDI, RDI) Handler for C++" />
|
||||
<product id="13" name="NYSE ArcaBook Multicast for Equities Handler for C++" />
|
||||
</products>
|
||||
<checksum>5E50A1DACD94D7C1BECD316EEAE5AB02</checksum>
|
||||
<checksum>18F98ED1E0A87B4B11DA322403D7BDDD</checksum>
|
||||
</license>
|
||||
@@ -81,6 +81,11 @@ namespace api {
|
||||
for (size_t x = 0; x < raw.added_keys.size(); ++x) {
|
||||
(*state)[raw.added_keys[x]] = raw.added_items[x];
|
||||
}
|
||||
std::vector<T> all;
|
||||
all.reserve(state->size());
|
||||
for (const auto& item : *state) {
|
||||
all.push_back(item.second);
|
||||
}
|
||||
//
|
||||
// Change
|
||||
std::vector<Change<T>> changed;
|
||||
@@ -89,13 +94,6 @@ namespace api {
|
||||
changed.push_back(Change<T>{(*state)[raw.changed_keys[x]], raw.changed_items[x]});
|
||||
(*state)[raw.changed_keys[x]] = raw.changed_items[x];
|
||||
}
|
||||
//
|
||||
// All
|
||||
std::vector<T> all;
|
||||
all.reserve(state->size());
|
||||
for (const auto& item : *state) {
|
||||
all.push_back(item.second);
|
||||
}
|
||||
|
||||
return Update<T, TKey, ServiceType>(all, raw.added_items, changed, removed);
|
||||
}
|
||||
|
||||
@@ -148,14 +148,14 @@ std::optional<uint32_t> search_orders(const ExchangeOrderKey oid, const std::vec
|
||||
const auto& oo = orders[x];
|
||||
if (oo.id == oid) {
|
||||
if (oo.price == price) return { position };
|
||||
else return 0;
|
||||
else return 0 ;
|
||||
}
|
||||
else if (price == oo.price) {
|
||||
position += oo.size;
|
||||
position += 1;
|
||||
}
|
||||
else {
|
||||
price = oo.price;
|
||||
position = oo.size;
|
||||
position = 1;
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#include "lib/api/public/ServiceContext.h"
|
||||
#include "lib/api/services/MBOService.server.pb.h"
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
namespace bts {
|
||||
namespace utils { class Dispatcher; }
|
||||
@@ -25,5 +24,4 @@ class MBOServiceServer : public MBOServiceBase {
|
||||
|
||||
};
|
||||
|
||||
|
||||
}} //namespace
|
||||
@@ -9,10 +9,6 @@
|
||||
|
||||
namespace bts {
|
||||
namespace md {
|
||||
|
||||
// fwd declare from MBOServiceServer.cpp
|
||||
std::optional<uint32_t> search_orders(const ExchangeOrderKey oid, const std::vector<SnapshotOrder>& orders);
|
||||
|
||||
namespace test {
|
||||
int mbo_tests = 0;
|
||||
|
||||
@@ -206,7 +202,6 @@ TEST_CASE("MBO sort order", "[md][mbo]") {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("MBO change price and size", "[md][mbo]") {
|
||||
// When an order's size goes up it gets a new priority
|
||||
Co2TestInstrument instr { "MBO", api::SECURITYTYPE_FUTURE };
|
||||
@@ -293,27 +288,7 @@ TEST_CASE("MBO change price and size", "[md][mbo]") {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Do some tests on the snapshot
|
||||
MBOSnapshot result;
|
||||
copy_to_snapshot(state, &result);
|
||||
|
||||
auto ask30 = search_orders(ExchangeOrderKey(701267928346), result.asks);
|
||||
REQUIRE(ask30);
|
||||
REQUIRE(*ask30 == 0);
|
||||
|
||||
auto bid2875 = search_orders(ExchangeOrderKey(701267993135), result.bids);
|
||||
REQUIRE(bid2875);
|
||||
REQUIRE(*bid2875 == 20);
|
||||
|
||||
bid2875 = search_orders(ExchangeOrderKey(701267299079), result.bids);
|
||||
REQUIRE(bid2875);
|
||||
REQUIRE(*bid2875 == 6);
|
||||
|
||||
auto not_bid = search_orders(ExchangeOrderKey(701967299879), result.bids);
|
||||
auto not_ask = search_orders(ExchangeOrderKey(701967299879), result.asks);
|
||||
REQUIRE(!not_bid);
|
||||
REQUIRE(!not_ask);
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace cmd {
|
||||
|
||||
int RunSim::execute(std::vector<std::string> const &)
|
||||
{
|
||||
sim::start_exchange_sim(nullptr);
|
||||
sim::start_exchange_sim();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "lib/domain_model/Security.pb.h"
|
||||
#include "lib/md/relay/RelayRecorder.h"
|
||||
#include "lib/md/IntPrice.h"
|
||||
#include "lib/md/MBOProcessor.h"
|
||||
|
||||
#include <set>
|
||||
|
||||
@@ -125,7 +124,7 @@ struct MDPlayer : md::IRelayWriter
|
||||
};
|
||||
|
||||
|
||||
int start_exchange_sim(md::MBOWriter* mbo)
|
||||
int start_exchange_sim()
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -138,7 +137,7 @@ int start_exchange_sim(md::MBOWriter* mbo)
|
||||
std::istringstream str{str_settings};
|
||||
FIX::SessionSettings settings( str );
|
||||
|
||||
ex_sim::ExchangeSimApplication application(mbo);
|
||||
ex_sim::ExchangeSimApplication application;
|
||||
FIX::FileStoreFactory storeFactory( settings );
|
||||
FIX::FileLogFactory logFactory( settings );
|
||||
FIX::SocketAcceptor acceptor( application, storeFactory, settings, logFactory );
|
||||
|
||||
@@ -3,9 +3,8 @@
|
||||
#include <memory>
|
||||
|
||||
namespace bts {
|
||||
namespace md { class MBOWriter; }
|
||||
namespace sim {
|
||||
|
||||
int start_exchange_sim(md::MBOWriter*);
|
||||
int start_exchange_sim();
|
||||
|
||||
}}
|
||||
@@ -10,14 +10,12 @@
|
||||
#include "lib/md/Shm/FixedSecurity.h"
|
||||
#include "lib/md/Shm/MDStructure.h"
|
||||
#include "lib/md/get_symbols.h"
|
||||
#include "lib/md/MBOProcessor.h"
|
||||
#include "lib/utils/Dispatcher.h"
|
||||
#include "lib/utils/datetime.h"
|
||||
#include "server/sparkd/exchange_sim/book/Order.h"
|
||||
#include "server/sparkd/exchange_sim/book/OrderMatcher.h"
|
||||
#include "server/sparkd/exchange_sim/book/book_transform.h"
|
||||
#include "lib/persistence/SqliteStore.h"
|
||||
#include "lib/orderman/orderman_utils/fix_order_codec.h"
|
||||
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include <fmt/format.h>
|
||||
@@ -99,20 +97,14 @@ struct ExchangeSimApplication::MDConsumerRec {
|
||||
utils::TimeStamp last_read;
|
||||
};
|
||||
|
||||
inline FIX::OrderID exchange_key(const std::string& clOrdID) {
|
||||
return FIX::OrderID(clOrdID.substr(3));
|
||||
}
|
||||
|
||||
struct ExchangeSimApplication::PImpl {
|
||||
PImpl(md::MBOWriter* mbo)
|
||||
PImpl()
|
||||
: 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")),
|
||||
lock(),
|
||||
mbo(mbo) {}
|
||||
store(new persistence::SqliteStore("ex_sim_orders")) {}
|
||||
|
||||
IDGenerator m_generator;
|
||||
md::MDProducer producer;
|
||||
@@ -124,10 +116,9 @@ struct ExchangeSimApplication::PImpl {
|
||||
bool do_merge_with_md;
|
||||
std::unique_ptr<persistence::IStore> store;
|
||||
std::mutex lock;
|
||||
md::MBOWriter* mbo;
|
||||
};
|
||||
|
||||
ExchangeSimApplication::ExchangeSimApplication(md::MBOWriter* mbo) : me(new PImpl(mbo)) {
|
||||
ExchangeSimApplication::ExchangeSimApplication() : me(new PImpl()) {
|
||||
auto previous_book = me->store->retrieve_all();
|
||||
|
||||
auto all = me->store->retrieve_all()["books"];
|
||||
@@ -364,7 +355,7 @@ void ExchangeSimApplication::updateOrder(const Order &order, char status) {
|
||||
FIX::TargetSubID(order.sender_sub_id());
|
||||
|
||||
FIX42::ExecutionReport fixOrder;
|
||||
fixOrder.set(exchange_key(order.clordid()));
|
||||
fixOrder.set(FIX::OrderID("12345678901234567"));
|
||||
fixOrder.set(FIX::ExecID(me->m_generator.genExecutionID()));
|
||||
fixOrder.set(FIX::ExecTransType(FIX::ExecTransType_NEW));
|
||||
fixOrder.set(FIX::ExecType(status));
|
||||
@@ -414,7 +405,7 @@ void ExchangeSimApplication::rejectOrder(
|
||||
FIX::SenderCompID senderCompID(target.getValue());
|
||||
|
||||
FIX42::ExecutionReport fixOrder;
|
||||
fixOrder.set(exchange_key(clOrdID.getString()));
|
||||
fixOrder.set(FIX::OrderID("12345678901234567"));
|
||||
fixOrder.set(FIX::ExecID(me->m_generator.genExecutionID()));
|
||||
fixOrder.set(FIX::ExecTransType(FIX::ExecTransType_NEW));
|
||||
fixOrder.set(FIX::ExecType(FIX::ExecType_REJECTED));
|
||||
@@ -489,7 +480,7 @@ void ExchangeSimApplication::update_md(std::string const &sec_desc) {
|
||||
handle.update_direct(utils::TimeStamp::now(), bids_temp, asks_temp, me->md_sn++);
|
||||
|
||||
auto new_trades = matcher.get_new_trades();
|
||||
for (auto &t : new_trades) {
|
||||
for (auto &t : new_trades)
|
||||
handle.add_trade(
|
||||
utils::TimeStamp::now(),
|
||||
md::PriceSize_from_double<ex_sim::precision>(t.price.value() * price_factor,t.quantity.value()),
|
||||
@@ -497,29 +488,6 @@ void ExchangeSimApplication::update_md(std::string const &sec_desc) {
|
||||
t.bid_aggressor ? co2::AGGRESSOR_SIDE_BUY
|
||||
: ( t.ask_aggressor ? co2::AGGRESSOR_SIDE_SELL
|
||||
: co2::AGGRESSOR_SIDE_NONE) );
|
||||
}
|
||||
|
||||
// publish mbo
|
||||
auto mbo = me->mbo;
|
||||
if (mbo) {
|
||||
// get the list of trades
|
||||
auto ob = matcher.get_order_book(nullptr);
|
||||
auto snap = mbo->allocate_snapshot();
|
||||
for (const auto& order : ob.order()) {
|
||||
auto ek = exchange_key(order.clordid());
|
||||
md::SnapshotOrder sno {
|
||||
md::ExchangeOrderKey(std::atoll(ek.getString().c_str())),
|
||||
md::IntPrice_from_double<precision>(order.price() * price_factor),
|
||||
(int)order.open_quantity() };
|
||||
if (order.side() == api::SIDE_BUY) {
|
||||
snap->bids.push_back(sno);
|
||||
}
|
||||
else if (order.side() == api::SIDE_SELL) {
|
||||
snap->asks.push_back(sno);
|
||||
}
|
||||
}
|
||||
mbo->publish_snapshot(SecurityKey(it->second.key()), &snap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ GCC_DIAG_OFF("-Wignored-qualifiers")
|
||||
|
||||
namespace bts {
|
||||
namespace api {class Security;}
|
||||
namespace md {class MDConsumerHandle; class MBOWriter;}
|
||||
namespace md {class MDConsumerHandle;}
|
||||
namespace ex_sim {
|
||||
static const int precision = 9;
|
||||
class Order;
|
||||
@@ -55,7 +55,7 @@ class ExchangeSimApplication
|
||||
public FIX::MessageCracker
|
||||
{
|
||||
public:
|
||||
ExchangeSimApplication(md::MBOWriter*);
|
||||
ExchangeSimApplication();
|
||||
~ExchangeSimApplication();
|
||||
void merge_with_md_book();
|
||||
|
||||
|
||||
@@ -83,17 +83,13 @@ void OrderMatcher::add_or_merge(Order const &o, std::vector<Order> *out) {
|
||||
|
||||
auto range = find_level(*side,o.price());
|
||||
|
||||
// If the last order at this level is the same owner we can update it
|
||||
if (range.first != range.second) {
|
||||
auto last = range.second;
|
||||
last--;
|
||||
if (last->owner() == o.owner()) {
|
||||
auto no_const = const_cast<Order *>(&(*last));
|
||||
no_const->set_open_quantity(last->open_quantity() + o.quantity());
|
||||
for (auto it = range.first; it != range.second; it++)
|
||||
if (it->owner() == o.owner()) {
|
||||
auto no_const = const_cast<Order *>(&(*it));
|
||||
no_const->set_open_quantity(it->open_quantity() + o.quantity());
|
||||
match(out);
|
||||
return;
|
||||
}
|
||||
}
|
||||
add_new(o,out);
|
||||
}
|
||||
|
||||
@@ -236,14 +232,14 @@ Book OrderMatcher::get_book() const {
|
||||
return result;
|
||||
}
|
||||
|
||||
OrderBook OrderMatcher::get_order_book(const char* exclude_owner) const
|
||||
OrderBook OrderMatcher::get_order_book(std::string const&exclude_owner) const
|
||||
{
|
||||
OrderBook result;
|
||||
for (auto &b : me->bids)
|
||||
if (exclude_owner == nullptr || b.owner() != exclude_owner)
|
||||
if (b.owner() != exclude_owner)
|
||||
*result.add_order() = b;
|
||||
for (auto &a : me->asks)
|
||||
if (exclude_owner == nullptr || a.owner() != exclude_owner)
|
||||
if (a.owner() != exclude_owner)
|
||||
*result.add_order() = a;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ class OrderMatcher {
|
||||
Quantity by_quantity,
|
||||
std::string const& order_owner);
|
||||
Book get_book() const;
|
||||
OrderBook get_order_book(const char*) const;
|
||||
OrderBook get_order_book(std::string const&exclude_owner) const;
|
||||
|
||||
Order const *get_order(std::string const &clorid);
|
||||
|
||||
|
||||
@@ -152,7 +152,7 @@ void run_market_datapublishers(MBOWriter* mbo) {
|
||||
}));
|
||||
|
||||
if (config::get<MarketDataConfig>().use_sim()) {
|
||||
threading::make_thread("ExchangeSim", [mbo]() { sim::start_exchange_sim(mbo); })
|
||||
threading::make_thread("ExchangeSim", []() { sim::start_exchange_sim(); })
|
||||
.detach();
|
||||
}
|
||||
boot_sleep();
|
||||
|
||||
Reference in new issue
Block a user