Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9946c4716f | ||
|
|
ee0e719e76 | ||
|
|
5d5761288f | ||
|
|
6dbeaa14e2 | ||
|
|
6066e2162c | ||
|
|
4279e3d388 | ||
|
|
221814cc11 |
No files matched your search
@@ -97,7 +97,7 @@ namespace mbts.spark {
|
||||
|
||||
public event Action visible_columns_changed;
|
||||
|
||||
public IEnumerable<ColumnType> visible_columns =>
|
||||
public IEnumerable<ColumnType> visible_column_types =>
|
||||
columns.Where(c => c.settings.show)
|
||||
.Select(c => c.column_type);
|
||||
|
||||
@@ -253,6 +253,7 @@ 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();
|
||||
@@ -330,7 +331,7 @@ namespace mbts.spark {
|
||||
|
||||
#region Column Utility Methods
|
||||
Column _column_for_point(Point point) =>
|
||||
columns.FirstOrDefault(c => c.x_right > point.X, columns.Length > 0 ? columns[columns.Length - 1] : Column.Empty);
|
||||
_visible_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);
|
||||
@@ -913,4 +914,4 @@ namespace mbts.spark {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,6 +38,14 @@ 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)]
|
||||
@@ -250,7 +258,7 @@ namespace mbts.spark {
|
||||
ask_column = LadderColumnSettings.Default,
|
||||
price_column = LadderColumnSettings.Default,
|
||||
last_column = LadderColumnSettings.Default,
|
||||
piq_column = LadderColumnSettings.Default;
|
||||
piq_column = LadderColumnSettings.DefaultPiqColumnSettings;
|
||||
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_columns.Select(t => ColumnFactory.create(_ladder, t)));
|
||||
_ladder.visible_column_types.Select(t => ColumnFactory.create(_ladder, t)));
|
||||
this.vm = vm;
|
||||
DataContext = vm;
|
||||
DataContextChanged += datacontext_changed;
|
||||
|
||||
@@ -35,6 +35,7 @@ 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";
|
||||
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
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.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);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,47 +13,29 @@ 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 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 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 int Main(string[] args) {
|
||||
mbts.utils.BTSNativeMethods.provide_command_line(args, args.Length);
|
||||
|
||||
//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));
|
||||
// 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 >(args)
|
||||
.MapResult<ConfigcheckOptions,ScriptClientOptions,TailServiceOptions,ServiceTestOptions,SettingsManagerOptions,TestCommandOptions,OrderStressOptions,int>(
|
||||
Configcheck.Run,
|
||||
ScriptClientCommand.Run,
|
||||
TailService.Run,
|
||||
ServiceTest.Run,
|
||||
SettingsManagerCommand.Run,
|
||||
TestCommand.Run,
|
||||
OrderStress.Run,
|
||||
errors => 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -81,11 +81,6 @@ 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;
|
||||
@@ -94,6 +89,13 @@ 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 += 1;
|
||||
position += oo.size;
|
||||
}
|
||||
else {
|
||||
price = oo.price;
|
||||
position = 1;
|
||||
position = oo.size;
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "lib/api/public/ServiceContext.h"
|
||||
#include "lib/api/services/MBOService.server.pb.h"
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
namespace bts {
|
||||
namespace utils { class Dispatcher; }
|
||||
@@ -24,4 +25,5 @@ class MBOServiceServer : public MBOServiceBase {
|
||||
|
||||
};
|
||||
|
||||
|
||||
}} //namespace
|
||||
@@ -9,6 +9,10 @@
|
||||
|
||||
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;
|
||||
|
||||
@@ -202,6 +206,7 @@ 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 };
|
||||
@@ -288,7 +293,27 @@ 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);
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
Reference in new issue
Block a user