Compare commits

..
13 Commits
277 changed files with 4555 additions and 25639 deletions

No files matched your search

+3 -8
View File
@@ -5,9 +5,7 @@
"includePath": [
"/usr/include",
"/usr/local/include",
"${workspaceRoot}",
"${workspaceFolder}/src",
"${workspaceRoot}/externals/linux/include"
"${workspaceRoot}"
],
"defines": [],
"intelliSenseMode": "clang-x64",
@@ -15,16 +13,13 @@
"path": [
"/usr/include",
"/usr/local/include",
"${workspaceRoot}",
"${workspaceFolder}/src",
"${workspaceRoot}/externals/linux/include"
"${workspaceRoot}"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
},
"cStandard": "c11",
"cppStandard": "c++17",
"compileCommands": "${workspaceFolder}/build/ninja_debug/compile_commands.json"
"cppStandard": "c++17"
},
{
"name": "Windows",
+26 -129
View File
@@ -44,8 +44,7 @@
"debuggerPath": "/usr/bin/gdb"
},
"sourceFileMap": {
"/home/bts/spark/": "${workspaceRoot}",
"/home/bts/spark_host/": "${workspaceRoot}",
"/home/bts/spark/": "${workspaceRoot}"
}
},
{
@@ -99,52 +98,11 @@
"externalConsole": true,
"requireExactSource": false
},
{
"name": "sparkcmd Launch",
"type": "clr",
"request": "launch",
"program": "${workspaceRoot}/build/Debug/bin/net471/sparkcmd.exe",
"args": [
"historical",
"--server",
//"--rstart", "11/22/2019",
//"--rend", "11/25/2019",
//"--rsymbol", "ES",
//"--rsecuritytype", "Synthetic",
//"--post_process_file_type", "Trade",
//"--upload_to_aws",
],
"cwd": "${workspaceRoot}",
"stopAtEntry": false,
"externalConsole": true,
"requireExactSource": false
},
{
"name": "sparkcmd simulation",
"type": "clr",
"request": "launch",
"program": "${workspaceRoot}/build/Debug/bin/net471/sparkcmd.exe",
"args": [
"historical",
"--rstart", "11/26/2019",
"--rend", "11/26/2019",
"--rsymbol", "ZN",
"--rsecuritytype", "Synthetic",
"--algo_security", "ZNH0;ZNZ9-ZNH0;ZNZ9",
"--algo_type", "RoundTrip",
"--algo_params", "size=10;tick_size=0.015625,0.0078125,0.015625;hedge_factors=1,1,-1",
"--skip_preanalysis", "true",
],
"cwd": "${workspaceRoot}",
"stopAtEntry": false,
"externalConsole": true,
"requireExactSource": false
},
{
"name": "Excel Launch",
"type": "clr",
"request": "launch",
"program": "C:/Program Files/Microsoft Office/Office16/EXCEL.EXE",
"program": "C:/Program Files/Microsoft Office/Office14/EXCEL.EXE",
"args": [
"${workspaceRoot}/build/Debug/bin/net471/spark_excel-addin64-packed.xll"
],
@@ -160,13 +118,30 @@
"program": "${workspaceRoot}/build/Debug/bin/net471/sparkcmd.exe",
"args": [
"fix",
"-order_session",
"--export_atdl_path",
"./atdl/",
"--export_single_file",
],
"cwd": "${workspaceRoot}/build/Debug/bin/net471/",
"stopAtEntry": false,
"externalConsole": true,
"requireExactSource": false
},
},
{
"name": "Fix Launch2",
"type": "clr",
"request": "launch",
"program": "${workspaceRoot}/build/Debug/bin/net471/sparkcmd.exe",
"args": [
"fix",
"--validate_atdl_path",
"./atdl/"
],
"cwd": "${workspaceRoot}/build/Debug/bin/net471/",
"stopAtEntry": false,
"externalConsole": true,
"requireExactSource": false
},
{
"name": "Client Tests",
"type": "clr",
@@ -182,18 +157,11 @@
"requireExactSource": false
},
{
"name": ".NET Framework Attach",
"name": "Client Attach",
"type": "clr",
"request": "attach",
"processId": "${command:pickProcess}"
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach",
"processId": "${command:pickProcess}",
"requireExactSource": false
},
{
"name": "Spreader Tests",
"type": "cppdbg",
@@ -400,22 +368,17 @@
"quoteArgs": true
},
"sourceFileMap": {
"/home/bts/spark_host/": "${workspaceRoot}"
"/home/bts/spark/": "${workspaceRoot}"
},
"justMyCode": true
},
{
"name": "sparkcmd vsdbg (c#)",
"name": ".NET Core Remote Launch",
"type": "coreclr",
"request": "launch",
"program": "sparkcmd",
"args": [
"historical",
"--rstart", "11/20/2019",
"--rend", "11/20/2019",
"--rsymbol", "CL",
"--rsecuritytype", "Spread",
"--post_process_db", "mbo_history",
"test",
],
"env": {"LD_LIBRARY_PATH" : "."},
"stopAtEntry": false,
@@ -433,72 +396,6 @@
"/home/bts/spark/": "${workspaceRoot}"
},
"justMyCode": false
},
{
"name": "sparkcmd gdb (c++)",
"type": "cppdbg",
"request": "launch",
"program": "/home/bts/spark/build/ninja_debug/server/sparkcmd",
"args": [
"historical",
"--rstart", "10/21/2019",
"--rend", "10/21/2019",
"--rsymbol", "CL",
"--rsecuritytype", "Future",
"--algo_security", "CLX9",
"--algo_type", "TWAP",
"--algo_params", "'size=100;profit_ticks=1;tick_size=1,1,1;;hedge_factors=1,1,-1'",
"--skip_preanalysis", "true",
],
"stopAtEntry": false,
"cwd": "/home/bts/spark/build/ninja_debug/server/",
"environment": [],
"externalConsole": true,
"MIMode": "gdb",
"preLaunchTask": "",
"logging": {
"engineLogging": false
},
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "enable pretty-printer",
"ignoreFailures": true
},
{
"description": "Skip STL",
"text": "skip -gfi /usr/include/c++/7/bits/*.h",
"ignoreFailures": true
},
{
"description": "LD LIBRARY",
"text": "set env LD_LIBRARY_PATH=.",
"ignoreFailures": false
}
],
"pipeTransport": {
"pipeCwd": "${workspaceRoot}",
"pipeProgram": "c:\\program files\\git\\usr\\bin\\ssh.exe",
"pipeArgs": [
"bts@sparkvm"
],
"debuggerPath": "/usr/bin/gdb"
},
"sourceFileMap": {
"/home/bts/spark/": "${workspaceRoot}"
}
},
{
"name": "Jupyter notebook",
"type": "coreclr",
"request": "launch",
"program": "jupyter",
"args": ["notebook", "--notebook-dir=c:\\code\\bts\\spark\\src\\client\\spark_historical\\Notebooks"],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
"console": "internalConsole",
},
},
]
}
+10 -19
View File
@@ -14,21 +14,24 @@
"focus": false,
"panel": "shared"
},
"group": "build"
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "server_build",
"label": "server_build",
"type": "shell",
"command": ".\\tools\\buildsparkd.cmd",
"problemMatcher": {
"base": "$gcc",
"problemMatcher": {
"base": "$gcc",
"owner": "cpp",
"fileLocation": [
"relative",
"${workspaceFolder}"
"${workspaceFolder}"
],
"pattern": {
"regexp": "(.?)(home)(.?)(bts)(.?)(spark)(.?)(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)",
"regexp": "(.?)(home)(.?)(bts)(.?)(spark)(.?)(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)",
"file": 8,
"line": 9,
"column": 10,
@@ -46,18 +49,6 @@
"kind": "build",
"isDefault": true
}
},
{
"label": "linux build (Debug)",
"type": "shell",
"command": "cd build/ninja_debug; time ninja",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$gcc"
]
}
}
]
}
-1
View File
@@ -1 +0,0 @@
[0108/231015.447:ERROR:file_io.cc(89)] ReadExactly: expected 36, observed 0
+1 -1
View File
@@ -1,6 +1,6 @@
+++
title="Client API"
redirect_to = "client/getting-started/overview/"
template="client.html"
sort_by="weight"
+++
@@ -1,5 +1,6 @@
+++
title="Getting Started"
template="client.html"
sort_by="weight"
weight = 1
+++
@@ -1,25 +1,9 @@
+++
title = "Install Prerequisites"
weight = 10
template="client.html"
weight = 1
+++
# C#/.NET
We target [.NET Standard 2.0](https://docs.microsoft.com/en-us/dotnet/standard/net-standard) so you can use .NET Framework 4.6.1+ or .NET Core 2.0+. Simply add a reference to the [Spark Nuget package](https://nuget.org) to get started.
```
dotnet new console -lang c#
dotnet add package spark_sdk
dotnet build
```
# C++
The easiest way to get started with C++ is to use the Spark Server SDK to develop your application. Follow the instructions to [download and install the Spark Server SDK](/server/getting-started/install) and open the client_sdk sample project. If you want to run your C++ Client SDK application on Windows [contact us](mailto://api@bluetradesys.com) to get the required headers and binaries.
# JavaScript
We use JavaScript internally with the Spark Client API over a websocket connection but the documentation and packaging isn't ready yet. If this is something you're interested in get in touch with us at [api@bluetradesys.com](mailto:api@bluetradesys.com).
## Coming Soon
* Install .net core
@@ -1,31 +0,0 @@
+++
title = "Overview"
weight = 1
+++
The Spark Client SDK is a high level command and control API which can be used to build scripts or integrate Spark into your existing ecosystem. The API is divided into several independent **"services"** responsible for different aspects of the system. A Service can define both [remote procedure call (RPC)](/client/getting-started/services#rpc) and incremental [streaming](/client/getting-started/services#streams) data.
The [Spark Desktop](https://www.bluetradingsystems.com/bts-spark/) is built on top of this API so you can be assured that it is complete and well tested.
Spark uses [Google Protocol Buffers](https://developers.google.com/protocol-buffers/) as an interface definition language similar to [GRPC](https://grpc.io) but backed by our custom high-performance TCP protocol. We currently support C#/.NET and C++ <!--and Javascript--> but the architecture is designed for easy extension so contact us about your specific business needs.
## Orders
Use the [OrderService](/client/services/orderservice) to send and manage orders including native exchange orders, spreader orders, and custom Algo orders created using the [Spark Server SDK](https://api.bluetradesys.com/server/).
## Spreader
Use the [SyntheticSecurityService](/client/services/syntheticsecurityservice) to create and manage synthetic spreads. Once created these spreads show up in the security and market data feeds just like exchange listed spreads.
## Position
Use the [PositionService](/client/services/positionservice) to get your position and P&L reports or add fills manually to keep the Spark system up to date with an external system.
## Administration
Use the [AdminService](/client/services/adminservice) to manage users and control limits.
## Market Data
For .NET subscribe to market data though the high level MarketDataClient interface. From C++ or JavaScript use the MarketDataRelay service directly.
@@ -1,127 +0,0 @@
+++
title = "Services"
weight = 20
+++
The Spark Client SDK uses [Google Protocol Buffers](https://developers.google.com/protocol-buffers/) to define the interface for each service in a language independent manner. Services have both functions which return a single result and streams of data which return values continuously while subscribed. This page describes the mapping from the Protocol Buffer definition to the concrete definition in each supported language.
# ServiceContext
To connect your client to the Spark Server you need to get or create a `ServiceContext` instance. A `ServiceContext` represents a connection to the Spark Server and a background thread for handling messages on that connection. Generally there should be a single `ServiceContext` per process. All of the methods on the `ServiceContext` are safe thread safe.
Construct a ServiceContext by calling the default constructor. The ServiceContext will find the Spark Server by loading the server configuration over an HTTP connection. To determine the URL it will search the following locations and use the first one that is present.
* A command line argument `-configserver <url>`
* An environment variable `BTSCONFIG`
* `%APPDATA%/bts/conf/spark.conf` (Windows)
* /sparkdata/conf/spark.conf (Linux)
* $HOME/sparkdata/conf/spark.conf (Linux)
If your application is running on a system with the BTS Client installed this will probably work without any further configuration. If you plan to run your client application on a separate machine we recommend setting the `BTSCONFIG` environment variable.
<div class="info">
<i class="fa fa-lightbulb-o fa-fw" aria-hidden="true"></i>
If you are using the Spark Server SDK to run a local copy of the Spark server set <p><strong>BTSCONFIG = http://localhost:9000/config/</strong></p>
</div>
To get a proxy for a given service call ServiceContext.locate&lt;T>("qualifier") where T is the type of the service and "qualifier" is an optional qualifier used to disambiguate between 2 instances of the same service. The locate call cannot fail but it may return a disconnected proxy. When you make a call on the proxy you should check the call result to see if the method call succeeded.
# RPC
Here is the OrderService reduced to a single method definition. A RPC method always takes exactly 1 argument and returns 1 value. In this example the `create_order` call takes a `Create` instance and returns a `Response`.
```C
service OrderService {
rpc create_order(Create) returns (Response);
...
}
```
The `Create` and `Response` types are also defined as protocol buffer messages. Each field can either be a primitive type another message or a list or map.
```C
message Create {
OrderDefinition new_order = 1;
double price = 2;
uint32 quantity = 3;
}
message Response {
uint32 order_key = 1;
OrderError error_code = 2;
string msg = 3;
}
```
Each RPC call generates both synchronous (blocking) and asynchronous variants. In C# the asynchronous calls have the `_async` suffix and return a `Task`. In C++ the call is overloaded to either return a value synchronously or accept a callback function to be called on the ServiceContext thread when the call completes. <!-- In Javascript only async methods returning a Promise are generated because it never makes sense to make a blocking call in the browser. -->
To call the resulting service locate a proxy using the [ServiceContext](#servicecontext) and then call `cancel_order` or `cancel_order_async`. If you are calling the Spark API from a GUI application you should always prefer the `_async` version of the calls.
### C# example
```c#
var ctx = new ServiceContext();
var orders = ctx.locate<OrderService>();
var response =
await orders.create_order_async(
new Create { price = 2.25, quantity = 42 });
if (response.success) {
Console.WriteLine($"success: {response.value}");
}
else {
Console.WriteLine($"Error: {response.error_message}");
}
```
### C++ example
```cpp
auto ctx = ServiceContext{};
auto orders = ctx.locate<OrderService>();
Create c;
c.set_price(2.25);
c.set_quantity(42);
// Instead of providing an _async method C++ uses overloading.
// To make a syncronous call simply omit the callback
orders.create_order(c, [=](const Result<Response>& response) {
if(response.success()) {
std::cout << "success.";
}
else {
std::cout << "error: " << response.error_message();
}
});
```
# Streams
Streams allow you to subscribe to live updating data. Each stream represents a changing collection of protocol buffer objects. Similar to a database row each item has an `id` which uniquely identifies it within the collection. Updates from the Spark server can add, remove or replace entries in the collection. Since only the changed items are sent over the wire the stream can remain responsive even when it represents a large collection.
Streams are implemented using the language bindings for [ReativeX](http://reactivex.io/) which provide utility functions to drill down to the specific data your application needs. In C# we provide both mutable and immutable versions of the generated data types (C++ users can rely on `const`).
When defined in a proto file streams use the `stream` keyword on the result type.
```C
service OrderService {
...
rpc fills (FillsSub) returns (stream Fill);
}
```
### C# example
```c#
var sc = new ServiceContext();
var orders = sc.locate<OrderService>();
var fills_observable = orders.subscribei_fills();
var unsub = fills_observable.Subscribe(update => {
Console.WriteLine(
"Added {0} items, Removed {1} items, Updated {2} items. Total items {3}",
update.added.Count(),
update.removed.Count(),
update.changes.Count(),
update.all.Count());
});
Thread.Sleep(TimeSpan.FromMinutes(5));
unsub.Dispose();
```
### C++ Example
```cpp
```
-6
View File
@@ -1,6 +0,0 @@
+++
title="Samples"
sort_by="weight"
weight = 30
+++
@@ -1,3 +0,0 @@
+++
title = "AdminService"
+++
@@ -1,3 +0,0 @@
+++
title = "OrderService"
+++
@@ -1,3 +0,0 @@
+++
title = "PositionService"
+++
@@ -1,3 +0,0 @@
+++
title = "SyntheticService"
+++
@@ -1,6 +0,0 @@
+++
title="Services"
#sort_by="weight"
weight = 10
+++
@@ -1,3 +0,0 @@
+++
title = "Market Data"
+++
+1
View File
@@ -1,5 +1,6 @@
+++
title="Algo API"
template="documentation.html"
redirect_to = "server/getting-started/overview/"
sort_by="weight"
+++
@@ -1,5 +1,6 @@
+++
title="Getting Started"
template="documentation.html"
sort_by="weight"
weight = 1
+++
@@ -5,7 +5,7 @@ weight = 2
## Request Access 🔑
To start using the Server SDK you will need to request access though our sales department. Please email <a href="mailto:api@bluetradesys.com">api@bluetradesys.com</a> or call <a href="tel:919-913-0850">(919) 913-0850</a> and we will provide download credentials.
To start using the Server SDK you will need to request access though our sales department. Please email <a href="mailto:info@bluetradesys.com">info@bluetradesys.com</a> or call <a href="tel:919-913-0850">(919) 913-0850</a> and we will provide download credentials.
## Download
File renamed without changes.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 46 KiB

+1
View File
@@ -1,5 +1,6 @@
+++
title="Reference"
template="documentation.html"
sort_by="weight"
weight = 2
+++
-6
View File
@@ -6,9 +6,3 @@ weight = 40
## I need to make a call that might take a few seconds. What is the best way to do this?
Create a background thread in [do_before_launch](/server/ref/initialization#before-launch) or [do_launch](/server/ref/initialization#launch-launch-attached) to do the work. Use [on_timer](/server/ref/subscriptions#timer) to poll until the result is available.
## I don't see the header files in the .zip file. Where are they?
The SDK headers are baked into the docker image along with the build tools. Once you've loaded the image with `docker load < spark_sdk.img` you can run this command to copy them out to your local file system `docker run --rm -it -v $PWD:/out spark_sdk /bin/tar -cvf /out/headers.tar /sdk/include` This will copy the headers to the current directory in headers.tar. We still recommend doing the actual build inside the docker environment but having a copy of the headers can be useful for setting up your development environment.
+1
View File
@@ -1,5 +1,6 @@
+++
title="Samples"
template="documentation.html"
sort_by="weight"
weight = 3
+++
+31
View File
@@ -0,0 +1,31 @@
{% extends "index.html" %}
{% block extra_nav_class %}{% endblock extra_nav_class %}
{% block extra_content_class %}content--reversed{% endblock extra_content_class %}
{% block content %}
{% set section = get_section(path="client/_index.md") %}
<div class="documentation">
<aside class="documentation__sidebar">
<ul>
{% for p in section.subsections %}
{% set subsection = get_section(path=p) %}
<li>
<span class="documentation__sidebar__title">{{ subsection.title }}</span>
<ul>
{% for page in subsection.pages %}
<li class="{% if current_path == page.path %}active{% endif %}">
<a href="{{page.permalink}}">{{page.title}}</a>
</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
</aside>
<div class="documentation__content">
{% block doc_content %}
{% endblock doc_content %}
</div>
</div>
{% endblock content %}
+36
View File
@@ -0,0 +1,36 @@
{% extends "index.html" %}
{% block extra_nav_class %}{% endblock extra_nav_class %}
{% block extra_content_class %}content--reversed{% endblock extra_content_class %}
{% block content %}
{%if page.extra.section %}
{% set section = get_section(path="{{page.extra.section}}/_index.md") %}
{% else %}
{% set section = get_section(path="server/_index.md") %}
{% endif %}
<div class="documentation">
<aside class="documentation__sidebar">
<ul>
{% for p in section.subsections %}
{% set subsection = get_section(path=p) %}
<li>
<span class="documentation__sidebar__title">{{ subsection.title }}</span>
<ul>
{% for page in subsection.pages %}
<li class="{% if current_path == page.path %}active{% endif %}">
<a href="{{page.permalink}}">{{page.title}}</a>
</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
</aside>
<div class="documentation__content">
{% block doc_content %}
{% endblock doc_content %}
{% block next_link %} {% endblock next_link %}
</div>
</div>
{% endblock content %}
+15 -15
View File
@@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="en-us">
<html lang="en-gb">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
@@ -14,7 +14,6 @@
<link rel="stylesheet" href="{{ get_url(path="site.css") }}"/>
<link rel="icon" href="{{ get_url(path="favicon.ico") }}">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
<script> dataLayer = [{ 'visitorType': 'geek' }]; </script>
</head>
<body>
@@ -37,13 +36,13 @@
</nav>
</header>
<div class="content content--reversed">
<div class="content {% block extra_content_class %}{% endblock extra_content_class %}">
{% block content %}
<div class="hero">
<h1>Spark SDK</h1>
<p class="hero__tagline">
Spark consists of a client UI
(<a href="https://www.bluetradingsystems.com/bts-spark#ladder-algo-screen">Spark Client</a>),
(<a class="white" href="https://www.bluetradingsystems.com/bts-spark#ladder-algo-screen">Spark Client</a>),
a high-performance professional futures front end, connected via our proprietary protocol over TCP to our Spark Server, which in turn connects to execution venues via their native protocols.
Use the Spark SDK to extend Spark Server with your custom Algos, then use the Client SDK to launch and control them.
</p>
@@ -65,7 +64,7 @@
<a href="{{ get_url(path="@/server/_index.md") }}" class="button">Get started</a>
</div>
<div class="selling-point">
<div class="selling-point disabled">
<h2>
Client SDK
<i class="fa fa-gamepad" aria-hidden="true"></i>
@@ -73,9 +72,19 @@
<p>
The Spark client SDK allows you to integrate spark with your existing ecosystem. The Spark Client is built entirely on this simple, powerful API.
</p>
<a href="" class="button">Get started</a>
<a href="" class="button" disabled>Get started</a>
</div>
<!-- <div class="selling-point disabled">
<h2>
Microsoft Excel
<i class="fa fa-table" aria-hidden="true"></i>
</h2>
<p>
More of your business is built on excel than probably should be. Continue this worrying trend with the Spark Excel API.
</p>
<a href="" class="button" disabled>Get started</a>
</div> -->
</div>
</div>
@@ -85,15 +94,6 @@
© Blue Trading Systems
</footer>
<script>
if (location.hostname == "api.bluetradesys.com") {
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-56FHG8R');
}
</script>
<script type="text/javascript" src="{{ get_url(path="elasticlunr.min.js") }}"></script>
<script type="text/javascript" src="{{ get_url(path="search_index.en.js") }}"></script>
<script type="text/javascript" src="{{ get_url(path="search.js") }}"></script>
+8 -36
View File
@@ -1,39 +1,13 @@
{% extends "index.html" %}
{# this has access to the "page" variable but documentation.html does not #}
{% extends "documentation.html" %}
{% block title %}{{ page.title }} | {{ super() }} {% endblock title %}
{% block doc_content %}
<h1>{{page.title}}</h1>
{{page.content | safe}}
{% endblock doc_content %}
{% block next_link %}
{% endblock next_link %}
{% block content %}
{% set section = get_section(path=page.ancestors[1]) %}
{#
{#<div>{{ section.title }} </div>#}
<div class="documentation">
<aside class="documentation__sidebar">
<ul>
{% for p in section.subsections %}
{% set subsection = get_section(path=p) %}
<li>
<span class="documentation__sidebar__title">{{ subsection.title }}</span>
<ul>
{% for page in subsection.pages %}
<li class="{% if current_path == page.path %}active{% endif %}">
<a href="{{page.permalink}}">{{page.title}}</a>
</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
</aside>
<div class="documentation__content">
<h1>{{page.title}}</h1>
{{page.content | safe}}
{# next/pre links #}
<p>
<p>
{% if page.lighter %}
<a href="{{ page.lighter.permalink }}">
<i class="fa fa-chevron-left fa-fw" aria-hidden="true"></i>
@@ -47,7 +21,5 @@
<i class="fa fa-chevron-right fa-fw" aria-hidden="true"></i>
</a>
{% endif %}
</p>
</div>
</div>
{% endblock content %}
</p>
{% endblock next_link %}
-9
View File
@@ -4,15 +4,6 @@ weight = 3
sort_by = "weight"
insert_anchor_links = "right"
+++
## 2.15.3
### Bug Fixes
- Fixed a bug where some CME currency spreads exhibited incorrect tick values
## 2.15.2
### User Visible Changes
- Excel RTD plugin can now receive ICE market data
## 2.15.1
### Bug Fixes
- Fixed a FIX log parsing issue that resulted in exchange gateway logon problems
## 2.15.0
### User Visible Changes
- Added ability to hide Ladder status messages via Ladder Settings -> Left Panel tab -> Show/Hide groupbox -> Status Message
-29
View File
@@ -25,12 +25,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "spark_excel", "src\client\s
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "spark_fix", "src\client\spark_fix\spark_fix.csproj", "{D8031C13-7BEA-430A-BB60-40927D15CFC3}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "spark_historical", "src\client\spark_historical\spark_historical.csproj", "{5F64A360-43F4-4AD8-8B04-3C3F4424BCBC}"
EndProject
Global
GlobalSection(Performance) = preSolution
HasPerformanceSessions = true
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
@@ -246,30 +241,6 @@ Global
{D8031C13-7BEA-430A-BB60-40927D15CFC3}.RelWithDebInfo|x64.Build.0 = Release|x64
{D8031C13-7BEA-430A-BB60-40927D15CFC3}.RelWithDebInfo|x86.ActiveCfg = Release|x64
{D8031C13-7BEA-430A-BB60-40927D15CFC3}.RelWithDebInfo|x86.Build.0 = Release|x64
{5F64A360-43F4-4AD8-8B04-3C3F4424BCBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5F64A360-43F4-4AD8-8B04-3C3F4424BCBC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5F64A360-43F4-4AD8-8B04-3C3F4424BCBC}.Debug|x64.ActiveCfg = Debug|Any CPU
{5F64A360-43F4-4AD8-8B04-3C3F4424BCBC}.Debug|x64.Build.0 = Debug|Any CPU
{5F64A360-43F4-4AD8-8B04-3C3F4424BCBC}.Debug|x86.ActiveCfg = Debug|Any CPU
{5F64A360-43F4-4AD8-8B04-3C3F4424BCBC}.Debug|x86.Build.0 = Debug|Any CPU
{5F64A360-43F4-4AD8-8B04-3C3F4424BCBC}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU
{5F64A360-43F4-4AD8-8B04-3C3F4424BCBC}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU
{5F64A360-43F4-4AD8-8B04-3C3F4424BCBC}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
{5F64A360-43F4-4AD8-8B04-3C3F4424BCBC}.MinSizeRel|x64.Build.0 = Debug|Any CPU
{5F64A360-43F4-4AD8-8B04-3C3F4424BCBC}.MinSizeRel|x86.ActiveCfg = Debug|Any CPU
{5F64A360-43F4-4AD8-8B04-3C3F4424BCBC}.MinSizeRel|x86.Build.0 = Debug|Any CPU
{5F64A360-43F4-4AD8-8B04-3C3F4424BCBC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5F64A360-43F4-4AD8-8B04-3C3F4424BCBC}.Release|Any CPU.Build.0 = Release|Any CPU
{5F64A360-43F4-4AD8-8B04-3C3F4424BCBC}.Release|x64.ActiveCfg = Release|Any CPU
{5F64A360-43F4-4AD8-8B04-3C3F4424BCBC}.Release|x64.Build.0 = Release|Any CPU
{5F64A360-43F4-4AD8-8B04-3C3F4424BCBC}.Release|x86.ActiveCfg = Release|Any CPU
{5F64A360-43F4-4AD8-8B04-3C3F4424BCBC}.Release|x86.Build.0 = Release|Any CPU
{5F64A360-43F4-4AD8-8B04-3C3F4424BCBC}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU
{5F64A360-43F4-4AD8-8B04-3C3F4424BCBC}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
{5F64A360-43F4-4AD8-8B04-3C3F4424BCBC}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
{5F64A360-43F4-4AD8-8B04-3C3F4424BCBC}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
{5F64A360-43F4-4AD8-8B04-3C3F4424BCBC}.RelWithDebInfo|x86.ActiveCfg = Release|Any CPU
{5F64A360-43F4-4AD8-8B04-3C3F4424BCBC}.RelWithDebInfo|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
+1 -1
View File
@@ -97,7 +97,7 @@
<Copy SourceFiles="%(Proto2.FullPath)" DestinationFolder="$(WorkingDirectory)" SkipUnchangedFiles="True" UseHardLinksIfPossible="True" />
<Error Text="protogen.exe does not exist. If you forgot to clone with externals try: git submodule update --init --recursive" Condition="!Exists($(protogen))" />
<Message Importance="High" Text="Doing Proto2 %(proto2.filename)" />
<Exec Command="PYTHONPATH=$(Externals)/python $(Protogen) %(Proto2.filename)%(proto2.extension) --csharp_out=. -I. -I$(SourceRoot) -I$(Externals)/include"
<Exec Command="$(Protogen) %(Proto2.filename)%(proto2.extension) --csharp_out=. -I. -I$(SourceRoot) -I$(Externals)/include"
WorkingDirectory="$(WorkingDirectory)" />
<ItemGroup>
<Compile Include="$(WorkingDirectory)/%(Proto2.filename).cs" />
@@ -1,7 +1,6 @@
using bts.api;
using bts.co2;
using bts.collections;
using bts.utils.csv;
using mbts.persist;
using mbts.spark.filters;
using mbts.ui;
@@ -53,7 +52,7 @@ namespace mbts.spark {
columns.Add(new RenderTextColumn<Row, TimeAndSalesView.Columns>(col_key, r => r[col_key], filter, filter_template, r => _get_aggressor_brush(r))
{ id = col_id(col_key), Header = header, Width = width, sort_member_path = sort_member_path, horizontal_alignment = h_alignment }
);
// be sure to load GridSettings AFTER the columns collection has been populated, the grid settings manager looks columns by id to apply the appropriate settings,
// if the collection is not populated, the column settings will not be applied
grid_settings_manager = new SimpleGridSettingsManager<Row>(columns, new Dictionary<string, GridColumnSettingsFeatureFlags> { }, row_vms);
@@ -174,19 +173,6 @@ namespace mbts.spark {
}
}
public static System.Collections.Specialized.OrderedDictionary csv_ordered_properties =>
CsvHelper.create_ordering_maintainer(
typeof(TimeAndSalesVM.Row),
new string[] {
nameof(security),
nameof(time),
nameof(price),
nameof(size),
nameof(aggressor_side),
nameof(security_key),
});
public void raise_invalidated() => invalidated?.Invoke();
}
}
@@ -3,7 +3,6 @@ using bts.api;
using bts.shell;
using bts.shell.fills;
using bts.spark;
using bts.utils.csv;
using mbts.co2;
using mbts.persist;
using mbts.ui;
@@ -64,7 +63,6 @@ namespace mbts.spark {
var current_smd_source = connectable_builder.create(vm => vm.current_security_md_observable(_bus)).OnDispatcher();
var selected_secs_source = connectable_builder.create(vm => vm.selected_securities_observable()).OnDispatcher();
_commands = new SparkCommand[] {
new SparkCommandCommand("Export to csv", Icons.Export, FileDialogCommand.export_csv(() => _vm.value.row_vms.ToCsv(TimeAndSalesVM.Row.csv_ordered_properties), "TaS")),
SparkCommands.ShowLadder(SparkCommands.KeyGestures.ShowLadder).complete(current_smd_source, md => md.HasValue, ConvertUtils.ValueOrDefault),
SparkCommands.ShowOrderTicketFromSecurity(SparkCommands.KeyGestures.ShowOrderTicket).complete(current_smd_source, md => md.HasValue, ConvertUtils.ValueOrDefault),
SparkCommands.ShowFills(SparkCommands.KeyGestures.ShowFills).complete(selected_secs_source, always_true, get_fills_startup_data),
@@ -5,7 +5,6 @@ using bts.collections;
using bts.shell.fills;
using bts.spark;
using bts.utils;
using bts.utils.csv;
using mbts.collections;
using mbts.persist;
using mbts.spark.filters;
@@ -24,7 +23,6 @@ using System.Linq;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using static bts.api.orderman.Fill.Types;
using static bts.shell.FillsWindowFactory;
@@ -312,7 +310,6 @@ namespace mbts.spark {
public FillStatus fill_status => _fill.FillStatus;
public string fill_key => _fill.FillKey;
public string order_key => _order.Key.ToString();
public string symbol => fill_tuple.security?.Symbol;
public bool is_selected {
get => _is_selected;
set => Set(ref _is_selected, value);
@@ -333,28 +330,6 @@ namespace mbts.spark {
public override bool Equals(object obj) => Equals(obj as Row);
public override int GetHashCode() => _fill.FillKey.GetHashCode() ^ _order.Key.GetHashCode();
public static System.Collections.Specialized.OrderedDictionary csv_ordered_properties =>
CsvHelper.create_ordering_maintainer(typeof(Row),
new string[] {
nameof(security),
nameof(symbol),
nameof(order_type),
nameof(root_algo_display_name),
nameof(side),
nameof(fill_time),
nameof(user),
nameof(account),
nameof(exchange),
nameof(time_in_force),
nameof(size),
nameof(price),
nameof(fill_kind),
nameof(fill_status),
nameof(fill_key),
nameof(order_key),
nameof(security_key)
});
public event Action invalidated;
void IRowVM.raise_invalidated() => invalidated?.Invoke();
}
@@ -3,7 +3,6 @@ using bts.api;
using bts.shell;
using bts.shell.fills;
using bts.spark;
using bts.utils.csv;
using mbts.persist;
using mbts.ui;
using mbts.ui.settings;
@@ -55,7 +54,6 @@ namespace mbts.spark {
_view = new FillsView { DataContext = _vm };
_commands = new List<SparkCommand> {
new SparkCommandCommand("Export to csv", Icons.Export, FileDialogCommand.export_csv(() => _vm.rows.ToCsv(FillsVM.Row.csv_ordered_properties), "Fills")),
// wrap the grid settings view factory in a dialogCommand here since the vm is destroyed/recreated when the security criteria changes
SparkCommands.window_settings_command(new DialogCommand(() => {
var vm = new ShellSettingsDialogVM<GridSettings, SimpleGridSettingsVM>(
@@ -4,7 +4,6 @@ using bts.api.orderman;
using bts.collections;
using bts.spark;
using bts.utils;
using bts.utils.csv;
using mbts.ui;
using mbts.ui.controls;
using System;
@@ -12,7 +11,6 @@ using System.Collections.Generic;
using System.ComponentModel;
using System.Reactive.Linq;
using System.Runtime.CompilerServices;
using System.Linq;
using System.Windows.Input;
using System.Windows.Media;
using Columns = mbts.spark.OrderBookGridView.ColumnKeys;
@@ -62,35 +60,6 @@ namespace mbts.spark {
public event Action<(OrderSecurityRootPair oldval, OrderSecurityRootPair newval)> updated;
public event PropertyChangedEventHandler PropertyChanged;
public static System.Collections.Specialized.OrderedDictionary csv_ordered_properties =>
CsvHelper.create_ordering_maintainer(
typeof(OrderBookRowVM),
new string[] {
nameof(security_text),
nameof(symbol),
nameof(time_created),
nameof(last_change),
nameof(user),
nameof(account),
nameof(exchange),
nameof(time_in_force),
nameof(order_type),
nameof(root_algo_display_name),
nameof(order_sub_type),
nameof(side),
nameof(quantity),
nameof(filled_quantity),
nameof(price),
nameof(avg_price),
nameof(last_price),
nameof(piq),
nameof(status),
// last message (could contains commas, so skipping)
nameof(security_key),
nameof(order_key),
nameof(parent_order_key),
});
// Core
public OrderSecurityRootPair order_tuple { get; private set; }
public OrderRecordImmutable order => order_tuple.order.order;
@@ -4,7 +4,6 @@ using bts.shell;
using bts.shell.fills;
using bts.shell.orderbook;
using bts.spark;
using bts.utils.csv;
using bts.view;
using mbts.persist;
using mbts.ui;
@@ -185,7 +184,6 @@ namespace mbts.spark {
show_grid_settings_command.group = CommandGroups.Auxiliary;
_commands = new SparkCommand[] {
new SparkCommandCommand("Export to csv", Icons.Export, FileDialogCommand.export_csv(() => _vm.rows.ToCsv(OrderBookRowVM.csv_ordered_properties), "OrderBook")),
toggle_show_right_panel_command,
attach_selected_orders_command,
detach_selected_orders_command,
+44 -15
View File
@@ -653,25 +653,54 @@ namespace mbts.spark.utilities {
return def;
}
}
static CustomOrderDefinition.CustomOneofCase[] algo_config(
Func<bts.config.AlgoPermissions, List<string>> selector)
{
var conf = mbts.config.Configuration.get<bts.config.AlgoPermissions>();
return selector(conf).Select(x =>
{
return (CustomOrderDefinition.CustomOneofCase)System.Enum.Parse(typeof(CustomOrderDefinition.CustomOneofCase), x, true);
}).ToArray();
}
public static readonly CustomOrderDefinition.CustomOneofCase[]
// exchange_order_types are the types which can be submitted on an exchange security
exchange_order_types = algo_config(x => x.exchange_order_types),
spreader_order_types = algo_config(x => x.spreader_order_types),
attachable_order_types = algo_config(x => x.attachable_order_types),
outright_order_types = algo_config(x => x.outright_order_types);
exchange_order_types = new[] {
CustomOrderDefinition.CustomOneofCase.Market,
CustomOrderDefinition.CustomOneofCase.Limit,
CustomOrderDefinition.CustomOneofCase.Stop,
CustomOrderDefinition.CustomOneofCase.StopLimit,
CustomOrderDefinition.CustomOneofCase.GlbxIceberg,
CustomOrderDefinition.CustomOneofCase.Iceberg,
CustomOrderDefinition.CustomOneofCase.Lean,
CustomOrderDefinition.CustomOneofCase.Join,
CustomOrderDefinition.CustomOneofCase.Cover,
CustomOrderDefinition.CustomOneofCase.Top,
CustomOrderDefinition.CustomOneofCase.Offset,
CustomOrderDefinition.CustomOneofCase.Splitter,
CustomOrderDefinition.CustomOneofCase.Scratch,
CustomOrderDefinition.CustomOneofCase.Prorata,
},
spreader_order_types = new[] {
CustomOrderDefinition.CustomOneofCase.Spreader,
CustomOrderDefinition.CustomOneofCase.Iceberg,
CustomOrderDefinition.CustomOneofCase.Lean,
CustomOrderDefinition.CustomOneofCase.Join,
CustomOrderDefinition.CustomOneofCase.Cover,
CustomOrderDefinition.CustomOneofCase.Top,
CustomOrderDefinition.CustomOneofCase.Splitter,
CustomOrderDefinition.CustomOneofCase.Scratch,
CustomOrderDefinition.CustomOneofCase.Prorata,
},
attachable_order_types = new[] {
CustomOrderDefinition.CustomOneofCase.Iceberg,
CustomOrderDefinition.CustomOneofCase.Lean,
CustomOrderDefinition.CustomOneofCase.Join,
CustomOrderDefinition.CustomOneofCase.Cover,
CustomOrderDefinition.CustomOneofCase.Top,
CustomOrderDefinition.CustomOneofCase.Offset,
CustomOrderDefinition.CustomOneofCase.Scratch,
CustomOrderDefinition.CustomOneofCase.Prorata,
},
outright_order_types = new[] {
CustomOrderDefinition.CustomOneofCase.Market,
CustomOrderDefinition.CustomOneofCase.Limit,
CustomOrderDefinition.CustomOneofCase.Stop,
CustomOrderDefinition.CustomOneofCase.StopLimit,
CustomOrderDefinition.CustomOneofCase.GlbxIceberg,
};
public static readonly CustomOrderDefinition.CustomOneofCase[] all_order_types = exchange_order_types.Union(spreader_order_types).ToArray();
public static void copy_values(CustomOrderDefinitionImmutable source, ref CustomOrderDefinition target) =>
@@ -28,17 +28,15 @@ namespace mbts.spark
where TMutable : class, IMessage, new()
{
TMutable _message;
readonly protected Func<IMessage, IMessage> _message_override;
protected GenericOrderParamVM(FieldDescriptor descriptor, Func<IMessage, IMessage> message_override = null)
protected GenericOrderParamVM(FieldDescriptor descriptor)
{
_message = new TMutable();
_message_override = message_override;
this.descriptor = descriptor;
}
public FieldDescriptor descriptor { get; set; }
public virtual Google.Protobuf.IMessage message
public Google.Protobuf.IMessage message
{
get => _message;
set
@@ -55,12 +53,11 @@ namespace mbts.spark
where TMutable : class, IMessage, new()
{
readonly Func<TModel, TView> _convert;
readonly Func<TView, TModel> _convert_back;
readonly Func<TView, TModel> _convert_back;
TView _value;
public GenericOrderParamVM(FieldDescriptor field_descriptor, Func<TModel, TView> convert,
Func<TView, TModel> convert_back, Func<IMessage, IMessage> message_override = null) :
base(field_descriptor, message_override)
public GenericOrderParamVM(FieldDescriptor field_descriptor, Func<TModel, TView> convert, Func<TView, TModel> convert_back) :
base(field_descriptor)
{
_convert = convert;
_convert_back = convert_back;
@@ -71,8 +68,7 @@ namespace mbts.spark
get => _value;
set
{
this.descriptor.Accessor.SetValue( _message_override == null ? this.message : _message_override(this.message),
_convert_back(_value = value));
this.descriptor.Accessor.SetValue(this.message, _convert_back(_value = value));
RaisePropertyChanged();
}
}
@@ -88,7 +84,7 @@ namespace mbts.spark
protected override void on_param_changed()
{
_value = _convert(ConvertUtils.try_convert<TModel>(this.descriptor.Accessor.GetValue(_message_override == null ? this.message : _message_override(this.message))));
_value = _convert(ConvertUtils.try_convert<TModel>(this.descriptor.Accessor.GetValue(this.message)));
RaisePropertyChanged(nameof(value));
}
}
@@ -96,8 +92,8 @@ namespace mbts.spark
class GenericOrderEnumeratedVM<TMutable> : GenericOrderParamVM<TMutable>, IGenericOrderParamVM<string>
where TMutable : class, IMessage, new()
{
public GenericOrderEnumeratedVM(FieldDescriptor descriptor, Func<IMessage, IMessage> message_override = null)
: base(descriptor, message_override)
public GenericOrderEnumeratedVM(FieldDescriptor descriptor)
: base(descriptor)
{
elements = new ObservableCollection<string>(_get_elements(descriptor));
}
@@ -106,13 +102,11 @@ namespace mbts.spark
public string selected_element
{
get => GenericOrderHelper.get_enumerated_value(_message_override == null ? this.message : _message_override(this.message),
descriptor);
get => GenericOrderHelper.get_enumerated_value(message, descriptor);
set
{
var orig = selected_element;
GenericOrderHelper.set_enumerated_value(_message_override == null ? this.message : _message_override(this.message),
descriptor, value);
GenericOrderHelper.set_enumerated_value(message, descriptor, value);
if (selected_element != orig)
RaisePropertyChanged();
}
@@ -154,23 +148,22 @@ namespace mbts.spark
class GenericOrderQuantityVM<TMutable> : GenericOrderParamVM<TMutable>, IGenericOrderParamVM<QuantityMeasureImmutable?>
where TMutable : class, IMessage, new()
{
public GenericOrderQuantityVM(FieldDescriptor descriptor, Func<IMessage, IMessage> message_override = null)
: base(descriptor, message_override) { }
public GenericOrderQuantityVM(FieldDescriptor descriptor)
: base(descriptor) { }
QuantityMeasureImmutable? IGenericOrderParamVM<QuantityMeasureImmutable?>.value { get => quantity; set => quantity= value; }
public QuantityMeasureImmutable? quantity
{
get => GenericOrderHelper.get_quantity_value(_message_override == null ? this.message : _message_override(this.message),
descriptor);
get => GenericOrderHelper.get_quantity_value(message, descriptor);
set
{
var orig = quantity;
GenericOrderHelper.set_quantity_value(_message_override == null ? this.message : _message_override(this.message),
descriptor, value);
GenericOrderHelper.set_quantity_value(message, descriptor, value);
if (quantity != orig)
RaisePropertyChanged();
}
}
public IObservable<QuantityMeasureImmutable?> subscribe_value()
{
return Observable.Create<QuantityMeasureImmutable?>(o =>
@@ -181,9 +174,10 @@ namespace mbts.spark
o.OnNext(quantity);
});
}
protected override void on_param_changed()
{
RaisePropertyChanged(nameof(quantity));
}
}
}
}
@@ -96,41 +96,9 @@ namespace mbts.spark {
{
Google.Protobuf.Reflection.MessageDescriptor desc = new TMutable().Descriptor;
_parameters.SyncWithDictionary(
desc.Fields.InDeclarationOrder().Where(_is_value_param_desc).ToDictionary(p => p.Name), x => _mk_param_vm(x));
add_message_params(desc);
desc.Fields.InDeclarationOrder().Where(_is_value_param_desc).ToDictionary(p => p.Name), _mk_param_vm);
}
}
void add_message_params(Google.Protobuf.Reflection.MessageDescriptor desc)
{
var msgs = desc.Fields.InDeclarationOrder().Where(x => !_is_value_param_desc(x) &&
x.MessageType.ClrType != typeof(CustomOrderDefinition) );
foreach(var message_field in msgs)
{
foreach (var fd in message_field.MessageType.Fields.InDeclarationOrder())
{
if(_is_value_param_desc(fd)) //one level deep
{
var mk = _mk_param_vm(fd,
outside_object =>
{
var msgfield = message_field.Accessor.GetValue(outside_object);
if(msgfield == null)
{
message_field.Accessor.SetValue(outside_object, Activator.CreateInstance(message_field.MessageType.ClrType));
msgfield = message_field.Accessor.GetValue(outside_object);
}
return (IMessage)msgfield;
});
if(mk == null)
continue;
if(!_parameters.Add(mk))
_parameters.Add(message_field.Name + "_" + mk.descriptor.Name, mk);
}
}
}
}
static bool _is_value_param_desc(FieldDescriptor desc)
{
return (desc.FieldType != Google.Protobuf.Reflection.FieldType.Message ||
@@ -149,53 +117,50 @@ namespace mbts.spark {
return v;
}
GenericOrderParamVM<TMutable> _mk_param_vm(FieldDescriptor descriptor, Func<IMessage, IMessage> message_override = null)
GenericOrderParamVM<TMutable> _mk_param_vm(FieldDescriptor descriptor)
{
ExceptionAssert.Argument.NotNull(descriptor, nameof(descriptor));
if (descriptor.FieldType == FieldType.Message &&
descriptor.MessageType.FullName == typeof(bts.spark.QuantityMeasure).FullName)
{
var qm = new GenericOrderQuantityVM<TMutable>(descriptor, message_override);
return attached(qm, GenericOrderHelper.get_quantity_value, GenericOrderHelper.set_quantity_value, message_override);
var qm = new GenericOrderQuantityVM<TMutable>(descriptor);
return attached(qm, GenericOrderHelper.get_quantity_value, GenericOrderHelper.set_quantity_value);
}
else if(descriptor.FieldType == FieldType.Enum)
{
var pvm = new GenericOrderEnumeratedVM<TMutable>(descriptor, message_override);
attached(pvm, GenericOrderHelper.get_enumerated_value, GenericOrderHelper.set_enumerated_value, message_override);
var pvm = new GenericOrderEnumeratedVM<TMutable>(descriptor);
attached(pvm, GenericOrderHelper.get_enumerated_value, GenericOrderHelper.set_enumerated_value);
return pvm;
}
else if (descriptor.FieldType == FieldType.Bool)
return mk<bool?, bool>(descriptor, v => v, v => v.GetValueOrDefault(), message_override);
return mk<bool?, bool>(descriptor, v => v, v => v.GetValueOrDefault());
else if (descriptor.FieldType == FieldType.Double || descriptor.FieldType == FieldType.Float)
return mk<double, double>(descriptor, v => v, v => v, message_override, double.NaN);
return mk<double, double>(descriptor, v => v, v => v, double.NaN);
else if (descriptor.FieldType == FieldType.Int32)
return mk<int?, int>(descriptor, v => v, v => v.GetValueOrDefault(), message_override);
return mk<int?, int>(descriptor, v => v, v => v.GetValueOrDefault());
else if (descriptor.FieldType == FieldType.UInt32)
return mk<uint?, uint>(descriptor, v => v, v => v.GetValueOrDefault(), message_override);
return mk<uint?, uint>(descriptor, v => v, v => v.GetValueOrDefault());
else if (descriptor.FieldType == FieldType.String)
return mk<string, string>(descriptor, v => v, v => v, message_override);
return mk<string, string>(descriptor, v => v, v => v);
else
return null;
}
GenericOrderParamVM<TMutable, TView, TModel> mk<TView, TModel>(FieldDescriptor fdesc, Func<TModel, TView> convert, Func<TView, TModel> convert_back,
Func<IMessage, IMessage> message_override = null, TView default_value = default)
GenericOrderParamVM<TMutable, TView, TModel> mk<TView, TModel>(FieldDescriptor fdesc, Func<TModel, TView> convert, Func<TView, TModel> convert_back, TView default_value = default)
{
var pvm = new GenericOrderParamVM<TMutable, TView, TModel>(fdesc, convert, convert_back, message_override);
return attached<TView, GenericOrderParamVM<TMutable, TView, TModel>>(pvm, get_from_param, assign_to_param,
message_override, default_value);
var pvm = new GenericOrderParamVM<TMutable, TView, TModel>(fdesc, convert, convert_back);
return attached<TView, GenericOrderParamVM<TMutable, TView, TModel>>(pvm, get_from_param, assign_to_param, default_value);
TView get_from_param(IMessage param, FieldDescriptor fd) => convert(ConvertUtils.try_convert<TModel>(fdesc.Accessor.GetValue(param)));
void assign_to_param(IMessage param, FieldDescriptor fd, TView value) => fdesc.Accessor.SetValue(param, convert_back(value));
}
TParam attached<T, TParam>(TParam pvm, Func<IMessage, FieldDescriptor, T> selector, Action<IMessage, FieldDescriptor, T> assign_to_param,
Func<IMessage, IMessage> message_override = null, T default_value = default) where TParam : GenericOrderParamVM<TMutable>, IGenericOrderParamVM<T>
TParam attached<T, TParam>(TParam pvm, Func<IMessage, FieldDescriptor, T> selector, Action<IMessage, FieldDescriptor, T> assign_to_param, T default_value = default) where TParam : GenericOrderParamVM<TMutable>, IGenericOrderParamVM<T>
{
add_property<T>(
pvm.descriptor.Name,
mdef => mdef != null ? selector( message_override == null ? mdef : message_override(mdef), pvm.descriptor) : default_value,
(mdef, v) => assign_to_param(message_override == null ? mdef : message_override(mdef), pvm.descriptor, v),
mdef => mdef != null ? selector(mdef, pvm.descriptor) : default_value,
(mdef, v) => assign_to_param(mdef, pvm.descriptor, v),
() => pvm.value,
v => pvm.value = v,
pvm.subscribe_value(),
@@ -4,14 +4,14 @@ using OffsetDefi = bts.api.orderman.OffsetOrderDefinitionImmutable;
namespace mbts.spark {
static partial class OrderTypeVMFactory {
class OffsetOrderVM : OrderTypeVMBase<OffsetDef, OffsetDefi> {
readonly Property<int?> _tick_offset_on_deploy;
readonly Property<uint?> _tick_offset_on_deploy;
public OffsetOrderVM(AlgoKey key, string display_name, AlgoEditingPermissions editing_permissions)
: base(key, display_name, editing_permissions) {
_tick_offset_on_deploy = add_nullable_property(nameof(tick_offset_on_deploy), OffsetDef.TickOffsetOnDeployFieldNumber, 0);
_tick_offset_on_deploy = add_nullable_property(nameof(tick_offset_on_deploy), OffsetDef.TickOffsetOnDeployFieldNumber, 0u);
}
public int? tick_offset_on_deploy { get => _tick_offset_on_deploy.Value; set => _tick_offset_on_deploy.set(value); }
public uint? tick_offset_on_deploy { get => _tick_offset_on_deploy.Value; set => _tick_offset_on_deploy.set(value); }
}
}
}
+2 -3
View File
@@ -18,8 +18,7 @@
<LangVersion>7.2</LangVersion>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<WarningsAsErrors />
<Version>$(major).$(minor).$(patch)</Version>
<Version Condition="'$(version)'=='..'">1.0.0</Version>
<Version>1.0.0</Version>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="../spark_api/spark_api.csproj" />
@@ -35,7 +34,7 @@
<PackageReference Include="Google.Protobuf" Version="3.6.1" />
<PackageReference Include="IronPython" Version="2.7.7" />
<PackageReference Include="NAudio" Version="1.8.4" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
<PackageReference Include="NUnit" Version="3.10.1" />
<PackageReference Include="NUnit3TestAdapter" Version="3.8.0" />
@@ -691,7 +691,7 @@
<TextBlock VerticalAlignment="Center" >Tick Offset</TextBlock>
<c:HelpButton Margin="{StaticResource Margin.LP1}" ToolTip="How many ticks off the inside market to deploy the order, this guards against crossing the market inadventently" />
</StackPanel>
<c:TickUpDownInt x:Name="PART_TickOffsetOnDeploy_TickUpDownUInt" Grid.Column="2" Value="{Binding tick_offset_on_deploy}"/>
<c:TickUpDownUInt x:Name="PART_TickOffsetOnDeploy_TickUpDownUInt" Grid.Column="2" Value="{Binding tick_offset_on_deploy}"/>
<uag:AlgoPickerNodeView
x:Name="PART_Child_AlgoPickerNodeView"
Grid.Row="2"
@@ -64,25 +64,6 @@ namespace mbts.ui {
}
}, can_execute == null ? null : new Func<object, bool>(_ => can_execute()));
public static IDialogCommand export_csv(
Func<string> get_file_content,
string source_window_name) =>
new AnonymousFileDialogCommand<object>(_ =>
_create_save_file_dialog(
Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
$"BTS_Spark_{source_window_name}_{DateTime.Now.ToString("yyyyMMdd_HHmm")}.csv",
new[] { ("CSV (comma delimited)", new string[] { "csv" }) }
),
(_, file) => {
try {
File.WriteAllText(file, get_file_content.Invoke());
} catch (Exception ex) {
BTSMessageBox.Show($"Error exporting data to csv: {ex}.", "CSV Export Error", BTSMessageBoxButtons.OK, System.Windows.MessageBoxImage.Error, true, false, true);
}
},
// we are always able to perform an export, even when no rows (it will just be a header)
(_) => true);
static TDialog _create_file_dialog<TDialog>(string initial_dir = null, IReadOnlyList<(string name, string[] extensions)> filter_items = null) where TDialog : FileDialog, new() {
var rv = new TDialog();
if (!string.IsNullOrEmpty(initial_dir))
@@ -292,9 +292,7 @@ namespace mbts.spark {
int count = 0;
double factored_base = log10_diff > 0 ? reduced_target_base * Math.Pow(10, Math.Ceiling(log10_diff)) : reduced_target_base;
do {
// Note that the modulus operator is not used here due to rounding errors.
// Such a rounding errror was the cause of the bug https://bluetradesys.atlassian.net/browse/SP-283.
if (MathUtils.is_int(factored_base / raw_base))
if (factored_base % raw_base == 0)
return new TickFactors(factored_base, factored_base / raw_base);
factored_base *= 10;
} while (++count < 10);
@@ -4,8 +4,6 @@ using System.Runtime.InteropServices;
using System.Security;
using Google.Protobuf;
using security_key = System.UInt32;
using bts.co2;
using System.Linq;
namespace mbts.co2
{
@@ -87,7 +85,6 @@ namespace mbts.co2
[DllImport("libspark")]
internal unsafe static extern void post_on_scan_security_thread(Action callback);
}
internal static class Co2NativeTestMethods
@@ -136,59 +133,5 @@ namespace mbts.co2
[DllImport("libspark")]
internal static extern void co2_test_get_constants(out ulong max_depth, out ulong max_implied_depth, out sbyte nan_exponent);
internal unsafe delegate void raw_receive_pb_or_string(byte* buffer, int buffer_size);
[DllImport("libspark")]
private static unsafe extern void raw_co2_compute_synthetic_book(
byte[] security_buffer,
int security_length,
IntPtr[] leg_books,
int[] leg_lengths,
int leg_books_length,
raw_receive_pb_or_string callback);
internal static unsafe BookMessageImmutable co2_compute_synthetic_book(SecurityImmutable synthetic, params BookMessageImmutable[] books) {
BookMessage result = null;
string error = null;
var security_buffer = synthetic.ToByteArray();
// var h = GCHandle.Alloc(null, GCHandleType.Pinned).
var book_buffers =
books
.Select(b => b.ToByteArray())
.ToArray();
GCHandle[] book_buffer_handles =
book_buffers
.Select(b => GCHandle.Alloc(b,GCHandleType.Pinned))
.ToArray();
IntPtr[] book_buffer_pointers =
book_buffer_handles
.Select(h => h.AddrOfPinnedObject())
.ToArray();
var lengths =
book_buffers
.Select(b => b.Length)
.ToArray();
raw_co2_compute_synthetic_book(
security_buffer,
security_buffer.Length,
book_buffer_pointers,
lengths,
book_buffers.Length,
(byte* buffer, int length) => {
if (length < 0) {
error = new string((char*)buffer,0,-1 * length);
}
else {
result = Co2NativeMethods.deserialize<BookMessage>(buffer, (ulong)length);
}
});
if(error != null) {
// C# style multiple return values
throw new Exception(error);
}
return new BookMessageImmutable(result);
}
}
}
-42
View File
@@ -52,49 +52,7 @@ namespace mbts.co2 {
return _mantissa.GetHashCode();
}
public static IntPrice from_double(double price, sbyte precision) {
if (double.IsNaN(price)) return NaN;
if (Math.Abs(price%1) != 0) {
double rounding = 0.5 * Math.Pow(10,-precision);
price += (price > 0) ? rounding : -rounding;
price *= Math.Pow(10,precision);
return new IntPrice((long)price, (sbyte)-precision);
}
return new IntPrice((long)price, 0);
}
public static IntPrice NaN = new IntPrice(0,127);
static double[] powers_10 = {
1E-20, 1E-19, 1E-18, 1E-17, 1E-16, 1E-15, 1E-14, 1E-13, 1E-12, 1E-11, 1E-10, 1E-9, 1E-8, 1E-7, 1E-6, 1E-5, 1E-4, 1E-3, 1E-2, 1E-1,
1E0,
1E1, 1E2, 1E3, 1E4, 1E5, 1E6, 1E7, 1E8, 1E9, 1E10, 1E11, 1E12, 1E13, 1E14, 1E15, 1E16, 1E17, 1E18, 1E19, 1E20};
static int max_abs_power_10 = powers_10.Length / 2;
static double pow10(int power)
{
int offset = power + max_abs_power_10;
int powers_10_sz = powers_10.Length;
bts.Log.assert(offset >= 0 && offset < powers_10_sz);
if (offset >= 0 && offset < powers_10_sz)
{
return powers_10[offset];
}
return double.NaN;
}
public static IntPrice from_double(double price, int precision = 9)
{
if (Double.IsNaN(price))
return NaN;
if (Math.Abs(price - Math.Truncate(price)) != 0.0)
{
double rounding = 0.5 * pow10(-precision);
price += (price > 0.0) ? rounding : -rounding;
price *= pow10(precision);
return new IntPrice((long)price, Convert.ToSByte(-precision));
}
return new IntPrice((long)price, 0);
}
}
}
@@ -1,6 +1,4 @@
using bts;
using System.Collections.Generic;
using System.Linq;
namespace mbts.co2 {
public static class NativePriceHelpers {
@@ -40,60 +38,6 @@ namespace mbts.co2 {
public const uint COCONUT_MAX_DEPTH = 10;
public const uint COCONUT_MAX_IMPLIED_DEPTH = 2;
internal const sbyte COCONUT_NAN_EXPONENT = 127;
public static double side_at(this bts.co2.BookMessage book, bts.api.Side side, int level)
{
if(side == bts.api.Side.Buy)
return bid_at(book, level);
else
return ask_at(book, level);
}
public static uint sidesize_at(this bts.co2.BookMessage book, bts.api.Side side, int level)
{
if (side == bts.api.Side.Buy)
return bidsize_at(book, level);
else
return asksize_at(book, level);
}
public static double bid_at(this bts.co2.BookMessage book, int level)
{
var lev = book.Bids[level];
return NativePriceHelpers.to_double(lev.Mantissa, (sbyte)lev.Exponent);
}
public static double ask_at(this bts.co2.BookMessage book, int level)
{
var lev = book.Asks[level];
return NativePriceHelpers.to_double(lev.Mantissa, (sbyte)lev.Exponent);
}
public static uint bidsize_at(this bts.co2.BookMessage book, int level)
{
var lev = book.Bids[level];
return lev.Size;
}
public static uint asksize_at(this bts.co2.BookMessage book, int level)
{
var lev = book.Asks[level];
return lev.Size;
}
public static double price(this bts.co2.PriceSizeMessage p)
{
return NativePriceHelpers.to_double(p.Mantissa, (sbyte)p.Exponent);
}
public static double price(this bts.co2.TradeMessage p)
{
return NativePriceHelpers.to_double(p.Mantissa, (sbyte)p.Exponent);
}
public static IList<double> all_bids(this bts.co2.BookMessage book)
{
var lev = book.Bids.Select(x => NativePriceHelpers.to_double(x.Mantissa, (sbyte)x.Exponent)).ToList();
return lev;
}
public static IList<double> all_asks(this bts.co2.BookMessage book)
{
var lev = book.Asks.Select(x => NativePriceHelpers.to_double(x.Mantissa, (sbyte)x.Exponent)).ToList();
return lev;
}
}
}
@@ -4,5 +4,4 @@ using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("sparkcmd")]
[assembly: InternalsVisibleTo("spark_test")]
[assembly: InternalsVisibleTo("spark_fix")]
[assembly: InternalsVisibleTo("spark_historical")]
+1
View File
@@ -11,6 +11,7 @@ namespace bts.api
{
fix_tag = 8507,
fix_tag_is_header = 8509,
skip_fix_tag = 8510,
}
public enum EnumValueOptions
{
@@ -1,147 +0,0 @@
using System;
using System.Collections.Generic;
using Google.Protobuf;
using Google.Protobuf.Collections;
using Google.Protobuf.WellKnownTypes;
using mbts.co2;
namespace bts.history
{
public interface IHasMsgSeqNum
{
uint MsgSeqNum { get; }
}
public interface IHasDateTimeStamp
{
DateTime trade_date { get; set;}
DateTime sending_time { get; set;}
DateTime transact_time { get; set; }
}
public interface IHasTimestamp
{
Timestamp SendingTime { get; set; }
Timestamp TransactTime { get; set; }
}
public interface IHasMdPacket
{
MarketDataIncrementalRefresh Md{ get; }
}
public interface IHasMdEntry
{
MDEntry MdEntry { get; }
int EntryIndex { get; }
}
public interface IHasTopBook : IHasMdEntry, IHasMdPacket
{
co2.TopBookMessage TopBook { get; set; }
}
public interface IHasBook : IHasMdEntry, IHasMdPacket
{
co2.BookMessage Book { get; set; }
}
public interface IHasTrade : IHasMdEntry, IHasMdPacket
{
co2.TradeMessage Trade { get; set; }
}
public interface IHasMBO : IHasMdPacket
{
RepeatedField<OrderIDEntry> Orders { get; }
}
public sealed partial class HistoryRow : IHasTopBook, IHasMBO, IHasTrade, IHasBook, IHasDateTimeStamp, IHasTimestamp, IHasMsgSeqNum
{
public DateTime trade_date { get { return DateTime.SpecifyKind(this.TradeDate.ToDateTime(), DateTimeKind.Utc); }
set { this.TradeDate = Timestamp.FromDateTime(value); } }
public DateTime sending_time { get { return DateTime.SpecifyKind(this.SendingTime.ToDateTime(), DateTimeKind.Utc); }
set { this.SendingTime = Timestamp.FromDateTime(value); } }
public DateTime transact_time { get { return DateTime.SpecifyKind(this.TransactTime.ToDateTime(), DateTimeKind.Utc); }
set { this.TransactTime = Timestamp.FromDateTime(value); } }
public HistoryRow add_orders(IEnumerable<OrderIDEntry> orderentries)
{
this.Orders.AddRange(orderentries);
return this;
}
}
public interface IMBOMessage
{
MDUpdateAction OrderUpdateAction {get;}
ulong OrderId {get;}
uint SecurityId {get;}
string SecurityDesc {get;}
ulong MdOrderPriority {get;}
double MdEntryPx {get;}
uint MdPriceLevel {get;}
ulong MdDisplayQty {get;}
uint LastQty {get;}
MDEntryType MdEntryType {get;}
uint ReferenceId {get;}
}
public sealed partial class MBOMessage : IMBOMessage
{
public MDUpdateAction OrderUpdateAction => OrderEntry != null ? OrderEntry.OrderUpdateAction : MdEntry.MdUpdateAction;
public ulong OrderId => OrderEntry != null ? OrderEntry.OrderId : MdEntry.OrderId;
public uint SecurityId => MdEntry.SecurityId;
public string SecurityDesc => MdEntry.Symbol;
public ulong MdOrderPriority => OrderEntry != null ? OrderEntry.MdOrderPriority : MdEntry.MdOrderPriority;
public double MdEntryPx => MdEntry.MdEntryPx;
public uint MdPriceLevel => MdEntry.MdPriceLevel;
public ulong MdDisplayQty => OrderEntry != null ? OrderEntry.MdDisplayQty : MdEntry.MdDisplayQty;
public uint LastQty => OrderEntry != null ? OrderEntry.LastQty : MdEntry.LastQty;
public MDEntryType MdEntryType => MdEntry.MdEntryType;
public uint ReferenceId => OrderEntry != null ? OrderEntry.ReferenceId : MdEntry.ReferenceId;
public uint NumberOfOrders => MdEntry.NumberOfOrders;
}
public sealed partial class MarketDataIncrementalRefresh
{
public MarketDataIncrementalRefresh add_entries(IEnumerable<MDEntry> mdentries, IEnumerable<OrderIDEntry> orderentries)
{
this.MdEntries.AddRange(mdentries);
this.OrderIdEntries.AddRange(orderentries);
return this;
}
}
public interface ITradeDetail
{
ulong OrderId { get; set; }
uint LastQty { get; set; }
ITradeDetail clone();
}
public sealed partial class OrderIDEntry : ITradeDetail
{
ITradeDetail ITradeDetail.clone()
{
return this.Clone();
}
}
}
namespace bts.co2
{
public sealed partial class BookMessage
{
public BookMessage add_bids_and_asks(IEnumerable<PriceSizeMessage> bids, IEnumerable<PriceSizeMessage> asks)
{
this.Bids.AddRange(bids);
this.Asks.AddRange(asks);
return this;
}
}
public sealed partial class TradeMessage
{
public double price => NativePriceHelpers.to_double(this.Mantissa, (sbyte)this.Exponent);
}
}
+2
View File
@@ -0,0 +1,2 @@
dotnet pack
dotnet nuget push
+5 -5
View File
@@ -3,19 +3,17 @@
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<Authors>Blue Trading Systems</Authors>
<Company>Blue Trading Systems</Company>
<Description />
<PackageId>Spark_API</PackageId>
<Product>Spark</Product>
<Description />
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Platforms>x64</Platforms>
<PlatformTarget>AnyCPU</PlatformTarget>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<WarningsAsErrors />
<Version>$(major).$(minor).$(patch)</Version>
<Version Condition="'$(version)'=='..'">0.0.0</Version>
<Version>1.0.0</Version>
<LangVersion>7.2</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Google.Protobuf" Version="3.6.1" />
<PackageReference Include="System.Collections.Immutable" Version="1.5.0" />
@@ -26,10 +24,12 @@
<Proto3 Include="**/*.proto" />
<Proto3 Include="../../lib/api/*.proto" />
<Proto3 Include="../../lib/api/services/*.proto" />
<!--Proto3 Remove="../../lib/api/services/MarketDataRelay.proto" /-->
<Proto3 Include="../../lib/md/protos/Co2.proto" />
<Proto3 Include="../../lib/domain_model/Security.proto" />
<Proto3 Include="../../lib/sparkproto/SparkProtos.proto" />
<Proto3 Update="../../lib/api/services/OutOfProcessURLListener.proto">
<!-- <CompileOptions>internal_access:</CompileOptions> -->
</Proto3>
</ItemGroup>
</Project>
@@ -1,10 +0,0 @@
using Google.Protobuf;
namespace bts.api {
public sealed partial class Product : ICustomDiagnosticMessage {
public string ToDiagnosticString() {
return $"{this.Symbol}:{this.Type}:{this.Exchange}";
}
}
}
@@ -2,5 +2,4 @@ using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("spark")]
[assembly: InternalsVisibleTo("sparkcmd")]
[assembly: InternalsVisibleTo("spark_test")]
[assembly: InternalsVisibleTo("spark_historical")]
+1 -2
View File
@@ -7,8 +7,7 @@
<PlatformTarget>AnyCPU</PlatformTarget>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<WarningsAsErrors />
<Version>$(major).$(minor).$(patch)</Version>
<Version Condition="'$(version)'=='..'">0.0.0</Version>
<Version>1.0.0</Version>
<LangVersion>7.2</LangVersion>
</PropertyGroup>
-52
View File
@@ -1,52 +0,0 @@
using System;
using System.IO;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Reflection;
namespace bts.utils.csv {
public static class CsvHelper {
public static string ToCsv<T>(this IEnumerable<T> items, OrderedDictionary properties = null) where T : class {
var output = "";
var delimiter = ",";
if (properties == null) {
properties = new OrderedDictionary();
foreach (var pi in typeof(T).GetProperties()) {
properties.Add(pi.Name, pi);
}
}
using (var sw = new StringWriter()) {
var dict_values = properties.Values.OfType<PropertyInfo>();
var header = dict_values.Select(n => n.Name).Aggregate((first, second) => first + delimiter + second);
sw.WriteLine(header);
foreach (var i in items) {
var row = dict_values.Select(x => x.GetValue(i, null))
.Select(x => x == null ? "null" : x.ToString())
.Aggregate((first, second) => first + delimiter + second);
sw.WriteLine(row);
}
output = sw.ToString();
}
return output;
}
public static OrderedDictionary create_ordering_maintainer(Type t, string[] property_names_in_order) {
OrderedDictionary od = new OrderedDictionary();
var props = t.GetProperties();
foreach (var n in property_names_in_order) {
var query = props.Where(pi => pi.Name == n);
if (query.Any()) {
var property_info = query.First();
if (!od.Contains(property_info)) {
od.Add(n, property_info);
}
}
}
return od;
}
}
}
Binary file not shown.
@@ -66,23 +66,9 @@ namespace bts.excel.rtd
if (string.IsNullOrEmpty(contract))
return Observable.Return(new []{"Can't Parse Contract: " + contract ?? string.Empty});
Func<SecurityImmutable, bool> desc = null;
switch(ven)
{
case Venue.Sim:
case Venue.Glbx:
desc = (x=> x.Glbx.SecurityDesc == contract);
break;
case Venue.Ice:
desc = (x=> x.Ice.SecurityDesc == contract);
break;
default:
desc = (x => true);
break;
}
Func<SecurityImmutable, bool> where = (x => x.Exchange == ven && x.Symbol == symbol && x.security_type() == sectype &&
x.Glbx.SecurityDesc == contract);
Func<SecurityImmutable, bool> where = (x => x.Exchange == ven && x.Symbol == symbol && x.security_type() == sectype && desc(x) );
var stream = market_data(ven).subscribe_combined(where);
return stream;
}
+2 -3
View File
@@ -17,8 +17,7 @@
<PlatformTarget>AnyCPU</PlatformTarget>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<WarningsAsErrors />
<Version>$(major).$(minor).$(patch)</Version>
<Version Condition="'$(version)'=='..'">1.0.0</Version>
<Version>1.0.0</Version>
</PropertyGroup>
<ItemGroup>
@@ -26,7 +25,7 @@
<PackageReference Include="System.Reactive" Version="3.1.1" />
<PackageReference Include="System.Reactive.PlatformServices" Version="3.1.1" />
<PackageReference Include="NUnit" Version="3.10.1" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
<PackageReference Include="System.Linq.Dynamic" Version="1.0.7" />
<PackageReference Include="ExcelDna.AddIn" Version="0.34.6" />
Binary file not shown.
+1 -8
View File
@@ -90,14 +90,7 @@ namespace bts.excel
{
if(string.IsNullOrEmpty(json))
json = "{}";
try
{
request = JsonParser.Default.Parse(json, desc);
}
catch(InvalidProtocolBufferException)
{
request = (IMessage) Newtonsoft.Json.JsonConvert.DeserializeObject(json, desc.ClrType);
}
request = JsonParser.Default.Parse(json, desc);
}
}
return request;
+1 -62
View File
@@ -25,68 +25,7 @@ namespace bts.excel
else if (!string.IsNullOrEmpty(key1))
val = jo[key1];
return val.ToString();
}
static Google.Protobuf.JsonFormatter _formatter =
new Google.Protobuf.JsonFormatter(new Google.Protobuf.JsonFormatter.Settings(true));
[ExcelFunction]
public static object bts_json_create(string type)
{
System.Type t = find_full_type_in_all_assemblies(type);
object obj = Activator.CreateInstance(t);
foreach(var pr in t.GetProperties())
{
object val = null;
try
{
val = Activator.CreateInstance(pr.PropertyType);
}
catch {}
try
{
pr.SetValue(obj, val);
}
catch {}
}
string s = "{}";
if(obj is Google.Protobuf.IMessage imsg)
s = _formatter.Format(imsg);
else
s = JsonConvert.SerializeObject(obj, Formatting.Indented);
return s;
}
[ExcelFunction]
public static object bts_json_fill(string root, string key, string value)
{
var jo = JObject.Parse(root);
jo[key] = value;
var s = jo.ToString();
return s;
}
[ExcelFunction]
public static object bts_date_to_json(object dt, bool is_duration = false)
{
string s = "{}";
if(is_duration)
{
var span = TimeSpan.FromDays((double)dt);
var ts = Google.Protobuf.WellKnownTypes.Duration.FromTimeSpan(span);
s = JsonConvert.SerializeObject(ts, Formatting.None);
s = _formatter.Format(ts);
s = s.Replace(@"""", "");
}
else
{
var dd = DateTime.FromOADate((double)dt);
var utc = DateTime.SpecifyKind(dd, DateTimeKind.Utc);
var ts = Google.Protobuf.WellKnownTypes.Timestamp.FromDateTime(utc);
s = JsonConvert.SerializeObject(ts, Formatting.None);
s = _formatter.Format(ts);
s = s.Replace(@"""", "");
}
return s;
}
}
public static bool parse_venue(string exch, out Venue ven)
{
+6 -25
View File
@@ -36,29 +36,13 @@ namespace bts.fix
class FixRouter : QuickFix.MessageCracker, IFIXSession, IFixRouter
{
readonly ConcurrentDictionary<SessionID, QuickFix.IApplication> _sessions = new ConcurrentDictionary<SessionID, IApplication>();
readonly Func<IFixRouter, SessionID, IApplication> _factory;
readonly Func<IFixRouter, SessionID, IApplication> _factory;
readonly MarketDataClient _md = new MarketDataClient();
readonly object _lock = new object();
readonly MarketDataService _md;
private readonly IDisposable _security_sub;
readonly ConcurrentDictionary<security_key, SecurityImmutable> _id_to_security = new ConcurrentDictionary<security_key, SecurityImmutable>();
readonly ConcurrentDictionary<string, SecurityImmutable> _desc_to_security = new ConcurrentDictionary<string, SecurityImmutable>();
public FixRouter(Func<IFixRouter, SessionID, IApplication> factory)
{
_factory = factory;
using(var service_context = new ServiceContext())
{
_md = service_context.locate<MarketDataService>();
_security_sub = _md.subscribe_securities().Subscribe( x =>
{
foreach( var sec in x.all)
{
var imm = sec.immutable();
_id_to_security[sec.Id] = imm;
_desc_to_security[imm.security_desc()] = imm;
}
});
}
}
IApplication session(SessionID sessionID)
@@ -230,21 +214,18 @@ namespace bts.fix
IEnumerable<SecurityImmutable> IFixRouter.get_securities()
{
return _id_to_security.Values;
return _md.securities;
}
SecurityImmutable? IFixRouter.lookup(uint key)
{
if(_id_to_security.TryGetValue(key, out SecurityImmutable sec))
return sec;
else
return null;
return _md.lookup(key);
}
SecurityImmutable? IFixRouter.lookup(string desc)
{
if (_desc_to_security.TryGetValue(desc, out SecurityImmutable sec))
return sec;
if (_md.lookup_security_key_from_desc(desc, out uint key))
return _md.lookup(key);
else
return null;
}
+10 -5
View File
@@ -63,10 +63,10 @@ namespace bts.fix
{
object obj = Activator.CreateInstance(desc.ClrType);
IMessage msg = (IMessage)obj;
return setup_message(msg, fix);
return fix_to_imsg(msg, fix);
}
public static IMessage setup_message(IMessage msg, QuickFix.FieldMap fix)
public static IMessage fix_to_imsg(IMessage msg, QuickFix.FieldMap fix)
{
foreach (var fd in msg.Descriptor.Fields.InDeclarationOrder())
{
@@ -78,8 +78,8 @@ namespace bts.fix
}
return msg;
}
static int get_tag(IMessage msg, FieldDescriptor fd, out bool is_header)
public static int get_tag(IMessage msg, FieldDescriptor fd, out bool is_header)
{
is_header = false;
int fieldnum = 0;
@@ -92,7 +92,12 @@ namespace bts.fix
{
int tagbase = 0;
if(msg.Descriptor.CustomOptions?.TryGetInt32((int)ApioptionsReflection.MessageOptions.fix_algostrategy_tagbase, out tagbase) ?? false)
return fd.FieldNumber + tagbase;
{
bool skip = false;
fd.CustomOptions?.TryGetBool((int)ApioptionsReflection.FieldOptions.skip_fix_tag, out skip);
if(!skip)
return fd.FieldNumber + tagbase;
}
}
throw new QuickFix.FieldNotFoundException(fd.FieldNumber);
}
+508
View File
@@ -0,0 +1,508 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using bts.api.orderman;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Linq;
using Google.Protobuf;
using Google.Protobuf.Reflection;
using System.Globalization;
namespace bts.fix
{
public class ATDL
{
readonly SortedList<string, FIXAlgoDefinition> _atdl = new SortedList<string, FIXAlgoDefinition>();
public IReadOnlyDictionary<string, FIXAlgoDefinition> algo_definitions => _atdl;
public const string default_algo_import_path = "./spark_algos.json";
public const string default_atdl_export_file_name = "spark_algos.xml";
const string core_ns = "http://www.fixprotocol.org/FIXatdl-1-1/Core";
const string layout_ns = "http://www.fixprotocol.org/FIXatdl-1-1/Layout";
const string val_ns = "http://www.fixprotocol.org/FIXatdl-1-1/Validation";
const string flow_ns = "http://www.fixprotocol.org/FIXatdl-1-1/Flow";
const string tz_ns = "http://www.fixprotocol.org/FIXatdl-1-1/Timezones";
const string region_ns = "http://www.fixprotocol.org/FIXatdl-1-1/Regions";
readonly static Dictionary<Type, int> _algo_types = new Dictionary<Type, int>();
static ATDL()
{
foreach (var fd in CustomOrderDefinition.Descriptor.Fields.InDeclarationOrder())
{
if (fd.FieldType == FieldType.Message)
_algo_types[fd.MessageType.ClrType] = 0;
}
}
public ATDL(string path = default_algo_import_path)
{
path = path ?? default_algo_import_path;
using(var fs = new StreamReader(path))
{
var algos = JsonParser.Default.Parse<FIXAlgoDefinitions>(fs);
foreach(var algo in algos.AlgoStrategy)
{
_atdl[algo.Name] = algo;
}
}
}
static bool is_directory(string path)
{
FileAttributes attr = File.GetAttributes(path);
return attr.HasFlag(FileAttributes.Directory);
}
public static void validate_fix_atdl(string validate_atdl_path)
{
if(is_directory(validate_atdl_path))
{
string[] files = Directory.GetFiles(validate_atdl_path, "*.xml", SearchOption.AllDirectories);
foreach(var f in files)
valididate_single_atdl_file(f);
}
else
valididate_single_atdl_file(validate_atdl_path);
}
static void valididate_single_atdl_file(string path)
{
Log.assert(!is_directory(path));
var reader = new Atdl4net.Xml.StrategiesReader();
var strats = reader.Load(path);
foreach (var strat in strats)
{
Console.WriteLine("Strategy " + strat.Name);
Dictionary<int, string> tagname = new Dictionary<int, string>();
Dictionary<string, int> nametag = new Dictionary<string, int>();
foreach(var par in strat.Parameters)
{
tagname.Add((int)par.FixTag.Value, par.Name);
nametag.Add(par.Name, (int)par.FixTag.Value);
Console.WriteLine(" Parameter " + par.Name);
}
}
XmlSchemaSet schema = new XmlSchemaSet();
const string xsdpath = "./atdl/schema/";
schema.Add(core_ns, xsdpath + "fixatdl-core-1-1.xsd");
schema.Add(flow_ns, xsdpath + "fixatdl-flow-1-1.xsd");
schema.Add(layout_ns, xsdpath + "fixatdl-layout-1-1.xsd");
schema.Add(region_ns, xsdpath + "fixatdl-regions-1-1.xsd");
schema.Add(tz_ns, xsdpath + "fixatdl-timezones-1-1.xsd");
schema.Add(val_ns, xsdpath + "fixatdl-validation-1-1.xsd");
XmlReader rd = XmlReader.Create(path);
XDocument doc = XDocument.Load(rd, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo);
doc.Validate(schema, (object _, ValidationEventArgs e) =>
{
XmlSeverityType type = XmlSeverityType.Warning;
if (Enum.TryParse<XmlSeverityType>("Error", out type))
{
if (type == XmlSeverityType.Error) throw new Exception(e.Exception.ToString() +
"\n line number: " + e.Exception.LineNumber.ToString());
}
});
Console.WriteLine("File " + path + " looks valid ");
}
public void write_fix_atdl(string path, bool single_file)
{
if(single_file && is_directory(path))
{
Directory.CreateDirectory(path);
path = path + "/" + default_atdl_export_file_name;
}
if(single_file)
write_single_fix_atdl(path, _atdl.Values);
else
{
Log.assert(is_directory(path));
Directory.CreateDirectory(path);
foreach(var algo in _atdl.Values)
{
var fname = path + $"/Spark_{algo.Name}.xml";
write_single_fix_atdl(fname, new[]{algo});
}
}
}
static void write_single_fix_atdl(string path, IEnumerable<FIXAlgoDefinition> algos)
{
var s = new XmlWriterSettings();
s.Encoding = System.Text.Encoding.UTF8;
s.OmitXmlDeclaration = false;
s.Indent = true;
s.IndentChars = " ";
using(XmlWriter w = XmlWriter.Create(path, s))
{
w.WriteStartDocument();
w.WriteStartElement("Strategies", core_ns);
w.WriteAttributeString("xmlns", "", null, core_ns);
w.WriteAttributeString("xmlns", "val", null, val_ns);
w.WriteAttributeString("xmlns", "lay", null, layout_ns);
w.WriteAttributeString("xmlns", "flow", null, flow_ns);
w.WriteAttributeString("xmlns", "tz", null, tz_ns);
w.WriteAttributeString("xmlns", "xsi", null, "http://www.w3.org/2001/XMLSchema-instance");
w.WriteAttributeString("xsi", "schemaLocation", null, "http://www.fixprotocol.org/FIXatdl-1-1/Core fixatdl-core-1-1.xsd");
FIXAlgoDefinition.Descriptor.FindFieldByNumber(FIXAlgoDefinition.NameFieldNumber)
.CustomOptions.TryGetInt32((int)api.ApioptionsReflection.FieldOptions.fix_tag, out int nametag);
w.WriteAttributeString("strategyIdentifierTag", nametag.ToString());
FIXAlgoDefinition.Descriptor.FindFieldByNumber(FIXAlgoDefinition.VersionFieldNumber)
.CustomOptions.TryGetInt32((int)api.ApioptionsReflection.FieldOptions.fix_tag, out int vertag);
w.WriteAttributeString("versionIdentifierTag", vertag.ToString());
foreach(var strat in algos)
{
w.WriteStartElement("Strategy");
w.WriteAttributeString("name", strat.Name);
w.WriteAttributeString("uiRep", strat.Name);
w.WriteAttributeString("wireValue", strat.Name);
string ver = strat.Version;
if(string.IsNullOrEmpty(ver))
ver = "1";
w.WriteAttributeString("version", ver);
w.WriteAttributeString("fixMsgType", "D");
w.WriteAttributeString("providerID", "BTS");
{
w.WriteStartElement("Regions");
w.WriteStartElement("Region");
w.WriteAttributeString("name", "TheAmericas");
w.WriteAttributeString("inclusion", "Include");
w.WriteStartElement("Country");
w.WriteAttributeString("CountryCode", "US");
w.WriteAttributeString("inclusion", "Include");
w.WriteEndElement();
w.WriteEndElement();
w.WriteEndElement();
}
{
w.WriteStartElement("Markets");
w.WriteStartElement("Market");
w.WriteAttributeString("MICCode", "XCME");
w.WriteAttributeString("inclusion", "Include");
w.WriteEndElement();
w.WriteEndElement();
}
{
w.WriteStartElement("SecurityTypes");
w.WriteStartElement("SecurityType");
w.WriteAttributeString("name", "FUT");
w.WriteAttributeString("inclusion", "Include");
w.WriteEndElement();
w.WriteEndElement();
}
var imsg = extract_order_from_custom(strat.Definition);
visit_parameters(w, imsg);
visit_layout(w, imsg);
w.WriteEndElement();
}
}
}
static bool get_tag_and_name(IMessage m, FieldDescriptor fd, FieldDescriptor parent_fd,
Dictionary<int, int> tags, Dictionary<string, int> names,
out int tag, out string fieldname)
{
tag = ProtoFix.get_tag(m, fd, out bool is_header);
fieldname = fd.Name;
if (fd.FieldType == FieldType.Message && fd.MessageType.ClrType == typeof(bts.api.orderman.CustomOrderDefinition))
{
return false;
}
//TODO the concept of the collision due to using the same order type in different places in tree isn't great
if (tags.ContainsKey(tag))
return false;
tags[tag] = 0;
if (names.ContainsKey(fieldname))
{
if (parent_fd != null)
{
fieldname = parent_fd.Name + "_" + fieldname;
if (names.ContainsKey(fieldname))
return false;
}
else
return false;
}
names[fieldname] = 0;
//TODO the concept of the collision due to using the same order type in different places in tree isn't great
return true;
}
static void visit_parameters(XmlWriter w, IMessage imsg)
{
Dictionary<int, int> tags = new Dictionary<int, int>();
Dictionary<string, int> names = new Dictionary<string, int>();
message_visitor(imsg, (m, fd, parent_fd) =>
{
try
{
if(!get_tag_and_name(m, fd, parent_fd, tags, names, out int tag, out string fieldname))
return;
w.WriteStartElement("Parameter");
w.WriteAttributeString("name", fieldname);
w.WriteAttributeString("fixTag", tag.ToString());
if (fd.FieldType == FieldType.Message && fd.MessageType.ClrType == typeof(Google.Protobuf.WellKnownTypes.Timestamp))
{
w.WriteAttributeString("xsi", "type", null, "UTCTimestamp_t");
w.WriteAttributeString("localMktTz", "America/New_York");
}
else if (fd.FieldType == FieldType.Message && fd.MessageType.ClrType == typeof(bts.spark.QuantityMeasure))
{
w.WriteAttributeString("xsi", "type", null, "Int_t");
w.WriteAttributeString("minValue", "0");
}
else if (fd.FieldType == FieldType.Enum)
{
w.WriteAttributeString("xsi", "type", null, "Char_t");
foreach (var val in fd.EnumType.Values)
{
string eval = null;
if (val.CustomOptions?.TryGetString((int)bts.api.ApioptionsReflection.EnumValueOptions.fix_value, out eval) ?? false)
{
w.WriteStartElement("EnumPair");
w.WriteAttributeString("enumID", val.Name);
w.WriteAttributeString("wireValue", eval);
w.WriteEndElement();
}
}
}
else if (fd.FieldType == FieldType.Int32)
{
w.WriteAttributeString("xsi", "type", null, "Int_t");
}
else if (fd.FieldType == FieldType.Double || fd.FieldType == FieldType.Float)
{
w.WriteAttributeString("xsi", "type", null, "Float_t");
}
else if (fd.FieldType == FieldType.UInt32)
{
w.WriteAttributeString("xsi", "type", null, "Int_t");
w.WriteAttributeString("minValue", "0");
}
else if( fd.FieldType == FieldType.Bool)
{
w.WriteAttributeString("xsi", "type", null, "Boolean_t");
}
else
{
w.WriteAttributeString("xsi", "type", null, "String_t");
}
w.WriteEndElement();
}
catch (QuickFix.FieldNotFoundException) { }
});
}
static string title_case(string title, bool insert_spaces = true)
{
var s = new CultureInfo("en").TextInfo.ToTitleCase(title.ToLower().Replace("_", " "));
if(!insert_spaces)
return s.Replace(" ", "");
else
return s;
}
static void visit_layout(XmlWriter w, IMessage imsg)
{
w.WriteStartElement("lay", "StrategyLayout", layout_ns);
w.WriteStartElement("lay", "StrategyPanel", layout_ns);
w.WriteAttributeString("orientation", "HORIZONTAL");
int msgcount = 0;
Dictionary<int, int> tags = new Dictionary<int, int>();
Dictionary<string, int> names = new Dictionary<string, int>();
Type mtype = null;
message_visitor(imsg, (m, fd, parent_fd) =>
{
try
{
if (!get_tag_and_name(m, fd, parent_fd, tags, names, out int tag, out string fieldname))
return;
if ( _algo_types.ContainsKey( m.GetType() ) && (mtype == null || m.GetType() != mtype))
{
if(msgcount > 0)
{
w.WriteEndElement();
msgcount--;
}
w.WriteStartElement("lay", "StrategyPanel", layout_ns);
w.WriteAttributeString("orientation", "VERTICAL");
msgcount++;
mtype = m.GetType();
}
w.WriteStartElement("lay", "Control", layout_ns);
w.WriteAttributeString("ID", fieldname + "_ID");
var label = title_case(fieldname);
w.WriteAttributeString("label", label);
w.WriteAttributeString("parameterRef", fieldname);
if (fd.FieldType == FieldType.Message && fd.MessageType.ClrType == typeof(Google.Protobuf.WellKnownTypes.Timestamp))
{
w.WriteAttributeString("xsi", "type", null, "lay:Clock_t");
w.WriteAttributeString("localMktTz", "America/New_York");
}
else if (fd.FieldType == FieldType.Message && fd.MessageType.ClrType == typeof(bts.spark.QuantityMeasure))
{
w.WriteAttributeString("xsi", "type", null, "lay:SingleSpinner_t");
w.WriteAttributeString("initValue", "0");
}
else if (fd.FieldType == FieldType.Enum)
{
w.WriteAttributeString("xsi", "type", null, "lay:DropDownList_t");
w.WriteAttributeString("initValue", fd.EnumType.Values.First().Name);
foreach (var val in fd.EnumType.Values)
{
string eval = null;
if (val.CustomOptions?.TryGetString((int)bts.api.ApioptionsReflection.EnumValueOptions.fix_value, out eval) ?? false)
{
w.WriteStartElement("lay", "ListItem", layout_ns);
w.WriteAttributeString("enumID", val.Name);
w.WriteAttributeString("uiRep", val.Name);
w.WriteEndElement();
}
}
}
else if (fd.FieldType == FieldType.Int32)
{
w.WriteAttributeString("xsi", "type", null, "lay:SingleSpinner_t");
w.WriteAttributeString("initValue", "0");
}
else if (fd.FieldType == FieldType.Double || fd.FieldType == FieldType.Float)
{
if(m.Descriptor.ClrType == typeof(IcebergOrderDefinition))
w.WriteAttributeString("xsi", "type", null, "lay:SingleSpinner_t");
else
w.WriteAttributeString("xsi", "type", null, "lay:DoubleSpinner_t");
w.WriteAttributeString("initValue", "0");
}
else if (fd.FieldType == FieldType.UInt32)
{
w.WriteAttributeString("xsi", "type", null, "lay:SingleSpinner_t");
w.WriteAttributeString("initValue", "0");
}
else if (fd.FieldType == FieldType.Bool)
{
w.WriteAttributeString("xsi", "type", null, "lay:CheckBox_t");
w.WriteAttributeString("initValue", "false");
}
else
{
w.WriteAttributeString("xsi", "type", null, "lay:TextField_t");
}
w.WriteEndElement();
}
catch (QuickFix.FieldNotFoundException) { }
});
for(int i = 0; i < msgcount; i++)
w.WriteEndElement();
w.WriteEndElement();
w.WriteEndElement();
}
public static void write_json(FIXAlgoDefinitions defs, string path)
{
using (var fs = new StreamWriter(path))
{
var s = JsonFormatter.Settings.Default;
var raw = JsonFormatter.Default.Format(defs);
object parsed = Newtonsoft.Json.JsonConvert.DeserializeObject(raw);
string indented = Newtonsoft.Json.JsonConvert.SerializeObject(parsed, Newtonsoft.Json.Formatting.Indented);
fs.Write(indented);
}
}
public static IMessage message_visitor(IMessage msg, Action<IMessage, FieldDescriptor, FieldDescriptor> visitor, FieldDescriptor parent = null)
{
var memb = msg.Descriptor.Fields.InDeclarationOrder().ToList();
memb = memb.OrderBy(x => (int)x.FieldType).ToList();
List<FieldDescriptor> subs = new List<FieldDescriptor>();
foreach (var fd in memb)
{
if (fd.FieldType == FieldType.Message)
subs.Add(fd);
visitor(msg, fd, parent);
}
foreach(var fd in subs)
{
bool custom = msg.Descriptor.ClrType == typeof(bts.api.orderman.CustomOrderDefinition);
var submsg = fd.Accessor.GetValue(msg);
if (submsg != null)
message_visitor((IMessage)submsg, visitor, custom ? parent : fd);
}
return msg;
}
public static IMessage extract_order_from_custom(CustomOrderDefinition custom)
{
foreach (var fd in CustomOrderDefinition.Descriptor.Fields.InDeclarationOrder())
{
var val = fd.Accessor.GetValue(custom);
if (val != null && val is IMessage valmsg)
return valmsg;
}
Log.assert(false, "can't find non-null member of CustomOrderDefintion");
return null;
}
#region write sample file
public static void write_sample_json(string path = "./spark_algos.json")
{
FIXAlgoDefinition tc = new FIXAlgoDefinition()
{
Name = "TickAndCover",
Definition = new CustomOrderDefinition
{
Cover = new CoverOrderDefinition
{
Child = new CustomOrderDefinition
{
Top = new TopOrderDefinition { Child = new CustomOrderDefinition { Limit = new LimitOrderDefinition() } }
},
Hedge = new CustomOrderDefinition
{
Lean = new LeanOrderDefinition { Child = new CustomOrderDefinition { Limit = new LimitOrderDefinition() } }
}
}
}
};
FIXAlgoDefinition sc = new FIXAlgoDefinition()
{
Name = "SmashAndCover",
Definition = new CustomOrderDefinition
{
Cover = new CoverOrderDefinition
{
Child = new CustomOrderDefinition
{
Lean = new LeanOrderDefinition{ Child = new CustomOrderDefinition { Limit = new LimitOrderDefinition() } }
},
Hedge = new CustomOrderDefinition
{
Lean = new LeanOrderDefinition { Child = new CustomOrderDefinition { Limit = new LimitOrderDefinition() } }
}
}
}
};
FIXAlgoDefinitions defs = new FIXAlgoDefinitions();
defs.AlgoStrategy.Add(tc);
defs.AlgoStrategy.Add(sc);
write_json(defs, path);
}
}
#endregion
}
@@ -0,0 +1 @@
(C) 2010 FIX Protocol Limited. All use of the FIXatdl Schema is subject to the disclaimer which is printed on one of the initial pages of the written specification for the FIXatdl Schema and is included in the zip file which you downloaded to obtain the Schema.
@@ -0,0 +1,219 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- - - - - - - - - - - - - - - - - - - - - - - - - -
FIXatdl Sample document instance for FIXatdl Schema Version 1.1
(C) 2010 FIX Protocol Limited. All use of the FIXatdl Schema is subject to
the disclaimer which is printed on one of the initial pages of the written specification
for the FIXatdl Schema and is included in the zip file which you downloaded to
obtain the Schema.
Comments and errors should be posted on the FIX protocol web-site
http://www.fixprotocol.org
- - - - - - - - - - - - - - - - - - - - - - - - - -
-->
<Strategies xmlns="http://www.fixprotocol.org/FIXatdl-1-1/Core" xmlns:val="http://www.fixprotocol.org/FIXatdl-1-1/Validation" xmlns:lay="http://www.fixprotocol.org/FIXatdl-1-1/Layout" xmlns:flow="http://www.fixprotocol.org/FIXatdl-1-1/Flow" xmlns:tz="http://www.fixprotocol.org/FIXatdl-1-1/Timezones" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.fixprotocol.org/FIXatdl-1-1/Core fixatdl-core-1-1.xsd" strategyIdentifierTag="7620" versionIdentifierTag="7621">
<!-- ************************ -->
<!-- ******* Tazer 1 ******** -->
<!-- ************************ -->
<Strategy name="Tazer1" uiRep="Tazer" wireValue="Tazer" version="1" fixMsgType="D" providerID="ABC">
<!-- US only -->
<Regions>
<Region name="TheAmericas" inclusion="Include">
<Country CountryCode="US" inclusion="Include"/>
</Region>
</Regions>
<!-- Nasdaq only -->
<Markets>
<Market MICCode="XNAS" inclusion="Include"/>
</Markets>
<!-- Equities ("CS") only -->
<SecurityTypes>
<SecurityType name="CS" inclusion="Include"/>
</SecurityTypes>
<!-- Parameter Section -->
<Parameter name="StartTime" xsi:type="UTCTimestamp_t" fixTag="7602" use="required">
<Description>Strategy Start Time</Description>
</Parameter>
<Parameter name="EndTime" xsi:type="UTCTimestamp_t" fixTag="7603" use="required" maxValue="16:00:00" localMktTz="America/New_York">
<Description>Strategy End Time</Description>
</Parameter>
<Parameter name="Text" xsi:type="String_t" fixTag="9999" use="optional"/>
<Parameter name="SweepDistribution" xsi:type="Char_t" fixTag="7640" use="required">
<EnumPair enumID="e_Uniform" wireValue="U">
<Description>The 'Uniform' setting for Sweep Distribution</Description>
</EnumPair>
<EnumPair enumID="e_Gaussian" wireValue="G">
<Description>The 'Gaussian' setting for Sweep Distribution</Description>
</EnumPair>
</Parameter>
<Parameter name="Variance" xsi:type="Float_t" fixTag="7641" use="optional" minValue="0.01" maxValue="0.50"/>
<Parameter name="DisplayQty" xsi:type="Int_t" fixTag="7645" use="optional" minValue="0"/>
<!-- Layout Section -->
<lay:StrategyLayout>
<lay:StrategyPanel orientation="VERTICAL" collapsible="false">
<lay:StrategyPanel orientation="HORIZONTAL" collapsible="false">
<lay:Control xsi:type="lay:Clock_t" ID="StartTimeClock" label="Start Time" parameterRef="StartTime" initValue="09:30:00" initValueMode="1" localMktTz="America/New_York"/>
<lay:Control xsi:type="lay:Clock_t" ID="EndTimeClock" label="End Time" parameterRef="EndTime" initValue="16:00:00" localMktTz="America/New_York"/>
<lay:Control ID="m_dq" xsi:type="lay:DropDownList_t" label="Display Qty Handling">
<lay:ListItem enumID="choice1" uiRep="Send nothing"/>
<lay:ListItem enumID="choice2" uiRep="Send 0"/>
<lay:ListItem enumID="choice3" uiRep="Send what user enters"/>
</lay:Control>
<lay:Control xsi:type="lay:TextField_t" ID="DisplayQuantity" label="Display Quantity" parameterRef="DisplayQty">
<!-- for "choice1" Control is still displayed however it appears disabled and is set to a null value (will not be transmitted over the wire) -->
<!-- for "choice2" Control is set to value "0" and is disabled (read-only) but will be transmitted over the wire -->
<flow:StateRule enabled="false">
<val:Edit logicOperator="OR">
<val:Edit field="m_dq" operator="EQ" value="choice1"/>
<val:Edit field="m_dq" operator="EQ" value="choice2"/>
</val:Edit>
</flow:StateRule>
<flow:StateRule visible="false">
<val:Edit field="m_dq" operator="EQ" value="choice1"/>
</flow:StateRule>
<flow:StateRule value="{NULL}">
<val:Edit field="m_dq" operator="EQ" value="choice1"/>
</flow:StateRule>
<flow:StateRule value="0">
<Description>Display Quantity should be set to 0 if Display Qty Handling is set to 'choice2'</Description>
<val:Edit field="m_dq" operator="EQ" value="choice2"/>
</flow:StateRule>
</lay:Control>
</lay:StrategyPanel>
<lay:StrategyPanel orientation="HORIZONTAL" collapsible="false">
<lay:Control ID="m_sd" xsi:type="lay:DropDownList_t" label="Sweep Distribution" parameterRef="SweepDistribution" initValue="e_Uniform">
<lay:ListItem enumID="e_Uniform" uiRep="Uniform"/>
<lay:ListItem enumID="e_Gaussian" uiRep="Gaussian"/>
</lay:Control>
<lay:Control xsi:type="lay:TextField_t" ID="Variance" label="Variance" parameterRef="Variance">
<!-- Control is still displayed however it appears disabled and is set to a null value (will not be transmitted over the wire) -->
<flow:StateRule enabled="false" value="{NULL}">
<val:Edit field="m_sd" operator="EQ" value="e_Uniform"/>
</flow:StateRule>
</lay:Control>
</lay:StrategyPanel>
</lay:StrategyPanel>
</lay:StrategyLayout>
<!-- Validation Section -->
<val:StrategyEdit errorMessage="End Time should be later than Start Time">
<val:Edit field="EndTime" operator="GT" field2="StartTime"/>
</val:StrategyEdit>
<val:StrategyEdit errorMessage="Variance is required when Sweep Distribution is Gaussian.">
<val:Edit logicOperator="OR">
<val:Edit field="SweepDistribution" operator="NE" value="G"/>
<val:Edit logicOperator="AND">
<val:Edit field="SweepDistribution" operator="EQ" value="G"/>
<val:Edit field="Variance" operator="EX"/>
</val:Edit>
</val:Edit>
</val:StrategyEdit>
<val:StrategyEdit errorMessage="Variance must be between 0 and 2.0">
<val:Edit logicOperator="OR">
<val:Edit field="SweepDistribution" operator="NE" value="G"/>
<val:Edit logicOperator="AND">
<val:Edit field="SweepDistribution" operator="EQ" value="G"/>
<val:Edit field="Variance" operator="EX"/>
<val:Edit field="Variance" operator="GT" value="0.0"/>
<val:Edit field="Variance" operator="LT" value="2.0"/>
</val:Edit>
</val:Edit>
</val:StrategyEdit>
</Strategy>
<Strategy name="OPLX" uiRep="Get Done" wireValue="60" version="2.0" fixMsgType="D">
<!-- Americas region only -->
<Regions>
<Region name="TheAmericas" inclusion="Include"/>
</Regions>
<!-- Security types other than Futures ("FUT") -->
<SecurityTypes>
<SecurityType name="FUT" inclusion="Exclude"/>
</SecurityTypes>
<Parameter name="StartTime" xsi:type="UTCTimestamp_t" fixTag="6168" use="optional"/>
<Parameter name="EndTime" xsi:type="UTCTimestamp_t" fixTag="126" use="optional"/>
<Parameter name="AgencyOnly" xsi:type="Int_t" fixTag="81" use="required">
<EnumPair wireValue="1" enumID="Yes"/>
<EnumPair wireValue="0" enumID="No"/>
</Parameter>
<Parameter name="Aggression" xsi:type="Char_t" fixTag="6408" use="optional">
<EnumPair enumID="e_Low" wireValue="L"/>
<EnumPair enumID="e_Medium" wireValue="S"/>
<EnumPair enumID="e_High" wireValue="H"/>
</Parameter>
<Parameter name="DisplaySize" xsi:type="Qty_t" fixTag="111" use="optional" minValue="0"/>
<lay:StrategyLayout>
<lay:StrategyPanel collapsible="false" orientation="HORIZONTAL">
<lay:StrategyPanel collapsible="false" orientation="VERTICAL">
<lay:Control ID="Aggression" xsi:type="lay:DropDownList_t" label="Aggression" initValue="e_Medium" parameterRef="Aggression">
<lay:ListItem enumID="e_Low" uiRep="Low"/>
<lay:ListItem enumID="e_Medium" uiRep="Medium"/>
<lay:ListItem enumID="e_High" uiRep="High"/>
</lay:Control>
<!-- Posting is a 'helper control' and not associated with a specific Parameter -->
<lay:Control ID="Posting" xsi:type="lay:DropDownList_t" label="Posting/Iceberg" initValue="e_SMART">
<lay:ListItem enumID="e_SMART" uiRep="SMART"/>
<lay:ListItem enumID="e_NOPOST" uiRep="NOPOST"/>
<lay:ListItem enumID="e_Custom" uiRep="Custom"/>
</lay:Control>
<lay:Control ID="DisplaySize" xsi:type="lay:SingleSpinner_t" label="Display Size" incrementPolicy="LotSize" parameterRef="DisplaySize">
<!-- e_SMART will be null (do not transmit over wire) and not visible nor enabled -->
<!-- e_NOPOST will be set to 0, visible, and disabled (read-only) - (non-null thus transmitted over the wire) -->
<!-- e_Custom will be non-null, visible, and enabled -->
<flow:StateRule visible="true">
<val:Edit logicOperator="OR">
<val:Edit field="Posting" operator="EQ" value="e_Custom"/>
<val:Edit field="Posting" operator="EQ" value="e_NOPOST"/>
</val:Edit>
</flow:StateRule>
<flow:StateRule enabled="true">
<val:Edit field="Posting" operator="EQ" value="e_Custom"/>
</flow:StateRule>
<flow:StateRule value="{NULL}">
<val:Edit field="Posting" operator="EQ" value="e_SMART"/>
</flow:StateRule>
<flow:StateRule value="0">
<val:Edit field="Posting" operator="EQ" value="e_NOPOST"/>
</flow:StateRule>
</lay:Control>
</lay:StrategyPanel>
<lay:StrategyPanel collapsible="false" orientation="VERTICAL">
<!-- StartTime and EndTime need a 'helper control' to support the fact that it is optional (also had to warp AgencyOnly with StrategyPanel as a given StrategyPanel can include only Control or StrategyPanel elements, but not both) -->
<lay:StrategyPanel collapsible="false" orientation="HORIZONTAL">
<lay:Control ID="c_EnableStartTime" xsi:type="lay:CheckBox_t" label="Start Time" initValue="false"/>
<lay:Control ID="StartTime" xsi:type="lay:Clock_t" label="" parameterRef="StartTime">
<flow:StateRule enabled="false" value="{NULL}">
<val:Edit field="c_EnableStartTime" operator="EQ" value="false"/>
</flow:StateRule>
</lay:Control>
</lay:StrategyPanel>
<lay:StrategyPanel collapsible="false" orientation="HORIZONTAL">
<lay:Control ID="c_EnableEndTime" xsi:type="lay:CheckBox_t" label="End Time" initValue="false"/>
<lay:Control ID="EndTime" xsi:type="lay:Clock_t" label="" initValue="16:00:00" localMktTz="America/New_York" parameterRef="EndTime">
<flow:StateRule enabled="false" value="{NULL}">
<val:Edit field="c_EnableEndTime" operator="EQ" value="false"/>
</flow:StateRule>
</lay:Control>
</lay:StrategyPanel>
<lay:StrategyPanel collapsible="false" orientation="HORIZONTAL">
<lay:Control ID="AgencyOnly" xsi:type="lay:DropDownList_t" label="Agency Only" initValue="No" parameterRef="AgencyOnly">
<lay:ListItem enumID="Yes" uiRep="Yes"/>
<lay:ListItem enumID="No" uiRep="No"/>
</lay:Control>
</lay:StrategyPanel>
</lay:StrategyPanel>
</lay:StrategyPanel>
</lay:StrategyLayout>
<val:StrategyEdit errorMessage="Start time must be less than end time.">
<!-- Note that "OR" "NX" checks are required as StartTime and EndTime Parameters are marked use="optional" -->
<val:Edit logicOperator="OR">
<val:Edit field="StartTime" operator="NX"/>
<val:Edit field="EndTime" operator="NX"/>
<val:Edit field="EndTime" operator="GT" field2="StartTime"/>
</val:Edit>
</val:StrategyEdit>
<val:StrategyEdit errorMessage="Display Size cannot be greater than Order Qty">
<val:Edit logicOperator="OR">
<val:Edit field="DisplaySize" operator="NX"/>
<val:Edit field="DisplaySize" operator="LE" field2="FIX_OrderQty"/>
</val:Edit>
</val:StrategyEdit>
</Strategy>
</Strategies>
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,105 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- - - - - - - - - - - - - - - - - - - - - - - - - -
FIXatdl Sample document instance for FIXatdl Schema Version 1.1
(C) 2010 FIX Protocol Limited. All use of the FIXatdl Schema is subject to
the disclaimer which is printed on one of the initial pages of the written specification
for the FIXatdl Schema and is included in the zip file which you downloaded to
obtain the Schema.
Comments and errors should be posted on the FIX protocol web-site
http://www.fixprotocol.org
- - - - - - - - - - - - - - - - - - - - - - - - - -
-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:flow="http://www.fixprotocol.org/FIXatdl-1-1/Flow" xmlns:val="http://www.fixprotocol.org/FIXatdl-1-1/Validation" xmlns:core="http://www.fixprotocol.org/FIXatdl-1-1/Core" targetNamespace="http://www.fixprotocol.org/FIXatdl-1-1/Flow" elementFormDefault="qualified" attributeFormDefault="unqualified" version="1.1">
<xs:annotation>
<xs:documentation>
This value is the internal build number of the ATDL Schema
</xs:documentation>
<xs:appinfo>
<BuildInfo buildNumber="2.7.2e20101221"/>
</xs:appinfo>
</xs:annotation>
<xs:import namespace="http://www.fixprotocol.org/FIXatdl-1-1/Validation" schemaLocation="fixatdl-validation-1-1.xsd"/>
<xs:import namespace="http://www.fixprotocol.org/FIXatdl-1-1/Core" schemaLocation="fixatdl-core-1-1.xsd"/>
<!-- Please email any suggestions or revisions to algotech@fixprotocol.org-->
<!-- Please note - Revision history is at the end of this xsd
Flow Sub-Schema
The intent of the flow sub-schema is to provide an easy, platform-neutral way to specify the interaction
of controls defined by the UI sub-schema. StateRules elements define the behavior of the control, while
Edit elements define how the rule should be executed based on how they evaluate.-->
<xs:element name="StateRule" type="flow:StateRule_t"/>
<xs:complexType name="StateRule_t">
<xs:sequence>
<xs:element ref="core:Description" minOccurs="0">
<xs:annotation>
<xs:documentation>Description of the State Rule.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:choice>
<xs:element ref="val:Edit"/>
<xs:element ref="val:EditRef"/>
</xs:choice>
</xs:sequence>
<xs:attribute name="enabled" type="xs:boolean" use="optional">
<xs:annotation>
<xs:documentation>Indicates whether or not to enable the control when the edit expression of the strategyEdit element evaluates to True.
The desired behavior is as follows:
when the StateRule’s edit condition is true and enabled=True then enable the control;
when the edit condition is true and enabled=false then disable the control;
when the edit condition is false and enable=True then disable the control;
when the edit condition is false and enabled=false then enable the control.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="visible" type="xs:boolean" use="optional">
<xs:annotation>
<xs:documentation>Indicates whether or not to show the control when the boolean expression, defined by the Edit element, evaluates to True.
The desired behavior is as follows:
when the StateRule’s edit condition is true and visible=True then display the control;
when the edit condition is true and visible=false then hide the control;
when the edit condition is false and visible=True then hide the control;
when the edit condition is false and enabled=false then display the control.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="value" type="xs:string" use="optional">
<xs:annotation>
<xs:documentation>GUI control's displayed value should be set to this value when edit condition is true. Although the type of this attribute has been listed as string, ultimately the type of this attribute must be compatible with the type of the control.
For example, if the control is numeric, such as a SingleSpinner, then a string containing a numeric value would an appropriate value (e.g. “15”).
If the control contains ListItem elements then allowable values of StateRule/@value is restricted to the enumIDs of the ListItem elements.
A special token, “{NULL}”, may be used for the value of this attribute to indicate that the control should be set to an uninitialized state. Controls that are un-initialized should have no value.
The effect of an un-initialized control is as follows:
When an order is to be generated, the controls which are linked to parameters will have their values retrieved. If there is no retrieved value because the control was un-initialized then the parameter should have no value and its associated FIX tag should be excluded from the message.
This is relevant only for controls that can be in an un-initialized state such as spinners and text fields. Controls such as check boxes and radio buttons are always initialized. (They are either checked or unchecked.)
</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:schema>
<!-- Please email any revisions to the Steward of the Master Model & Mapping artifacts at algotech@fixprotocol.org -->
<!-- Revision History -->
<!-- Date Version Author Comments
Authors - Greg Malatestinic, Rick Labs, Zoltan Feledy, Jim Arlet, Gideon Kaplan, Martin Naughton, Mike McDermott and other members of FPL Algo Trading WG.
-if there is anyone else then please speak up :-)
30jan08 v2.5 by Robert Golan for uris, revision history, and version stamping.
20May08 - <edit> elements max and min occurs is now 1
27May08 - stateGroup and stateRule can now refer to editRef.
30Aug08 - value attribute has been added.
17Sep08 - stateGroup.filed changed to stateGroup.targetParameter.
21Jan09 v2.5.3 by Greg Malatestinic
- removed stateGroup element
23Jan09 v2.5.6 by Martin Naughton and Mike McDermott
- added a description element to stateRule
- added a reference to the Core schema to support the description element reference
16Feb09 v2.5.9 by Mike McDermott
- added a 'flow' alias to the default namespace for consistency
- created a StateRule_t complex type for consistency
27Mar09 v2.6.3 by Mike McDermott
- updated namespaces to conform with FIX standard for xml namespaces
- updated namespaces to conform with *product* version of 1.1
- updated element and type names to conform with FIX standard of upper camel case
22Feb v2.7.2 by Greg Malatestinic
- All xsd files renamed to fixatdl-{sub-schema}-1-1.xsd. Import/@schemaLocation adjusted accordingly.
- Namespaces changed to http://www.fixprotocol.org/FIXatdl-1-1/{sub-schema}
15Dec2010 v2.7.2e by Greg Malatestinic
- Sync'd documentation with specification document.
-->
@@ -0,0 +1,564 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- - - - - - - - - - - - - - - - - - - - - - - - - -
FIXatdl Sample document instance for FIXatdl Schema Version 1.1
(C) 2010 FIX Protocol Limited. All use of the FIXatdl Schema is subject to
the disclaimer which is printed on one of the initial pages of the written specification
for the FIXatdl Schema and is included in the zip file which you downloaded to
obtain the Schema.
Comments and errors should be posted on the FIX protocol web-site
http://www.fixprotocol.org
- - - - - - - - - - - - - - - - - - - - - - - - - -
-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:lay="http://www.fixprotocol.org/FIXatdl-1-1/Layout" xmlns:flow="http://www.fixprotocol.org/FIXatdl-1-1/Flow" xmlns:core="http://www.fixprotocol.org/FIXatdl-1-1/Core" xmlns:tz="http://www.fixprotocol.org/FIXatdl-1-1/Timezones" targetNamespace="http://www.fixprotocol.org/FIXatdl-1-1/Layout" elementFormDefault="qualified" attributeFormDefault="unqualified" version="1.1">
<xs:annotation>
<xs:documentation>
This value is the internal build number of the ATDL Schema
</xs:documentation>
<xs:appinfo>
<BuildInfo buildNumber="2.7.2e20101221"/>
</xs:appinfo>
</xs:annotation>
<xs:import namespace="http://www.fixprotocol.org/FIXatdl-1-1/Flow" schemaLocation="fixatdl-flow-1-1.xsd"/>
<xs:import namespace="http://www.fixprotocol.org/FIXatdl-1-1/Core" schemaLocation="fixatdl-core-1-1.xsd"/>
<xs:import namespace="http://www.fixprotocol.org/FIXatdl-1-1/Timezones" schemaLocation="fixatdl-timezones-1-1.xsd"/>
<!-- Please email any suggestions or revisions to algotech@fixprotocol.org-->
<!-- Please note - Revision history is at the end of this xsd
User Interface Sub-Schema
The intent of the UI sub-schema is to provide an easy, platform-neutral way to specify the layout of components.
This schema should be flexible enough to support multiple-platforms (i.e. Java Swing, SWT, or Web).-->
<xs:element name="StrategyLayout" type="lay:StrategyLayout_t"/>
<xs:complexType name="StrategyLayout_t">
<xs:sequence>
<xs:element name="StrategyPanel" type="lay:StrategyPanel_t" maxOccurs="unbounded">
<xs:key name="controlKey">
<xs:selector xpath=".//lay:control"/>
<xs:field xpath="@ID"/>
</xs:key>
<xs:unique name="controlParameterRefMustBeUnique">
<xs:selector xpath=".//lay:control"/>
<xs:field xpath="@parameterRef"/>
</xs:unique>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="StrategyPanel_t">
<xs:sequence>
<xs:element name="StrategyPanel" type="lay:StrategyPanel_t" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="Control" type="lay:Control_t" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="title" type="xs:string">
<xs:annotation>
<xs:documentation>Title that appears in the panel border.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="collapsed" type="xs:boolean" default="false">
<xs:annotation>
<xs:documentation>Initial visual state of a panel. Indicates whether a panel is initially drawn in a collapsed state.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="collapsible" type="xs:boolean" default="true">
<xs:annotation>
<xs:documentation>Indicates whether panel can be collapsed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="color" type="xs:string">
<xs:annotation>
<xs:documentation>Set the background color. The value should appear as the RBG combination separated by commas.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="orientation" type="lay:PanelOrientation_t">
<xs:annotation>
<xs:documentation>Must be HORIZONTAL or VERTICAL. Declares the orientation of the components (parameters or nested strategyPanels) within a strategyPanel.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="border" type="lay:Border_t">
<xs:annotation>
<xs:documentation>Recommended border for the panel. Valid values are NONE and LINE.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
<xs:complexType name="Control_t" abstract="true">
<xs:sequence>
<xs:element ref="flow:StateRule" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="HelpText" type="lay:HelpText_t" minOccurs="0">
<xs:annotation>
<xs:documentation> Help text for the parameter </xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
<xs:attribute name="ID" use="required">
<xs:annotation>
<xs:documentation>Unique identifier of this control. No two controls of the same strategy can have the same ID.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:pattern value="[A-Za-z][A-za-z0-9_]{0,255}"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="parameterRef" use="optional">
<xs:annotation>
<xs:documentation>The name of the parameter for which this control gives the visual representation. A parameter with this name must be defined within the same strategy as this control.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:pattern value="[A-Za-z][A-za-z0-9_]{0,255}"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="label" type="xs:string">
<xs:annotation>
<xs:documentation>A title for this control which may be displayed. If the control is a Label_t then Control/@label or Control/@initValue must be used to define the string which is to be rendered. If both attributes are provided then Control/@initValue takes precedence.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="initFixField" type="xs:string">
<xs:annotation>
<xs:documentation>Indicates the initialization value is to be taken from this standard FIX field. Format: "FIX_" + FIXFieldName. Eg. "FIX_OrderQty". Required when initPolicy=”UseFixField”.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="initPolicy">
<xs:annotation>
<xs:documentation>Describes how to initialize the control. If the value of this attribute is undefined or equal to "UseValue" and initValue is defined then initialize with initValue.
If the value is equal to "UseFixField" then attempt to initialize with the value of the tag specified in initFixField. If the value is equal to "UseFixField" and it is not possible to access the value of the specified fix tag then revert to using initValue. If the value is equal to "UseFixField", the field is not accessible, and initValue is not defined, then do not initialize.
Valid values are: UseValue and UseFixField.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="UseValue"/>
<xs:enumeration value="UseFixField"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="tooltip" type="xs:string">
<xs:annotation>
<xs:documentation>Tool tip text for rendered GUI objects rendered for the parameter.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="disableForTemplate" type="xs:boolean" use="optional">
<xs:annotation>
<xs:documentation>For implementing systems that support saving order templates or pre-populated orders for basket trading/list trading this attribute specifies that the control should be disabled when the order screen is going to be saved as a template and not actually used to place an order.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
<xs:complexType name="Clock_t">
<xs:complexContent>
<xs:extension base="lay:Control_t">
<xs:attribute name="initValue" type="xs:time">
<xs:annotation>
<xs:documentation>The value used to pre-populate the GUI component when the order entry screen is initially rendered. Expressed in local market time of the order recipient system.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="initValueMode" default="0">
<xs:simpleType>
<xs:annotation>
<xs:documentation>Defines the treatment of initValue time. 0: use initValue; 1: use current time if initValue time has past.</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:int">
<xs:enumeration value="0"/>
<xs:enumeration value="1"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="localMktTz" type="tz:LocalMktTz_t">
<xs:annotation>
<xs:documentation>The timezone in which initValue is represented in. Required when initValue is supplied.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="TextField_t">
<xs:complexContent>
<xs:extension base="lay:Control_t">
<xs:attribute name="initValue" type="xs:string">
<xs:annotation>
<xs:documentation>The value used to pre-populate the GUI component when the order entry screen is initially rendered.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="SingleSelectList_t">
<xs:complexContent>
<xs:extension base="lay:Control_t">
<xs:sequence>
<xs:element name="ListItem" type="lay:ListItem_t" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="initValue" type="xs:string">
<xs:annotation>
<xs:documentation>The value used to pre-populate the GUI component when the order entry screen is initially rendered. Refers to an item in the list. Must be an enumID value from one of the listItems.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="MultiSelectList_t">
<xs:complexContent>
<xs:extension base="lay:Control_t">
<xs:sequence>
<xs:element name="ListItem" type="lay:ListItem_t" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="initValue" type="xs:string">
<xs:annotation>
<xs:documentation>The value used to pre-populate the GUI component when the order entry screen is initially rendered.
Refers to items in the list. Must be one or more enumID values from the listItems.
For multiple items use a space delimiter.
</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="Slider_t">
<xs:complexContent>
<xs:extension base="lay:Control_t">
<xs:sequence>
<xs:element name="ListItem" type="lay:ListItem_t" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="initValue" type="xs:string">
<xs:annotation>
<xs:documentation>The value used to pre-populate the GUI component when the order entry screen is initially rendered. Refers to an item in the list. Must be an enumID value from one of the listItems.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="CheckBox_t">
<xs:complexContent>
<xs:extension base="lay:Control_t">
<xs:attribute name="initValue" type="xs:boolean">
<xs:annotation>
<xs:documentation>The value used to pre-populate the GUI component when the order entry screen is initially rendered. True indicates the checkbox should be checked. False iundicates it should be unchecked. For rule evaluation, checked=true and unchecked=false.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="checkedEnumRef" type="xs:string">
<xs:annotation>
<xs:documentation>Refers to an enumID defined in the definition of the Parameter referred by Control/@parameterRef. This enumID is the output from this control if it is checked/selected.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="uncheckedEnumRef" type="xs:string">
<xs:annotation>
<xs:documentation>Refers to an enumID defined in the definition of the Parameter referred by Control/@parameterRef. This enumID is the output from this control if it is unchecked/unselected.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="CheckBoxList_t">
<xs:complexContent>
<xs:extension base="lay:Control_t">
<xs:sequence>
<xs:element name="ListItem" type="lay:ListItem_t" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="initValue" type="core:MultipleStringValue">
<xs:annotation>
<xs:documentation>The value used to pre-populate the GUI component when the order entry screen is initially rendered. Refers to enumIDs of child ListItems. If a ListItem's enumID is included then the associated checkbox should be checked when initially rendered. If it is not included then the checkbox should be unchecked when initially rendered.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="orientation" type="lay:PanelOrientation_t">
<xs:annotation>
<xs:documentation>Must be HORIZONTAL or VERTICAL. Declares the orientation of the radio buttons within a RadioButtonList or the checkboxes within a CheckBoxList.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="SingleSpinner_t">
<xs:complexContent>
<xs:extension base="lay:Control_t">
<xs:attribute name="initValue" type="xs:double">
<xs:annotation>
<xs:documentation>The value used to pre-populate the GUI component when the order entry screen is initially rendered.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="increment" type="xs:double" use="optional">
<xs:annotation>
<xs:documentation>Limits the granularity of a spinner control. Useful in spinner objects to enforce odd-lot and sub-penny restrictions.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="incrementPolicy" use="optional">
<xs:simpleType>
<xs:annotation>
<xs:documentation>
Describes how to use increment. If undefined then take value from increment
attribute, if LotSize use value based on symbol lot size. (If lot size is not available use value of
increment attribute.) If Tick use value based on symbol tick size. (If tick size is not available
use value of increment attribute.) If increment is to be used and is not defined then use a system
default value.
</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:enumeration value="Tick"/>
<xs:enumeration value="LotSize"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="DoubleSpinner_t">
<xs:complexContent>
<xs:extension base="lay:Control_t">
<xs:attribute name="initValue" type="xs:double">
<xs:annotation>
<xs:documentation>The value used to pre-populate the GUI component when the order entry screen is initially rendered.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="innerIncrement" type="xs:double" use="optional">
<xs:annotation>
<xs:documentation>Limits the granularity of the inner spinner of a double spinner control. Useful in spinner objects to enforce odd-lot and sub-penny restrictions.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="innerIncrementPolicy" use="optional">
<xs:simpleType>
<xs:annotation>
<xs:documentation>
Describes how to use innerIncrement. If undefined then take value from innerIncrement
attribute, if LotSize use value based on symbol lot size. (If lot size is not available use value of
innerIncrement attribute.) If Tick use value based on symbol tick size. (If tick size is not available
use value of innerIncrement attribute.) If innerIncrement is to be used and is not defined then use a system
default value.
</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:enumeration value="Tick"/>
<xs:enumeration value="LotSize"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="outerIncrement" type="xs:double" use="optional">
<xs:annotation>
<xs:documentation>Limits the granularity of the outer spinner of a double spinner control. Useful in spinner objects to enforce odd-lot and sub-penny restrictions.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="outerIncrementPolicy" use="optional">
<xs:simpleType>
<xs:annotation>
<xs:documentation>
Describes how to use outerIncrement. If undefined then take value from outerIncrement
attribute, if LotSize use value based on symbol lot size. (If lot size is not available use value of
outerIncrement attribute.) If Tick use value based on symbol tick size. (If tick size is not available
use value of outerIncrement attribute.) If outerIncrement is to be used and is not defined then use a system
default value.
</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:enumeration value="Tick"/>
<xs:enumeration value="LotSize"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="DropDownList_t">
<xs:complexContent>
<xs:extension base="lay:Control_t">
<xs:sequence>
<xs:element name="ListItem" type="lay:ListItem_t" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="initValue" type="xs:string">
<xs:annotation>
<xs:documentation>The value used to pre-populate the GUI component when the order entry screen is initially rendered. Refers to an item in the list. Must be an enumID value from one of the listItems.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="EditableDropDownList_t">
<xs:complexContent>
<xs:extension base="lay:Control_t">
<xs:sequence>
<xs:element name="ListItem" type="lay:ListItem_t" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="initValue" type="xs:string">
<xs:annotation>
<xs:documentation>The value used to pre-populate the GUI component when the order entry screen is initially rendered. Refers to an item in the list. Must be an enumID value from one of the listItems.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="RadioButton_t">
<xs:complexContent>
<xs:extension base="lay:Control_t">
<xs:attribute name="radioGroup" type="xs:string">
<xs:annotation>
<xs:documentation>Indicates a group of radio buttons, among which only one radio button may be selected at a time.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="initValue" type="xs:boolean">
<xs:annotation>
<xs:documentation>The value used to pre-populate the GUI component when the order entry screen is initially rendered. True indicates the radio button should initially be checked. False indicates it should be unchecked. For rule evaluation, checked=true and unchecked=false.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="checkedEnumRef" type="xs:string">
<xs:annotation>
<xs:documentation>Refers to an enumID defined in the definition of the Parameter referred by Control/@parameterRef. This enumID is the output from this control if it is checked/selected.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="uncheckedEnumRef" type="xs:string">
<xs:annotation>
<xs:documentation>Refers to an enumID defined in the definition of the Parameter referred by Control/@parameterRef. This enumID is the output from this control if it is unchecked/unselected.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="RadioButtonList_t">
<xs:complexContent>
<xs:extension base="lay:Control_t">
<xs:sequence>
<xs:element name="ListItem" type="lay:ListItem_t" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="initValue" type="xs:string">
<xs:annotation>
<xs:documentation>The value used to pre-populate the GUI component when the order entry screen is initially rendered. Refers to an item in the list. Must be an enumID value from one of the listItems.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="orientation" type="lay:PanelOrientation_t">
<xs:annotation>
<xs:documentation>Must be HORIZONTAL or VERTICAL. Declares the orientation of the radio buttons within a RadioButtonList or the checkboxes within a CheckBoxList.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="Label_t">
<xs:complexContent>
<xs:extension base="lay:Control_t">
<xs:attribute name="initValue" type="xs:string">
<xs:annotation>
<xs:documentation>Use this to set the displayed label. Control/@label or Control/@initValue must be used to define the string which is to be rendered. If both attributes are provided then Control/@initValue takes precedence.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="HiddenField_t">
<xs:complexContent>
<xs:extension base="lay:Control_t">
<xs:attribute name="initValue" type="xs:string"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="ListItem_t">
<xs:sequence>
<xs:element ref="flow:StateRule" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="enumID" use="optional">
<xs:annotation>
<xs:documentation>A reference to the enum specified in the parameter definition. Use is optional when the control does not refer to a parameter.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:pattern value="[A-Za-z][A-za-z0-9_]{0,255}"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="uiRep" type="xs:string">
<xs:annotation>
<xs:documentation>The value shown in the list. These are the values that go into Java or .Net list controls.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
<xs:simpleType name="HelpText_t">
<xs:restriction base="xs:string">
<xs:whiteSpace value="preserve"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="PanelOrientation_t">
<xs:restriction base="xs:string">
<xs:enumeration value="HORIZONTAL"/>
<xs:enumeration value="VERTICAL"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="Border_t">
<xs:restriction base="xs:string">
<xs:enumeration value="None"/>
<xs:enumeration value="Line"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
<!-- Please email any revisions to the Steward of the Master Model & Mapping artifacts at algotech@fixprotocol.org -->
<!-- Revision History -->
<!-- Date Version Author Comments
Authors - Greg Malatestinic, Rick Labs, Zoltan Feledy, Jim Arlet, Gideon Kaplan, Martin Naughton and other members of FPL Algo Trading WG.
-if there is anyone else then please speak up :-)
30jan08 v2.5 by Robert Golan for uris, revision history, and version stamping.
10Mar08 - Reverting to previous version naming. This is now version 2.4.3.
27Aug08 - Control Types have been reviewed and cleaned up.
23Dec08 v2.5.0
- Added Control elements
13Jan09 v2.5.1 by Greg Malatestinic
- Added increment and incrementSource to spinner control
- Added "id" to Control_t - a way to identify a control for use in a stateRule
- Added stateRule to Control_t
- Removed references to core
14Jan09 v2.5.2 by Mike McDermott
- moved 'parameterRef' attribute from each derived control type, to the base control element defintion
- changed 'increment' on Slider type to optional
- added 'tooltip' attribute from core schema to base control type
- changed 'incrementSource' attribute on SingleSpinner_t type to optional
- removed 'Static' as an option for 'incrementSource' on SingleSpinner_t
- added HiddenField_t as a control type
- removed component_t - it was deprecated by the new control type structure
21Jan09 v2.5.3 by Greg Malatestinic
- added increment to NumberSpinner_t and Slider_t and replaced incrementSource with incrementPolicy
- added innerIncrement and outerIncrement to DoubleSpinner_t and also inner/outerIncrementPolicy
- created complex type ListItem
- added ListItem elements to all list-based controls: SingleSelectList_t, MultiSelectList_t, ListBox_t, DropDpwnList_t, EditableDropDownList_t, RadioButtonList_t and MultiSelectListBox_t
- added initFixTag and initPolicy to Control_t
- added initValue (with appropriate type) to all concrete controls.
- added import of cor. Needed for Clock_t.initValue
22Jan09 v2.5.4 by Greg Malatestinic and Mike McDermott
- added helpText to Control_t and moved helpText_t from Core to Layout
28Jan09 v2.5.7 by Greg Malatestinic
- added ListItem element and initValue to HiddenField_t control
- created a new control type, Label_t.
16Feb09 v2.5.9 by Mike McDermott
- set the 'ID' attribute on Control_t to be 'required'
- added a xs:key constaint to the 'ID' attribute on Control_t
- added a 'lay' alias to the default namespace to allow the xs:key constraint to work correctly
- created a StrategyLayout_t complex type for consistency
20Feb09 v2.6.0 by Jim Arlet and Mike McDermott
- readded CheckBoxList_t
26Feb09 v2.6.1 by Mike McDermott
- added abstract="true" to Control_t to enfore the use of xsi:type
- removed ListBox_t and MultiListBox_t because they were determined to be redundant
- renamed RadioButtonList_t to RadioButtonGroup_t
- added a RadioButton_t control
09Mar09 v2.6.2 by Mike McDermott
- added 'disableForTemplate' attribute to the Control_t type
27Mar09 v2.6.3 by Mike McDermott
- updated namespaces to conform with FIX standard for xml namespaces
- updated namespaces to conform with *product* version of 1.1
- updated element and type names to conform with FIX standard of upper camel case
26May09 v2.6.5 by Mike McDermott
- added minOccurs="0" to all listItem references to prevent list items from being
'mandatory' on controls that could have a collection
10Jan10 v2.6.7 by John Shields
- added checkedEnumRef and uncheckedEnumRef attributes to Checkbox_t and RadioButton_t (moved from Boolean_t in Core schema)
- added radioGroup to RadioButton_t
- changed name of RadioButtonGroup_t back to RadioButtonList_t to avoid confusion with radioGroup attribute of RadioButton_t
- added ListItem sequence to Slider_t
- changed type of initValue attribute for Slider_t to xs:string (must be an enumID of one of the ListItems)
- removed increment and incrementPolicy attributes from Slider_t
13Jan10 v2.6.8 by Greg Malatestinic
- changed Clock_t/@initValue from UTCTimestamp to LocalMktTime
- added Clock_t/@localMktTz
- chenged CheckboxList_T/@initVal from type string to type MultipleStringValue
20Jan10 v2.6.9 by Greg Malatestinic
- No Changes
19Feb10 v2.7.1 by Greg Malatestinic
- initFixTag replaced by initFixField
- several border enums were removed. Only None and Line remain.
- added orientation attribute to RadioButtonList_t and CheckBoxList_t
22Feb v2.7.2 by Greg Malatestinic
- All xsd files renamed to fixatdl-{sub-schema}-1-1.xsd. Import/@schemaLocation adjusted accordingly.
- Namespaces changed to http://www.fixprotocol.org/FIXatdl-1-1/{sub-schema}
15Dec2010 v2.7.2e by Greg Malatestinic
- Sync'd documentation with specification document.
-->
@@ -0,0 +1,301 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- - - - - - - - - - - - - - - - - - - - - - - - - -
FIXatdl Sample document instance for FIXatdl Schema Version 1.1
(C) 2010 FIX Protocol Limited. All use of the FIXatdl Schema is subject to
the disclaimer which is printed on one of the initial pages of the written specification
for the FIXatdl Schema and is included in the zip file which you downloaded to
obtain the Schema.
Comments and errors should be posted on the FIX protocol web-site
http://www.fixprotocol.org
- - - - - - - - - - - - - - - - - - - - - - - - - -
-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:rg="http://www.fixprotocol.org/FIXatdl-1-1/Regions" targetNamespace="http://www.fixprotocol.org/FIXatdl-1-1/Regions" elementFormDefault="qualified" attributeFormDefault="unqualified" version="1.1">
<xs:annotation>
<xs:documentation>
This value is the internal build number of the ATDL Schema
</xs:documentation>
<xs:appinfo>
<BuildInfo buildNumber="2.7.2e20101221"/>
</xs:appinfo>
</xs:annotation>
<!-- Please email any suggestions or revisions to algotech@fixprotocol.org-->
<!-- Please note - Revision history is at the end of this xsd
Regions Mapping-->
<xs:element name="TheAmericas">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="AI"/>
<xs:enumeration value="AG"/>
<xs:enumeration value="AR"/>
<xs:enumeration value="AW"/>
<xs:enumeration value="BS"/>
<xs:enumeration value="BB"/>
<xs:enumeration value="BZ"/>
<xs:enumeration value="BM"/>
<xs:enumeration value="BO"/>
<xs:enumeration value="BR"/>
<xs:enumeration value="CA"/>
<xs:enumeration value="KY"/>
<xs:enumeration value="CL"/>
<xs:enumeration value="CO"/>
<xs:enumeration value="CR"/>
<xs:enumeration value="CU"/>
<xs:enumeration value="DM"/>
<xs:enumeration value="DO"/>
<xs:enumeration value="EC"/>
<xs:enumeration value="SV"/>
<xs:enumeration value="FK"/>
<xs:enumeration value="GD"/>
<xs:enumeration value="GP"/>
<xs:enumeration value="GT"/>
<xs:enumeration value="GY"/>
<xs:enumeration value="HT"/>
<xs:enumeration value="HN"/>
<xs:enumeration value="JM"/>
<xs:enumeration value="MQ"/>
<xs:enumeration value="MX"/>
<xs:enumeration value="MS"/>
<xs:enumeration value="AN"/>
<xs:enumeration value="NI"/>
<xs:enumeration value="PA"/>
<xs:enumeration value="PY"/>
<xs:enumeration value="PE"/>
<xs:enumeration value="PR"/>
<xs:enumeration value="BL"/>
<xs:enumeration value="KN"/>
<xs:enumeration value="LC"/>
<xs:enumeration value="MF"/>
<xs:enumeration value="PM"/>
<xs:enumeration value="VC"/>
<xs:enumeration value="TT"/>
<xs:enumeration value="TC"/>
<xs:enumeration value="US"/>
<xs:enumeration value="UY"/>
<xs:enumeration value="VG"/>
<xs:enumeration value="VI"/>
<xs:enumeration value="VE"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="EuropeMiddleEastAfrica">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="AX"/>
<xs:enumeration value="AL"/>
<xs:enumeration value="DZ"/>
<xs:enumeration value="AD"/>
<xs:enumeration value="AO"/>
<xs:enumeration value="AM"/>
<xs:enumeration value="AT"/>
<xs:enumeration value="AZ"/>
<xs:enumeration value="BH"/>
<xs:enumeration value="BY"/>
<xs:enumeration value="BE"/>
<xs:enumeration value="BJ"/>
<xs:enumeration value="BA"/>
<xs:enumeration value="BW"/>
<xs:enumeration value="BG"/>
<xs:enumeration value="BF"/>
<xs:enumeration value="BI"/>
<xs:enumeration value="CM"/>
<xs:enumeration value="CV"/>
<xs:enumeration value="CF"/>
<xs:enumeration value="TD"/>
<xs:enumeration value="KM"/>
<xs:enumeration value="CG"/>
<xs:enumeration value="CD"/>
<xs:enumeration value="CI"/>
<xs:enumeration value="HR"/>
<xs:enumeration value="CY"/>
<xs:enumeration value="CZ"/>
<xs:enumeration value="DK"/>
<xs:enumeration value="DJ"/>
<xs:enumeration value="EG"/>
<xs:enumeration value="GQ"/>
<xs:enumeration value="ER"/>
<xs:enumeration value="EE"/>
<xs:enumeration value="ET"/>
<xs:enumeration value="FO"/>
<xs:enumeration value="FI"/>
<xs:enumeration value="FR"/>
<xs:enumeration value="GF"/>
<xs:enumeration value="GA"/>
<xs:enumeration value="GM"/>
<xs:enumeration value="GE"/>
<xs:enumeration value="DE"/>
<xs:enumeration value="GH"/>
<xs:enumeration value="GI"/>
<xs:enumeration value="GR"/>
<xs:enumeration value="GL"/>
<xs:enumeration value="GG"/>
<xs:enumeration value="GN"/>
<xs:enumeration value="GW"/>
<xs:enumeration value="VA"/>
<xs:enumeration value="HU"/>
<xs:enumeration value="IS"/>
<xs:enumeration value="IR"/>
<xs:enumeration value="IQ"/>
<xs:enumeration value="IE"/>
<xs:enumeration value="IM"/>
<xs:enumeration value="IL"/>
<xs:enumeration value="IT"/>
<xs:enumeration value="JE"/>
<xs:enumeration value="JO"/>
<xs:enumeration value="KE"/>
<xs:enumeration value="KW"/>
<xs:enumeration value="LV"/>
<xs:enumeration value="LB"/>
<xs:enumeration value="LS"/>
<xs:enumeration value="LR"/>
<xs:enumeration value="LY"/>
<xs:enumeration value="LI"/>
<xs:enumeration value="LT"/>
<xs:enumeration value="LU"/>
<xs:enumeration value="MK"/>
<xs:enumeration value="MG"/>
<xs:enumeration value="MW"/>
<xs:enumeration value="ML"/>
<xs:enumeration value="MT"/>
<xs:enumeration value="MR"/>
<xs:enumeration value="MU"/>
<xs:enumeration value="YT"/>
<xs:enumeration value="MD"/>
<xs:enumeration value="MC"/>
<xs:enumeration value="ME"/>
<xs:enumeration value="MA"/>
<xs:enumeration value="MZ"/>
<xs:enumeration value="NA"/>
<xs:enumeration value="NL"/>
<xs:enumeration value="NE"/>
<xs:enumeration value="NG"/>
<xs:enumeration value="NO"/>
<xs:enumeration value="OM"/>
<xs:enumeration value="PS"/>
<xs:enumeration value="PN"/>
<xs:enumeration value="PL"/>
<xs:enumeration value="PT"/>
<xs:enumeration value="QA"/>
<xs:enumeration value="RE"/>
<xs:enumeration value="RO"/>
<xs:enumeration value="RU"/>
<xs:enumeration value="RW"/>
<xs:enumeration value="SH"/>
<xs:enumeration value="SM"/>
<xs:enumeration value="ST"/>
<xs:enumeration value="SA"/>
<xs:enumeration value="SN"/>
<xs:enumeration value="RS"/>
<xs:enumeration value="SC"/>
<xs:enumeration value="SL"/>
<xs:enumeration value="SK"/>
<xs:enumeration value="SI"/>
<xs:enumeration value="SO"/>
<xs:enumeration value="ZA"/>
<xs:enumeration value="GS"/>
<xs:enumeration value="ES"/>
<xs:enumeration value="LK"/>
<xs:enumeration value="SD"/>
<xs:enumeration value="SR"/>
<xs:enumeration value="SJ"/>
<xs:enumeration value="SZ"/>
<xs:enumeration value="SE"/>
<xs:enumeration value="CH"/>
<xs:enumeration value="SY"/>
<xs:enumeration value="EH"/>
<xs:enumeration value="TZ"/>
<xs:enumeration value="TG"/>
<xs:enumeration value="TN"/>
<xs:enumeration value="TR"/>
<xs:enumeration value="UG"/>
<xs:enumeration value="UA"/>
<xs:enumeration value="AE"/>
<xs:enumeration value="GB"/>
<xs:enumeration value="YE"/>
<xs:enumeration value="ZM"/>
<xs:enumeration value="ZW"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="AsiaPacificJapan">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="AF"/>
<xs:enumeration value="AS"/>
<xs:enumeration value="AU"/>
<xs:enumeration value="BD"/>
<xs:enumeration value="BT"/>
<xs:enumeration value="IO"/>
<xs:enumeration value="BN"/>
<xs:enumeration value="KH"/>
<xs:enumeration value="CN"/>
<xs:enumeration value="CX"/>
<xs:enumeration value="CC"/>
<xs:enumeration value="CK"/>
<xs:enumeration value="FJ"/>
<xs:enumeration value="PF"/>
<xs:enumeration value="GU"/>
<xs:enumeration value="HK"/>
<xs:enumeration value="IN"/>
<xs:enumeration value="ID"/>
<xs:enumeration value="JP"/>
<xs:enumeration value="KZ"/>
<xs:enumeration value="KI"/>
<xs:enumeration value="KP"/>
<xs:enumeration value="KR"/>
<xs:enumeration value="KG"/>
<xs:enumeration value="LA"/>
<xs:enumeration value="MO"/>
<xs:enumeration value="MY"/>
<xs:enumeration value="MV"/>
<xs:enumeration value="MH"/>
<xs:enumeration value="FM"/>
<xs:enumeration value="MN"/>
<xs:enumeration value="MM"/>
<xs:enumeration value="NR"/>
<xs:enumeration value="NP"/>
<xs:enumeration value="NC"/>
<xs:enumeration value="NZ"/>
<xs:enumeration value="NU"/>
<xs:enumeration value="NF"/>
<xs:enumeration value="MP"/>
<xs:enumeration value="PK"/>
<xs:enumeration value="PW"/>
<xs:enumeration value="PG"/>
<xs:enumeration value="PH"/>
<xs:enumeration value="WS"/>
<xs:enumeration value="SG"/>
<xs:enumeration value="SB"/>
<xs:enumeration value="TW"/>
<xs:enumeration value="TJ"/>
<xs:enumeration value="TH"/>
<xs:enumeration value="TL"/>
<xs:enumeration value="TK"/>
<xs:enumeration value="TO"/>
<xs:enumeration value="TM"/>
<xs:enumeration value="TV"/>
<xs:enumeration value="UM"/>
<xs:enumeration value="UZ"/>
<xs:enumeration value="VU"/>
<xs:enumeration value="VN"/>
<xs:enumeration value="WF"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:schema>
<!-- Please email any revisions to the Steward of the Master Model & Mapping artifacts at algotech@fixprotocol.org -->
<!-- Revision History -->
<!-- Date Version Author Comments
Authors - Greg Malatestinic, Rick Labs, Zoltan Feledy, Jim Arlet, Gideon Kaplan, Martin Naughton, Mike McDermott and other members of FPL Algo Trading WG.
-if there is anyone else then please speak up :-)
27Mar09 v2.6.3 by Mike McDermott
- updated namespaces to conform with FIX standard for xml namespaces
- updated namespaces to conform with *product* version of 1.1
- updated element and type names to conform with FIX standard of upper camel case
27Jan10 v2.7.1 by Greg Malatestinic
- added namespace declaration, rg, for Regions
22Feb v2.7.2 by Greg Malatestinic
- All xsd files renamed to fixatdl-{sub-schema}-1-1.xsd. Import/@schemaLocation adjusted accordingly.
- Namespaces changed to http://www.fixprotocol.org/FIXatdl-1-1/{sub-schema}
-->
@@ -0,0 +1,444 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- - - - - - - - - - - - - - - - - - - - - - - - - -
FIXatdl Sample document instance for FIXatdl Schema Version 1.1
(C) 2010 FIX Protocol Limited. All use of the FIXatdl Schema is subject to
the disclaimer which is printed on one of the initial pages of the written specification
for the FIXatdl Schema and is included in the zip file which you downloaded to
obtain the Schema.
Comments and errors should be posted on the FIX protocol web-site
http://www.fixprotocol.org
- - - - - - - - - - - - - - - - - - - - - - - - - -
-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tz="http://www.fixprotocol.org/FIXatdl-1-1/Timezones" targetNamespace="http://www.fixprotocol.org/FIXatdl-1-1/Timezones" elementFormDefault="qualified" attributeFormDefault="unqualified" version="1.1">
<xs:annotation>
<xs:documentation>
This value is the internal build number of the ATDL Schema
</xs:documentation>
<xs:appinfo>
<BuildInfo buildNumber="2.7.2e20101221"/>
</xs:appinfo>
</xs:annotation>
<!-- Please email any suggestions or revisions to algotech@fixprotocol.org-->
<!-- Please note - Revision history is at the end of this xsd -->
<xs:simpleType name="LocalMktTz_t">
<xs:restriction base="xs:string">
<xs:enumeration value="Africa/Abidjan"/>
<xs:enumeration value="Africa/Accra"/>
<xs:enumeration value="Africa/Addis_Ababa"/>
<xs:enumeration value="Africa/Algiers"/>
<xs:enumeration value="Africa/Asmara"/>
<xs:enumeration value="Africa/Bamako"/>
<xs:enumeration value="Africa/Bangui"/>
<xs:enumeration value="Africa/Banjul"/>
<xs:enumeration value="Africa/Bissau"/>
<xs:enumeration value="Africa/Blantyre"/>
<xs:enumeration value="Africa/Brazzaville"/>
<xs:enumeration value="Africa/Bujumbura"/>
<xs:enumeration value="Africa/Cairo"/>
<xs:enumeration value="Africa/Casablanca"/>
<xs:enumeration value="Africa/Ceuta"/>
<xs:enumeration value="Africa/Conakry"/>
<xs:enumeration value="Africa/Dakar"/>
<xs:enumeration value="Africa/Dar_es_Salaam"/>
<xs:enumeration value="Africa/Djibouti"/>
<xs:enumeration value="Africa/Douala"/>
<xs:enumeration value="Africa/El_Aaiun"/>
<xs:enumeration value="Africa/Freetown"/>
<xs:enumeration value="Africa/Gaborone"/>
<xs:enumeration value="Africa/Harare"/>
<xs:enumeration value="Africa/Johannesburg"/>
<xs:enumeration value="Africa/Kampala"/>
<xs:enumeration value="Africa/Khartoum"/>
<xs:enumeration value="Africa/Kigali"/>
<xs:enumeration value="Africa/Kinshasa"/>
<xs:enumeration value="Africa/Lagos"/>
<xs:enumeration value="Africa/Libreville"/>
<xs:enumeration value="Africa/Lome"/>
<xs:enumeration value="Africa/Luanda"/>
<xs:enumeration value="Africa/Lubumbashi"/>
<xs:enumeration value="Africa/Lusaka"/>
<xs:enumeration value="Africa/Malabo"/>
<xs:enumeration value="Africa/Maputo"/>
<xs:enumeration value="Africa/Maseru"/>
<xs:enumeration value="Africa/Mbabane"/>
<xs:enumeration value="Africa/Mogadishu"/>
<xs:enumeration value="Africa/Monrovia"/>
<xs:enumeration value="Africa/Nairobi"/>
<xs:enumeration value="Africa/Ndjamena"/>
<xs:enumeration value="Africa/Niamey"/>
<xs:enumeration value="Africa/Nouakchott"/>
<xs:enumeration value="Africa/Ouagadougou"/>
<xs:enumeration value="Africa/Porto-Novo"/>
<xs:enumeration value="Africa/Sao_Tome"/>
<xs:enumeration value="Africa/Tripoli"/>
<xs:enumeration value="Africa/Tunis"/>
<xs:enumeration value="Africa/Windhoek"/>
<xs:enumeration value="America/Adak"/>
<xs:enumeration value="America/Anchorage"/>
<xs:enumeration value="America/Anguilla"/>
<xs:enumeration value="America/Antigua"/>
<xs:enumeration value="America/Araguaina"/>
<xs:enumeration value="America/Argentina/Buenos_Aires"/>
<xs:enumeration value="America/Argentina/Catamarca"/>
<xs:enumeration value="America/Argentina/Cordoba"/>
<xs:enumeration value="America/Argentina/Jujuy"/>
<xs:enumeration value="America/Argentina/La_Rioja"/>
<xs:enumeration value="America/Argentina/Mendoza"/>
<xs:enumeration value="America/Argentina/Rio_Gallegos"/>
<xs:enumeration value="America/Argentina/Salta"/>
<xs:enumeration value="America/Argentina/San_Juan"/>
<xs:enumeration value="America/Argentina/San_Luis"/>
<xs:enumeration value="America/Argentina/Tucuman"/>
<xs:enumeration value="America/Argentina/Ushuaia"/>
<xs:enumeration value="America/Aruba"/>
<xs:enumeration value="America/Asuncion"/>
<xs:enumeration value="America/Atikokan"/>
<xs:enumeration value="America/Bahia"/>
<xs:enumeration value="America/Barbados"/>
<xs:enumeration value="America/Belem"/>
<xs:enumeration value="America/Belize"/>
<xs:enumeration value="America/Blanc-Sablon"/>
<xs:enumeration value="America/Boa_Vista"/>
<xs:enumeration value="America/Bogota"/>
<xs:enumeration value="America/Boise"/>
<xs:enumeration value="America/Cambridge_Bay"/>
<xs:enumeration value="America/Campo_Grande"/>
<xs:enumeration value="America/Cancun"/>
<xs:enumeration value="America/Caracas"/>
<xs:enumeration value="America/Cayenne"/>
<xs:enumeration value="America/Cayman"/>
<xs:enumeration value="America/Chicago"/>
<xs:enumeration value="America/Chihuahua"/>
<xs:enumeration value="America/Costa_Rica"/>
<xs:enumeration value="America/Cuiaba"/>
<xs:enumeration value="America/Curacao"/>
<xs:enumeration value="America/Danmarkshavn"/>
<xs:enumeration value="America/Dawson"/>
<xs:enumeration value="America/Dawson_Creek"/>
<xs:enumeration value="America/Denver"/>
<xs:enumeration value="America/Detroit"/>
<xs:enumeration value="America/Dominica"/>
<xs:enumeration value="America/Edmonton"/>
<xs:enumeration value="America/Eirunepe"/>
<xs:enumeration value="America/El_Salvador"/>
<xs:enumeration value="America/Fortaleza"/>
<xs:enumeration value="America/Glace_Bay"/>
<xs:enumeration value="America/Godthab"/>
<xs:enumeration value="America/Goose_Bay"/>
<xs:enumeration value="America/Grand_Turk"/>
<xs:enumeration value="America/Grenada"/>
<xs:enumeration value="America/Guadeloupe"/>
<xs:enumeration value="America/Guatemala"/>
<xs:enumeration value="America/Guayaquil"/>
<xs:enumeration value="America/Guyana"/>
<xs:enumeration value="America/Halifax"/>
<xs:enumeration value="America/Havana"/>
<xs:enumeration value="America/Hermosillo"/>
<xs:enumeration value="America/Indiana/Indianapolis"/>
<xs:enumeration value="America/Indiana/Knox"/>
<xs:enumeration value="America/Indiana/Marengo"/>
<xs:enumeration value="America/Indiana/Petersburg"/>
<xs:enumeration value="America/Indiana/Tell_City"/>
<xs:enumeration value="America/Indiana/Vevay"/>
<xs:enumeration value="America/Indiana/Vincennes"/>
<xs:enumeration value="America/Indiana/Winamac"/>
<xs:enumeration value="America/Inuvik"/>
<xs:enumeration value="America/Iqaluit"/>
<xs:enumeration value="America/Jamaica"/>
<xs:enumeration value="America/Juneau"/>
<xs:enumeration value="America/Kentucky/Louisville"/>
<xs:enumeration value="America/Kentucky/Monticello"/>
<xs:enumeration value="America/La_Paz"/>
<xs:enumeration value="America/Lima"/>
<xs:enumeration value="America/Los_Angeles"/>
<xs:enumeration value="America/Maceio"/>
<xs:enumeration value="America/Managua"/>
<xs:enumeration value="America/Manaus"/>
<xs:enumeration value="America/Marigot"/>
<xs:enumeration value="America/Martinique"/>
<xs:enumeration value="America/Mazatlan"/>
<xs:enumeration value="America/Menominee"/>
<xs:enumeration value="America/Merida"/>
<xs:enumeration value="America/Mexico_City"/>
<xs:enumeration value="America/Miquelon"/>
<xs:enumeration value="America/Moncton"/>
<xs:enumeration value="America/Monterrey"/>
<xs:enumeration value="America/Montevideo"/>
<xs:enumeration value="America/Montreal"/>
<xs:enumeration value="America/Montserrat"/>
<xs:enumeration value="America/Nassau"/>
<xs:enumeration value="America/New_York"/>
<xs:enumeration value="America/Nipigon"/>
<xs:enumeration value="America/Nome"/>
<xs:enumeration value="America/Noronha"/>
<xs:enumeration value="America/North_Dakota/Center"/>
<xs:enumeration value="America/North_Dakota/New_Salem"/>
<xs:enumeration value="America/Panama"/>
<xs:enumeration value="America/Pangnirtung"/>
<xs:enumeration value="America/Paramaribo"/>
<xs:enumeration value="America/Phoenix"/>
<xs:enumeration value="America/Port-au-Prince"/>
<xs:enumeration value="America/Port_of_Spain"/>
<xs:enumeration value="America/Porto_Velho"/>
<xs:enumeration value="America/Puerto_Rico"/>
<xs:enumeration value="America/Rainy_River"/>
<xs:enumeration value="America/Rankin_Inlet"/>
<xs:enumeration value="America/Recife"/>
<xs:enumeration value="America/Regina"/>
<xs:enumeration value="America/Resolute"/>
<xs:enumeration value="America/Rio_Branco"/>
<xs:enumeration value="America/Santarem"/>
<xs:enumeration value="America/Santiago"/>
<xs:enumeration value="America/Santo_Domingo"/>
<xs:enumeration value="America/Sao_Paulo"/>
<xs:enumeration value="America/Scoresbysund"/>
<xs:enumeration value="America/Shiprock"/>
<xs:enumeration value="America/St_Barthelemy"/>
<xs:enumeration value="America/St_Johns"/>
<xs:enumeration value="America/St_Kitts"/>
<xs:enumeration value="America/St_Lucia"/>
<xs:enumeration value="America/St_Thomas"/>
<xs:enumeration value="America/St_Vincent"/>
<xs:enumeration value="America/Swift_Current"/>
<xs:enumeration value="America/Tegucigalpa"/>
<xs:enumeration value="America/Thule"/>
<xs:enumeration value="America/Thunder_Bay"/>
<xs:enumeration value="America/Tijuana"/>
<xs:enumeration value="America/Toronto"/>
<xs:enumeration value="America/Tortola"/>
<xs:enumeration value="America/Vancouver"/>
<xs:enumeration value="America/Whitehorse"/>
<xs:enumeration value="America/Winnipeg"/>
<xs:enumeration value="America/Yakutat"/>
<xs:enumeration value="America/Yellowknife"/>
<xs:enumeration value="Antarctica/Casey"/>
<xs:enumeration value="Antarctica/Davis"/>
<xs:enumeration value="Antarctica/DumontDUrville"/>
<xs:enumeration value="Antarctica/Mawson"/>
<xs:enumeration value="Antarctica/McMurdo"/>
<xs:enumeration value="Antarctica/Palmer"/>
<xs:enumeration value="Antarctica/Rothera"/>
<xs:enumeration value="Antarctica/South_Pole"/>
<xs:enumeration value="Antarctica/Syowa"/>
<xs:enumeration value="Antarctica/Vostok"/>
<xs:enumeration value="Arctic/Longyearbyen"/>
<xs:enumeration value="Asia/Aden"/>
<xs:enumeration value="Asia/Almaty"/>
<xs:enumeration value="Asia/Amman"/>
<xs:enumeration value="Asia/Anadyr"/>
<xs:enumeration value="Asia/Aqtau"/>
<xs:enumeration value="Asia/Aqtobe"/>
<xs:enumeration value="Asia/Ashgabat"/>
<xs:enumeration value="Asia/Baghdad"/>
<xs:enumeration value="Asia/Bahrain"/>
<xs:enumeration value="Asia/Baku"/>
<xs:enumeration value="Asia/Bangkok"/>
<xs:enumeration value="Asia/Beirut"/>
<xs:enumeration value="Asia/Bishkek"/>
<xs:enumeration value="Asia/Brunei"/>
<xs:enumeration value="Asia/Choibalsan"/>
<xs:enumeration value="Asia/Chongqing"/>
<xs:enumeration value="Asia/Colombo"/>
<xs:enumeration value="Asia/Damascus"/>
<xs:enumeration value="Asia/Dhaka"/>
<xs:enumeration value="Asia/Dili"/>
<xs:enumeration value="Asia/Dubai"/>
<xs:enumeration value="Asia/Dushanbe"/>
<xs:enumeration value="Asia/Gaza"/>
<xs:enumeration value="Asia/Harbin"/>
<xs:enumeration value="Asia/Ho_Chi_Minh"/>
<xs:enumeration value="Asia/Hong_Kong"/>
<xs:enumeration value="Asia/Hovd"/>
<xs:enumeration value="Asia/Irkutsk"/>
<xs:enumeration value="Asia/Jakarta"/>
<xs:enumeration value="Asia/Jayapura"/>
<xs:enumeration value="Asia/Jerusalem"/>
<xs:enumeration value="Asia/Kabul"/>
<xs:enumeration value="Asia/Kamchatka"/>
<xs:enumeration value="Asia/Karachi"/>
<xs:enumeration value="Asia/Kashgar"/>
<xs:enumeration value="Asia/Katmandu"/>
<xs:enumeration value="Asia/Kolkata"/>
<xs:enumeration value="Asia/Krasnoyarsk"/>
<xs:enumeration value="Asia/Kuala_Lumpur"/>
<xs:enumeration value="Asia/Kuching"/>
<xs:enumeration value="Asia/Kuwait"/>
<xs:enumeration value="Asia/Macau"/>
<xs:enumeration value="Asia/Magadan"/>
<xs:enumeration value="Asia/Makassar"/>
<xs:enumeration value="Asia/Manila"/>
<xs:enumeration value="Asia/Muscat"/>
<xs:enumeration value="Asia/Nicosia"/>
<xs:enumeration value="Asia/Novosibirsk"/>
<xs:enumeration value="Asia/Omsk"/>
<xs:enumeration value="Asia/Oral"/>
<xs:enumeration value="Asia/Phnom_Penh"/>
<xs:enumeration value="Asia/Pontianak"/>
<xs:enumeration value="Asia/Pyongyang"/>
<xs:enumeration value="Asia/Qatar"/>
<xs:enumeration value="Asia/Qyzylorda"/>
<xs:enumeration value="Asia/Rangoon"/>
<xs:enumeration value="Asia/Riyadh"/>
<xs:enumeration value="Asia/Sakhalin"/>
<xs:enumeration value="Asia/Samarkand"/>
<xs:enumeration value="Asia/Seoul"/>
<xs:enumeration value="Asia/Shanghai"/>
<xs:enumeration value="Asia/Singapore"/>
<xs:enumeration value="Asia/Taipei"/>
<xs:enumeration value="Asia/Tashkent"/>
<xs:enumeration value="Asia/Tbilisi"/>
<xs:enumeration value="Asia/Tehran"/>
<xs:enumeration value="Asia/Thimphu"/>
<xs:enumeration value="Asia/Tokyo"/>
<xs:enumeration value="Asia/Ulaanbaatar"/>
<xs:enumeration value="Asia/Urumqi"/>
<xs:enumeration value="Asia/Vientiane"/>
<xs:enumeration value="Asia/Vladivostok"/>
<xs:enumeration value="Asia/Yakutsk"/>
<xs:enumeration value="Asia/Yekaterinburg"/>
<xs:enumeration value="Asia/Yerevan"/>
<xs:enumeration value="Atlantic/Azores"/>
<xs:enumeration value="Atlantic/Bermuda"/>
<xs:enumeration value="Atlantic/Canary"/>
<xs:enumeration value="Atlantic/Cape_Verde"/>
<xs:enumeration value="Atlantic/Faroe"/>
<xs:enumeration value="Atlantic/Madeira"/>
<xs:enumeration value="Atlantic/Reykjavik"/>
<xs:enumeration value="Atlantic/South_Georgia"/>
<xs:enumeration value="Atlantic/St_Helena"/>
<xs:enumeration value="Atlantic/Stanley"/>
<xs:enumeration value="Australia/Adelaide"/>
<xs:enumeration value="Australia/Brisbane"/>
<xs:enumeration value="Australia/Broken_Hill"/>
<xs:enumeration value="Australia/Currie"/>
<xs:enumeration value="Australia/Darwin"/>
<xs:enumeration value="Australia/Eucla"/>
<xs:enumeration value="Australia/Hobart"/>
<xs:enumeration value="Australia/Lindeman"/>
<xs:enumeration value="Australia/Lord_Howe"/>
<xs:enumeration value="Australia/Melbourne"/>
<xs:enumeration value="Australia/Perth"/>
<xs:enumeration value="Australia/Sydney"/>
<xs:enumeration value="Europe/Amsterdam"/>
<xs:enumeration value="Europe/Andorra"/>
<xs:enumeration value="Europe/Athens"/>
<xs:enumeration value="Europe/Belgrade"/>
<xs:enumeration value="Europe/Berlin"/>
<xs:enumeration value="Europe/Bratislava"/>
<xs:enumeration value="Europe/Brussels"/>
<xs:enumeration value="Europe/Bucharest"/>
<xs:enumeration value="Europe/Budapest"/>
<xs:enumeration value="Europe/Chisinau"/>
<xs:enumeration value="Europe/Copenhagen"/>
<xs:enumeration value="Europe/Dublin"/>
<xs:enumeration value="Europe/Gibraltar"/>
<xs:enumeration value="Europe/Guernsey"/>
<xs:enumeration value="Europe/Helsinki"/>
<xs:enumeration value="Europe/Isle_of_Man"/>
<xs:enumeration value="Europe/Istanbul"/>
<xs:enumeration value="Europe/Jersey"/>
<xs:enumeration value="Europe/Kaliningrad"/>
<xs:enumeration value="Europe/Kiev"/>
<xs:enumeration value="Europe/Lisbon"/>
<xs:enumeration value="Europe/Ljubljana"/>
<xs:enumeration value="Europe/London"/>
<xs:enumeration value="Europe/Luxembourg"/>
<xs:enumeration value="Europe/Madrid"/>
<xs:enumeration value="Europe/Malta"/>
<xs:enumeration value="Europe/Mariehamn"/>
<xs:enumeration value="Europe/Minsk"/>
<xs:enumeration value="Europe/Monaco"/>
<xs:enumeration value="Europe/Moscow"/>
<xs:enumeration value="Europe/Oslo"/>
<xs:enumeration value="Europe/Paris"/>
<xs:enumeration value="Europe/Podgorica"/>
<xs:enumeration value="Europe/Prague"/>
<xs:enumeration value="Europe/Riga"/>
<xs:enumeration value="Europe/Rome"/>
<xs:enumeration value="Europe/Samara"/>
<xs:enumeration value="Europe/San_Marino"/>
<xs:enumeration value="Europe/Sarajevo"/>
<xs:enumeration value="Europe/Simferopol"/>
<xs:enumeration value="Europe/Skopje"/>
<xs:enumeration value="Europe/Sofia"/>
<xs:enumeration value="Europe/Stockholm"/>
<xs:enumeration value="Europe/Tallinn"/>
<xs:enumeration value="Europe/Tirane"/>
<xs:enumeration value="Europe/Uzhgorod"/>
<xs:enumeration value="Europe/Vaduz"/>
<xs:enumeration value="Europe/Vatican"/>
<xs:enumeration value="Europe/Vienna"/>
<xs:enumeration value="Europe/Vilnius"/>
<xs:enumeration value="Europe/Volgograd"/>
<xs:enumeration value="Europe/Warsaw"/>
<xs:enumeration value="Europe/Zagreb"/>
<xs:enumeration value="Europe/Zaporozhye"/>
<xs:enumeration value="Europe/Zurich"/>
<xs:enumeration value="Indian/Antananarivo"/>
<xs:enumeration value="Indian/Chagos"/>
<xs:enumeration value="Indian/Christmas"/>
<xs:enumeration value="Indian/Cocos"/>
<xs:enumeration value="Indian/Comoro"/>
<xs:enumeration value="Indian/Kerguelen"/>
<xs:enumeration value="Indian/Mahe"/>
<xs:enumeration value="Indian/Maldives"/>
<xs:enumeration value="Indian/Mauritius"/>
<xs:enumeration value="Indian/Mayotte"/>
<xs:enumeration value="Indian/Reunion"/>
<xs:enumeration value="Pacific/Apia"/>
<xs:enumeration value="Pacific/Auckland"/>
<xs:enumeration value="Pacific/Chatham"/>
<xs:enumeration value="Pacific/Easter"/>
<xs:enumeration value="Pacific/Efate"/>
<xs:enumeration value="Pacific/Enderbury"/>
<xs:enumeration value="Pacific/Fakaofo"/>
<xs:enumeration value="Pacific/Fiji"/>
<xs:enumeration value="Pacific/Funafuti"/>
<xs:enumeration value="Pacific/Galapagos"/>
<xs:enumeration value="Pacific/Gambier"/>
<xs:enumeration value="Pacific/Guadalcanal"/>
<xs:enumeration value="Pacific/Guam"/>
<xs:enumeration value="Pacific/Honolulu"/>
<xs:enumeration value="Pacific/Johnston"/>
<xs:enumeration value="Pacific/Kiritimati"/>
<xs:enumeration value="Pacific/Kosrae"/>
<xs:enumeration value="Pacific/Kwajalein"/>
<xs:enumeration value="Pacific/Majuro"/>
<xs:enumeration value="Pacific/Marquesas"/>
<xs:enumeration value="Pacific/Midway"/>
<xs:enumeration value="Pacific/Nauru"/>
<xs:enumeration value="Pacific/Niue"/>
<xs:enumeration value="Pacific/Norfolk"/>
<xs:enumeration value="Pacific/Noumea"/>
<xs:enumeration value="Pacific/Pago_Pago"/>
<xs:enumeration value="Pacific/Palau"/>
<xs:enumeration value="Pacific/Pitcairn"/>
<xs:enumeration value="Pacific/Ponape"/>
<xs:enumeration value="Pacific/Port_Moresby"/>
<xs:enumeration value="Pacific/Rarotonga"/>
<xs:enumeration value="Pacific/Saipan"/>
<xs:enumeration value="Pacific/Tahiti"/>
<xs:enumeration value="Pacific/Tarawa"/>
<xs:enumeration value="Pacific/Tongatapu"/>
<xs:enumeration value="Pacific/Truk"/>
<xs:enumeration value="Pacific/Wake"/>
<xs:enumeration value="Pacific/Wallis"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
<!-- Please email any revisions to the Steward of the Master Model & Mapping artifacts at algotech@fixprotocol.org -->
<!-- Revision History -->
<!-- Date Version Author Comments
Authors - Greg Malatestinic, Rick Labs, Zoltan Feledy, Jim Arlet, Gideon Kaplan, Martin Naughton, Mike McDermott and other members of FPL Algo Trading WG.
-if there is anyone else then please speak up :-)
27Mar09 v2.6.6 by Mike McDermott
- Initial Version
10Jan10 v2.6.7 by John Shields
- removed trailing whitespace from timezone values
27Jan10 by v2.7.1 by Greg Malatestinic
- added xmlns:tz="http://www.fixprotocol.org/ATDL-1-1/Timezones"
22Feb v2.7.2 by Greg Malatestinic
- All xsd files renamed to fixatdl-{sub-schema}-1-1.xsd. Import/@schemaLocation adjusted accordingly.
- Namespaces changed to http://www.fixprotocol.org/FIXatdl-1-1/{sub-schema}
-->
@@ -0,0 +1,165 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- - - - - - - - - - - - - - - - - - - - - - - - - -
FIXatdl Sample document instance for FIXatdl Schema Version 1.1
(C) 2010 FIX Protocol Limited. All use of the FIXatdl Schema is subject to
the disclaimer which is printed on one of the initial pages of the written specification
for the FIXatdl Schema and is included in the zip file which you downloaded to
obtain the Schema.
Comments and errors should be posted on the FIX protocol web-site
http://www.fixprotocol.org
- - - - - - - - - - - - - - - - - - - - - - - - - -
-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:lay="http://www.fixprotocol.org/FIXatdl-1-1/Validation" xmlns:core="http://www.fixprotocol.org/FIXatdl-1-1/Core" targetNamespace="http://www.fixprotocol.org/FIXatdl-1-1/Validation" elementFormDefault="qualified" attributeFormDefault="unqualified" version="1.1">
<xs:annotation>
<xs:documentation>
This value is the internal build number of the ATDL Schema
</xs:documentation>
<xs:appinfo>
<BuildInfo buildNumber="2.7.2e20101221"/>
</xs:appinfo>
</xs:annotation>
<xs:import namespace="http://www.fixprotocol.org/FIXatdl-1-1/Core" schemaLocation="fixatdl-core-1-1.xsd"/>
<!-- Please email any suggestions or revisions to algotech@fixprotocol.org-->
<!-- Please note - Revision history is at the end of this xsd -->
<!--
Validation Sub-Schema
In order to validate the parameter values entered by the user the following sub-schema has been provided.
It enables the creation of complex and conditional validation rules that can be applied to the algorithmic
orders generated by an OMS or EMS. -->
<xs:element name="StrategyEdit" type="lay:StrategyEdit_t"/>
<xs:complexType name="StrategyEdit_t">
<xs:annotation>
<xs:documentation>Specifies a strategy-wide rule consisting of a boolean expression and an error message to be didsplayed when the boolean expression evaluates to False().</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element ref="core:Description" minOccurs="0">
<xs:annotation>
<xs:documentation>Optional description of the Strategy Edit.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:choice>
<xs:element name="Edit" type="lay:Edit_t">
<xs:annotation>
<xs:documentation>Boolean expression evaluated in validation and flow control rules. An Edit element will describe a condition that is either true or false.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="EditRef" type="lay:EditRef_t"/>
</xs:choice>
</xs:sequence>
<xs:attribute name="errorMessage" type="xs:string" use="required">
<xs:annotation>
<xs:documentation>The error message to display when the boolean expression defined by StrategyEdit/Edit evaluates to False.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
<xs:element name="Edit" type="lay:Edit_t"/>
<xs:complexType name="Edit_t">
<xs:annotation>
<xs:documentation>Construct used to build a boolean expression.</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element ref="core:Description" minOccurs="0">
<xs:annotation>
<xs:documentation>Description of the Edit.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="Edit" type="lay:Edit_t" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="EditRef" type="lay:EditRef_t" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="field" type="xs:string" use="optional">
<xs:annotation>
<xs:documentation>Field name for comparison. When the edit is used within a stateRule, this field must refer to the ID of a Control. When the edit is used within a strategyEdit, this field must refer to either the name of a parameter or a standard FIX field name. When referring to a standard FIX tag then the name must be pre-pended with the string “FIX_”, e.g. “FIX_OrderQty”.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="field2" type="xs:string" use="optional">
<xs:annotation>
<xs:documentation>Value used as the second operand. Used in conjunction with Edit/@field and Edit/@operator. Similar definition to Edit/@field except that it is mutually exclusive with Edit/@value.
Required when: Edit/@operator is in {GE, GT, LE, LT, EQ, NE} and Edit/@value is not specified.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="value" type="xs:string" use="optional">
<xs:annotation>
<xs:documentation>Value used as the second operand. Used in conjunction with Edit/@field and Edit/@operator. Represents a string literal value and not a reference.
When Edit is a descendant of a StateRule element, Edit/@value refers to the value of the control referred by Edit/@field. If the control referred by Edit/@field has enumerated values then Edit/@value refers to the enumID of one of the control’s ListItem elements.
When Edit is a descendant of a StrategyEdit element, Edit/@value refers to the wireValue of the parameter referred by Edit/@field.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="operator" type="lay:operator_t" use="optional">
<xs:annotation>
<xs:documentation>One of the following enumerated types: EX (Exists or supplied by user), NX (Does not exist or was not supplied), EQ (Equal), LT (Less than), GT (Greater than), NE (Not equal), LE (Less than equal), GE (Greater than equal). Required when logicOperator is not present. An edit element must contain either a logicOperator attribute or an operator attribute, but never both.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="logicOperator" type="lay:logicOperator_t" use="optional">
<xs:annotation>
<xs:documentation>Operator where operands are one or more Edit elements. Short-circuit evaluation is assumed in all edit statements. Valid values are one of the enumerations: AND, OR, XOR, NOT. Required when operator is not present. An edit element must contain either a logicOperator attribute or an operator attribute, but never both.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="id" type="xs:string" use="optional">
<xs:annotation>
<xs:documentation>Optional identifier. Allows for re-use of this edit within stateRule or editRef elements. This attribute is required if the Edit element is a direct child of either the Strategies or Strategy elements.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
<xs:element name="EditRef" type="lay:EditRef_t"/>
<xs:complexType name="EditRef_t">
<xs:attribute name="id" type="xs:string" use="required">
<xs:annotation>
<xs:documentation>Refers to an ID of a previously defined edit element. The edit element may be defined at the strategy level or at the strategies level.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
<xs:simpleType name="operator_t">
<xs:restriction base="xs:string">
<xs:enumeration value="EX"/>
<xs:enumeration value="NX"/>
<xs:enumeration value="EQ"/>
<xs:enumeration value="NE"/>
<xs:enumeration value="LE"/>
<xs:enumeration value="LT"/>
<xs:enumeration value="GE"/>
<xs:enumeration value="GT"/>
<!-- exists -->
<!-- not exists -->
<!-- equal -->
<!-- not equal -->
<!-- less than or equal -->
<!-- less than -->
<!-- greater than or equal -->
<!-- greater than -->
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="logicOperator_t">
<xs:restriction base="xs:string">
<xs:enumeration value="AND"/>
<xs:enumeration value="OR"/>
<xs:enumeration value="XOR"/>
<xs:enumeration value="NOT"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
<!-- Please email any revisions to the Steward of the Master Model & Mapping artifacts at algotech@fixprotocol.org -->
<!-- Revision History -->
<!-- Date Version Author Comments
Authors - Greg Malatestinic, Rick Labs, Zoltan Feledy, Jim Arlet, Gideon Kaplan, Martin Naughton, Mike McDermott and other
members of FPL Algo Trading WG. - if there is anyone else then please speak up :-)
30Jan08 v2.5 by Robert Golan for uris, revision history, and version stamping.
14May08 v2.4.9 by Greg Malatestinic
- changes to <edit> to support tree-like expression structure. Added field2 attribute. logicOperator and operator
are mutually exclusive - one is required.
23Jan09 v2.5.6 by Martin Naughton and Mike McDermott
- added a description element to strategyEdit and edit
- added a reference to the Core schema to support the description element reference
16Feb09 v2.5.9 by Mike McDermott
- added a 'val' alias to the default namespace for consistency
- created a StrategyEdit_t complex type to conform with the existing pattern
22Feb v2.7.2 by Greg Malatestinic
- All xsd files renamed to fixatdl-{sub-schema}-1-1.xsd. Import/@schemaLocation adjusted accordingly.
- Namespaces changed to http://www.fixprotocol.org/FIXatdl-1-1/{sub-schema}
15Dec2010 v2.7.2e by Greg Malatestinic
- Sync'd documentation with specification document.
-->
-84
View File
@@ -1,84 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using bts.api.orderman;
namespace bts.fix
{
public class ATDL
{
readonly Dictionary<string, FIXAlgoDefinition> _atdl = new Dictionary<string, FIXAlgoDefinition>();
public IReadOnlyDictionary<string, FIXAlgoDefinition> algo_definitions => _atdl;
public ATDL(string path = "./spark_algos.json")
{
using(var fs = new StreamReader(path))
{
var algos = Google.Protobuf.JsonParser.Default.Parse<FIXAlgoDefinitions>(fs);
foreach(var algo in algos.AlgoStrategy)
{
_atdl[algo.Name] = algo;
}
}
}
public static void write_json(FIXAlgoDefinitions defs, string path)
{
using (var fs = new StreamWriter(path))
{
var s = Google.Protobuf.JsonFormatter.Settings.Default;
var raw = Google.Protobuf.JsonFormatter.Default.Format(defs);
object parsed = Newtonsoft.Json.JsonConvert.DeserializeObject(raw);
string indented = Newtonsoft.Json.JsonConvert.SerializeObject(parsed, Newtonsoft.Json.Formatting.Indented);
fs.Write(indented);
}
}
public static void write_sample_json(string path = "./spark_algos.json")
{
FIXAlgoDefinition tc = new FIXAlgoDefinition()
{
Name = "TickAndCover",
Definition = new CustomOrderDefinition
{
Cover = new CoverOrderDefinition
{
Child = new CustomOrderDefinition
{
Top = new TopOrderDefinition { Child = new CustomOrderDefinition { Limit = new LimitOrderDefinition() } }
},
Hedge = new CustomOrderDefinition
{
Lean = new LeanOrderDefinition { Child = new CustomOrderDefinition { Limit = new LimitOrderDefinition() } }
}
}
}
};
FIXAlgoDefinition sc = new FIXAlgoDefinition()
{
Name = "SmashAndCover",
Definition = new CustomOrderDefinition
{
Cover = new CoverOrderDefinition
{
Child = new CustomOrderDefinition
{
Lean = new LeanOrderDefinition{ Child = new CustomOrderDefinition { Limit = new LimitOrderDefinition() } }
},
Hedge = new CustomOrderDefinition
{
Lean = new LeanOrderDefinition { Child = new CustomOrderDefinition { Limit = new LimitOrderDefinition() } }
}
}
}
};
FIXAlgoDefinitions defs = new FIXAlgoDefinitions();
defs.AlgoStrategy.Add(tc);
defs.AlgoStrategy.Add(sc);
write_json(defs, path);
}
}
}
@@ -31,7 +31,6 @@ namespace bts.fix
protected readonly ConcurrentDictionary<uint, OrderRecordImmutable> _order_cache = new ConcurrentDictionary<uint, OrderRecordImmutable>();
protected readonly ConcurrentDictionary<uint, string> _fix_clorderids = new ConcurrentDictionary<uint, string>();
protected readonly ConcurrentDictionary<string, uint> _external_id_vs_bts_key = new ConcurrentDictionary<string, uint>();
public DropCopySession(IFixRouter router, SessionID sess) : base(router, sess)
{
}
@@ -106,12 +105,7 @@ namespace bts.fix
throw new IncorrectTagValue(QuickFix.Fields.Tags.SecurityRequestType);
}
void _add_order_info_to_caches(OrderRecordImmutable o) {
_order_cache[o.Key] = o;
if (o.HasDef && !string.IsNullOrEmpty(o.Def.ExternalOrderId)) {
_external_id_vs_bts_key[o.Def.ExternalOrderId] = o.Key;
}
}
virtual async protected void subscribe_fills_and_orders(SessionID sessionID)
{
@@ -126,7 +120,7 @@ namespace bts.fix
foreach (var order in o.added)
{
var ostat = build_order_status(sessionID, order);
_add_order_info_to_caches(order);
_order_cache[order.Key] = order;
_router.send(ostat, sessionID);
}
foreach (var order in o.changed)
+18 -31
View File
@@ -27,14 +27,6 @@ delete limit
create algo
8=FIX.4.29=15635=D49=CQG56=SPARK34=150=3073797=N52=20200109-20:20:5011=900010081=ACC A21=255=SIM:ESH0207=SIM54=160=20200809-18:20:3238=1040=244=320059=06401=Lean8401=118402=28405=010=128
jake:
new
8=FIX.4.29=15635=D49=CQG56=SPARK34=150=3073797=N52=20200109-20:20:5011=86753091=ACC A21=255=SIM:ESH0207=SIM54=160=20200809-18:20:3238=1040=244=320059=010=128
cancel-replace
8=FIX.4.29=11035=G49=CQG56=SPARK37=1341=867530911=867531021=155=ESH054=160=20200113-19:45:2938=1040=244=320110=017
cancel
8=FIX.4.29=8935=F49=CQG56=SPARK41=867530937=1311=867531155=ESH054=160=20200113-19:45:2738=1010=123
*/
class OrderSession : DropCopySession
{
@@ -66,23 +58,21 @@ create algo
virtual public void OnMessage(OrderCancelRequest cancel, SessionID s)
{
var original_client_id = cancel.OrigClOrdID.getValue();
if (!base._external_id_vs_bts_key.ContainsKey(original_client_id))
throw new IncorrectTagValue(QuickFix.Fields.Tags.OrigClOrdID);
var key = base._external_id_vs_bts_key[original_client_id];
var id = cancel.OrderID.getValue();
if(!uint.TryParse(id, out uint key))
throw new IncorrectTagValue(QuickFix.Fields.Tags.OrderID);
var resp = _orderservice.Value.cancel_order(new Cancel { OrderKey = key });
if (resp.ErrorCode != OrderError.Ok)
{
send_cancel_reject(s, resp.ErrorCode, "Cancel Rejected: " + resp.ErrorCode.ToString() + " - " + resp.Msg, cancel);
send_cancel_reject(s, "Cancel Rejected: " + resp.ErrorCode.ToString() + " - " + resp.Msg, cancel);
}
}
virtual public void OnMessage(OrderCancelReplaceRequest replace, SessionID s)
{
var original_client_id = replace.OrigClOrdID.getValue();
if (!base._external_id_vs_bts_key.ContainsKey(original_client_id))
throw new IncorrectTagValue(QuickFix.Fields.Tags.OrigClOrdID);
var key = base._external_id_vs_bts_key[original_client_id];
var id = replace.OrderID.getValue();
if (!uint.TryParse(id, out uint key))
throw new IncorrectTagValue(QuickFix.Fields.Tags.OrderID);
double price = Convert.ToDouble(replace.Price.getValue());
uint sz = Convert.ToUInt32(Math.Abs(replace.OrderQty.getValue()));
var upd = new Update
@@ -95,7 +85,7 @@ create algo
var resp = _orderservice.Value.update_order(upd);
if (resp.ErrorCode != OrderError.Ok)
{
send_cancel_reject(s, resp.ErrorCode, "Cancel Rejected: " + resp.ErrorCode.ToString() + " - " + resp.Msg, replace);
send_cancel_reject(s, "Cancel Rejected: " + resp.ErrorCode.ToString() + " - " + resp.Msg, replace);
}
}
@@ -138,10 +128,8 @@ create algo
cr.Quantity = Convert.ToUInt32(Math.Abs(create.OrderQty.getValue()));
}
catch { throw new IncorrectTagValue(QuickFix.Fields.Tags.OrderQty); }
if (!create.IsSetClOrdID())
if(!create.IsSetClOrdID())
throw new IncorrectTagValue(QuickFix.Fields.Tags.ClOrdID);
else
def.ExternalOrderId = create.ClOrdID.ToString();
var resp = _orderservice.Value.create_order(cr);
_fix_clorderids[resp.OrderKey] = create.ClOrdID.getValue();
@@ -163,15 +151,8 @@ create algo
else
{
var custom = algodef.Definition.Clone();
foreach (var fd in CustomOrderDefinition.Descriptor.Fields.InDeclarationOrder())
{
var val = fd.Accessor.GetValue(custom);
if(val != null && val is Google.Protobuf.IMessage valmsg)
{
ProtoFix.setup_message(valmsg, fix);
break;
}
}
var imsg = ATDL.extract_order_from_custom(custom);
ProtoFix.fix_to_imsg(imsg, fix);
return custom;
}
}
@@ -184,7 +165,13 @@ create algo
case '1':
return new CustomOrderDefinition { Market = new MarketOrderDefinition() };
case '2':
return new CustomOrderDefinition { Limit = new LimitOrderDefinition() };
{
if(fix.IsSetField(QuickFix.Fields.Tags.MaxShow))
return new CustomOrderDefinition { GlbxIceberg =
new GLBXIcebergOrderDefinition() { MaxShowQuantity = (uint)Math.Abs(fix.GetInt(QuickFix.Fields.Tags.MaxShow)) }};
else
return new CustomOrderDefinition { Limit = new LimitOrderDefinition() };
}
case '3':
return new CustomOrderDefinition { Stop = new StopOrderDefinition()
{
+6 -11
View File
@@ -159,24 +159,18 @@ namespace bts.fix
Log.FIX.error(_sess.ToString() + " " + message, file, line);
}
protected void send_cancel_reject(SessionID sess, OrderError reject_reason, string text, Message refmessage)
protected void send_cancel_reject(SessionID sess, string text, Message refmessage)
{
OrderCancelReject rej = new OrderCancelReject();
if (reject_reason == OrderError.UnknownOrder) {
rej.CxlRejReason = new CxlRejReason(CxlRejReason.UNKNOWN_ORDER);
rej.OrdStatus = new OrdStatus(OrdStatus.REJECTED);
rej.OrderID = new OrderID("NONE");
}
if (refmessage is QuickFix.FIX42.OrderCancelRequest cancel)
{
if (cancel.IsSetClOrdID())
rej.SetField(cancel.ClOrdID);
if (cancel.IsSetOrigClOrdID())
rej.SetField(cancel.OrigClOrdID);
if (cancel.IsSetOrderID() && reject_reason != OrderError.UnknownOrder)
if (cancel.IsSetOrderID())
rej.SetField(cancel.OrderID);
rej.CxlRejResponseTo = new CxlRejResponseTo(CxlRejResponseTo.ORDER_CANCEL_REQUEST);
rej.CxlRejResponseTo = new CxlRejResponseTo('1');
rej.Text = new Text(text);
_router.send(rej, sess);
}
@@ -186,14 +180,15 @@ namespace bts.fix
rej.SetField(replace.ClOrdID);
if (replace.IsSetOrigClOrdID())
rej.SetField(replace.OrigClOrdID);
if (replace.IsSetOrderID() && reject_reason != OrderError.UnknownOrder)
if (replace.IsSetOrderID())
rej.SetField(replace.OrderID);
rej.CxlRejResponseTo = new CxlRejResponseTo(CxlRejResponseTo.ORDER_CANCEL_REPLACE_REQUEST);
rej.CxlRejResponseTo = new CxlRejResponseTo('2');
rej.Text = new Text(text);
_router.send(rej, sess);
}
else
throw new UnsupportedMessageType();
}
protected bool security_types_equal(bts.api.SecurityType btstype, QuickFix.Fields.SecurityType fixtype)
+2 -2
View File
@@ -84,7 +84,7 @@
{ "name": "Join", "definition": { "join": { "child": { "limit": {} } } } },
{ "name": "Iceberg", "definition": { "iceberg": { "child": { "limit": {} } } } },
{ "name": "Scratch", "definition": { "scratch": { "child": { "limit": {} } } } },
{ "name": "Spreader", "definition": { "spreader": { } } },
{ "name": "ISpreader", "definition": { "iceberg": { "child": { "spreader": {} } } } }
{ "name": "ISpreader", "definition": { "iceberg": { "child": { "spreader": {} } } } },
{ "name": "Spreader", "definition": { "spreader": { } } }
]
}
+21 -2
View File
@@ -7,7 +7,7 @@
<Product>Spark</Product>
<Description />
<Platforms>x64</Platforms>
<PlatformTarget>x64</PlatformTarget>
<PlatformTarget>AnyCPU</PlatformTarget>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<WarningsAsErrors />
<LangVersion>7.2</LangVersion>
@@ -24,7 +24,13 @@
<PackageReference Include="QuickFix.Net.NETCore.FIX42" Version="1.8.1" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
</ItemGroup>
<ItemGroup Condition = " '$(OS)' == 'Windows_NT' ">
<Reference Include="fixatdl">
<HintPath>../../../externals/windows/lib/debug/Atdl4net.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../spark_api/spark_api.csproj"/>
<ProjectReference Include="../spark_core/spark_core.csproj"/>
@@ -35,6 +41,12 @@
<Copy SourceFiles="./spark_algos.json" DestinationFolder="$(OutputPath)/" SkipUnchangedFiles="true" />
<Copy SourceFiles="./spec/fix/FIX42.xml" DestinationFolder="$(OutputPath)/spec/fix/" SkipUnchangedFiles="true" />
<Copy SourceFiles="./spec/fix/FIX44.xml" DestinationFolder="$(OutputPath)/spec/fix/" SkipUnchangedFiles="true" />
<Copy SourceFiles="./atdl/schema/fixatdl-core-1-1.xsd" DestinationFolder="$(OutputPath)/atdl/schema/" SkipUnchangedFiles="true" />
<Copy SourceFiles="./atdl/schema/fixatdl-flow-1-1.xsd" DestinationFolder="$(OutputPath)/atdl/schema/" SkipUnchangedFiles="true" />
<Copy SourceFiles="./atdl/schema/fixatdl-layout-1-1.xsd" DestinationFolder="$(OutputPath)/atdl/schema/" SkipUnchangedFiles="true" />
<Copy SourceFiles="./atdl/schema/fixatdl-regions-1-1.xsd" DestinationFolder="$(OutputPath)/atdl/schema/" SkipUnchangedFiles="true" />
<Copy SourceFiles="./atdl/schema/fixatdl-timezones-1-1.xsd" DestinationFolder="$(OutputPath)/atdl/schema/" SkipUnchangedFiles="true" />
<Copy SourceFiles="./atdl/schema/fixatdl-validation-1-1.xsd" DestinationFolder="$(OutputPath)/atdl/schema/" SkipUnchangedFiles="true" />
</Target>
<Target Name="copy_fix471" AfterTargets="PostBuildEvent" >
@@ -42,5 +54,12 @@
<Copy SourceFiles="./spark_algos.json" DestinationFolder="$(OutputPath)/../net471" SkipUnchangedFiles="true" />
<Copy SourceFiles="./spec/fix/FIX42.xml" DestinationFolder="$(OutputPath)/../net471/spec/fix/" SkipUnchangedFiles="true" />
<Copy SourceFiles="./spec/fix/FIX44.xml" DestinationFolder="$(OutputPath)/../net471/spec/fix/" SkipUnchangedFiles="true" />
<Copy SourceFiles="./atdl/schema/fixatdl-core-1-1.xsd" DestinationFolder="$(OutputPath)/../net471/atdl/schema/" SkipUnchangedFiles="true" />
<Copy SourceFiles="./atdl/schema/fixatdl-flow-1-1.xsd" DestinationFolder="$(OutputPath)/../net471/atdl/schema/" SkipUnchangedFiles="true" />
<Copy SourceFiles="./atdl/schema/fixatdl-layout-1-1.xsd" DestinationFolder="$(OutputPath)/../net471/atdl/schema/" SkipUnchangedFiles="true" />
<Copy SourceFiles="./atdl/schema/fixatdl-regions-1-1.xsd" DestinationFolder="$(OutputPath)/../net471/atdl/schema/" SkipUnchangedFiles="true" />
<Copy SourceFiles="./atdl/schema/fixatdl-timezones-1-1.xsd" DestinationFolder="$(OutputPath)/../net471/atdl/schema/" SkipUnchangedFiles="true" />
<Copy SourceFiles="./atdl/schema/fixatdl-validation-1-1.xsd" DestinationFolder="$(OutputPath)/../net471/atdl/schema/" SkipUnchangedFiles="true" />
</Target>
</Project>
@@ -1,148 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using bts.api;
using MathNet.Numerics.Statistics;
using Google.Protobuf.WellKnownTypes;
using bts.co2;
namespace bts.history
{
public interface IAlgo
{
bool is_completed();
void set_param(string name, string val);
void process_book(string security_desc, uint security_key, co2.BookMessage current_book, co2.BookMessage curr_book,
MarketDataIncrementalRefresh packet);
void process_trades(string security_desc, uint security_key, IEnumerable<co2.TradeMessage> trades,
MarketDataIncrementalRefresh packet);
}
abstract public partial class AlgoBase : IAlgo
{
public readonly Guid guid = Guid.NewGuid();
public ulong order_key { get; private set;}
public string[] security_list { get; private set; }
public Action<FillEntry> on_fill;
public Action<OrderStatus> on_status;
protected IOrderSink _sink;
public IOrderSink sink => _sink;
readonly protected SortedDictionary< string, Func<MDEntry, OrderIDEntry, bool> > _filter = new SortedDictionary<string, Func<MDEntry, OrderIDEntry, bool>>();
protected AlgoBase(IOrderSink sink, string[] security_list)
{
on_fill = new Action<FillEntry>(f => {});
on_status = new Action<OrderStatus>(s => {});
this._sink = sink;
this.security_list = security_list;
foreach (var sec in security_list)
_filter[sec] = (MDEntry md, OrderIDEntry id) => md.Symbol == sec;
}
readonly Dictionary<string, string> _algo_params = new Dictionary<string, string>();
public IReadOnlyDictionary<string, string> algo_params => _algo_params;
public virtual void set_param(string name, string val)
{
_algo_params[name] = val;
var pi = this.GetType().GetProperty(name);
if(pi != null)
{
if(val.Contains(','))
{
var elem = pi.PropertyType.GetElementType();
var ary = val.Split(',').Select(x => Convert.ChangeType(x, elem)).ToArray();
var tary = Array.CreateInstance(elem, ary.Length);
Array.Copy(ary, tary, ary.Length);
pi.SetValue(this, tary);
}
else
pi.SetValue(this, Convert.ChangeType(val, pi.PropertyType));
}
}
public virtual void process_book(string security_desc, uint security_key, co2.BookMessage current_book, co2.BookMessage curr_book,
MarketDataIncrementalRefresh packet)
{
if(!_filter.ContainsKey(security_desc))
return;
on_book(security_desc, security_key, current_book, curr_book, packet);
}
public virtual void process_trades(string security_desc, uint security_key, IEnumerable<co2.TradeMessage> trades,
MarketDataIncrementalRefresh packet)
{
if (!_filter.ContainsKey(security_desc))
return;
on_trades(security_desc, security_key, trades, packet);
}
public abstract object report();
public abstract bool is_completed();
protected virtual void on_book(string security_desc, uint security_key, co2.BookMessage current_book, co2.BookMessage working_book,
MarketDataIncrementalRefresh packet) { }
protected virtual void on_trades(string security_desc, uint security_key, IEnumerable<TradeMessage> trades,
MarketDataIncrementalRefresh packet) { }
protected abstract void do_launch(string[] security_list, api.Side side, double price, uint size, Timestamp asof, ulong order_key);
protected abstract void do_update(Timestamp asof, double price, uint size = uint.MinValue);
protected virtual void do_update(Timestamp asof, Dictionary<string, string> algo_params, double price, uint size = uint.MinValue)
{
foreach (var s in algo_params)
this.set_param(s.Key, s.Value);
this.do_update(asof, price, size);
}
protected abstract void do_cancel(Timestamp asof);
protected virtual void get_done(Timestamp asof) {}
public class Handle : IEquatable<Handle>
{
readonly AlgoBase _algo;
public Handle(AlgoBase algo)
{
_algo = algo;
}
public AlgoBase algo => _algo;
public ulong order_key => _algo.order_key;
public void launch(string[] security_list, api.Side side, double price, uint size, Timestamp asof, ulong order_key = ulong.MinValue)
{
if(order_key == ulong.MinValue)
order_key = IDGenerator.next_order_id();
_algo.do_launch(security_list, side, price, size, asof, order_key);
}
public void update(Timestamp asof, double price, uint size = uint.MinValue)
{
_algo.do_update(asof, price, size);
}
public void update(Timestamp asof, Dictionary<string, string> algo_params, double price, uint size = uint.MinValue)
{
foreach (var s in algo_params)
_algo.set_param(s.Key, s.Value);
update(asof, price, size);
}
public void cancel(Timestamp asof)
{
_algo.do_cancel(asof);
}
public void get_done(Timestamp asof)
{
_algo.get_done(asof);
}
public override int GetHashCode()
{
return this.algo.guid.GetHashCode();
}
public bool Equals(Handle other)
{
return this.algo.guid == other.algo.guid;
}
}
}
}
@@ -1,94 +0,0 @@
using System;
using MathNet.Numerics.Statistics;
using Google.Protobuf.WellKnownTypes;
using System.Collections.Generic;
using System.Reflection;
using bts.api;
namespace bts.history
{
public class AlgoFactory
{
static public AlgoBase algo_factory<AlgoType>(IOrderSink sink,string[] security_list, string algo_params = null)
where AlgoType : AlgoBase
{
return AlgoBase.algo_factory(typeof(AlgoType), sink, security_list, algo_params);
}
static public void set_algo_params(IAlgo inst, string algo_params)
{
AlgoBase.set_algo_params((AlgoBase) inst, algo_params);
}
static public void set_algo_params(IAlgo inst, IEnumerable<string> param)
{
AlgoBase.set_algo_params((AlgoBase)inst, param);
}
public static AlgoBase.Handle launch(AlgoBase algo, api.Side side, double price, uint size, Timestamp asof,
Action<AlgoBase.Handle, FillEntry> more_on_fill = null,
Action<AlgoBase.Handle, OrderStatus> more_on_status = null)
{
var order_key = IDGenerator.next_order_id();
//I am activating myself at the top\
var h = new AlgoBase.Handle(algo);
h.launch(algo.security_list, side, price, size, asof, order_key);
if (more_on_fill != null)
algo.on_fill += f => more_on_fill(h, f);
if (more_on_status != null)
algo.on_status += s => more_on_status(h, s);
return h;
}
}
abstract partial class AlgoBase
{
static public AlgoBase algo_factory(System.Type t, IOrderSink sink,
string[] security_list, string algo_params = null)
{
AlgoBase inst = inst = (AlgoBase)Activator.CreateInstance(t, sink, security_list);
if(algo_params != null)
set_algo_params(inst, algo_params);
return inst;
}
public virtual Handle create<C>(Action<Handle, FillEntry> more_on_fill = null,
Action<Handle, OrderStatus> more_on_status = null)
where C : AlgoBase
{
var child = AlgoBase.algo_factory(typeof(C), _sink, security_list);
Handle h = hookup_child(child, more_on_fill, more_on_status);
return h;
}
protected Handle hookup_child(AlgoBase child, Action<Handle, FillEntry> more_on_fill, Action<Handle, OrderStatus> more_on_status)
{
child.order_key = order_key;
AlgoBase.set_algo_params(child, this.algo_params);
child.on_fill += f => this.on_fill(f);
//child.on_status += s => this.on_status(s);
var h = new Handle(child);
if (more_on_fill != null)
child.on_fill += (f => more_on_fill(h, f));
if (more_on_status != null)
child.on_status += (s => more_on_status(h, s));
return h;
}
static public void set_algo_params(AlgoBase inst, string algo_params)
{
string[] param = algo_params.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
set_algo_params(inst, param);
}
static public void set_algo_params(AlgoBase inst, IEnumerable<string> param)
{
foreach (var par in param)
{
string[] tup = par.Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries);
Log.assert(tup.Length == 2);
inst.set_param(tup[0], tup[1]);
}
}
static public void set_algo_params(AlgoBase inst, IReadOnlyDictionary<string, string> param)
{
foreach (var par in param)
inst.set_param(par.Key, par.Value);
}
}
}
@@ -1,70 +0,0 @@
using System;
using System.Collections.Generic;
using mbts.co2;
using bts.api;
using Google.Protobuf.WellKnownTypes;
using MathNet.Numerics.Statistics;
namespace bts.history
{
public class CompletionCoverAlgo<Child, Hedge> : CompositeHedgeAlgo<Child, Hedge>
where Child : AlgoBase
where Hedge : AlgoBase
{
public CompletionCoverAlgo(IOrderSink sink, string[] security_list) : base(sink, security_list) { }
string[] _security_list;
Side _myside;
double _myprice;
uint _mysize;
//algo parameters
public double hedge_ticks { get; set; } = 0.0;
public double hedge_factor { get; set; } = 1.0;
protected override void do_launch(string[] security_list, Side side, double price, uint size, Timestamp asof, ulong order_key)
{
_security_list = security_list;
_myside = side;
_myprice = price;
_mysize = size;
_child = this.create<Child>();
_child.launch(security_list, side, price, size, asof);
}
protected override void on_child_status(Handle child, OrderStatus stat)
{
if(_child?.Equals(child) ?? false)
{
if(stat.state.Status == api.orderman.OrderStatus.Completed)
{
var side = Utils.opposite_side(_myside);
uint size = (uint)(_mysize * this.hedge_factor);
double price = (side == Side.Buy) ?
_myprice - this.hedge_ticks :
_myprice + this.hedge_ticks;
send_hedge(_security_list, side, price, size, stat.TransactTime, null,
(status_handle, status_entry) => { this.on_status?.Invoke(status_entry); }
);
}
this.on_status?.Invoke(stat);
}
}
protected override void do_update(Timestamp asof, double price, uint size = uint.MinValue)
{
_child.update(asof, price, size);
}
protected override void do_cancel(Timestamp asof)
{
_child.cancel(asof);
}
protected override void on_child_fill(Handle child, FillEntry fill)
{
}
}
}
@@ -1,261 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using MathNet.Numerics.Statistics;
using Google.Protobuf.WellKnownTypes;
namespace bts.history
{
public abstract class CompositeBase<Child, Hedge> : AlgoBase
where Hedge : AlgoBase
{
protected List<Handle> _children = new List<Handle>();
protected Handle _child
{
get
{
Log.assert(_children.Count <= 1);
return _children.FirstOrDefault();
}
set
{
Log.assert(_children.Count <= 1);
if(value == null)
{
if(_children.Count == 1)
_children.RemoveAt(0);
}
else
{
if(_children.Count == 0)
_children.Add(value);
else
_children[0] = value;
}
}
}
public CompositeBase(IOrderSink sink, string[] security_list) : base(sink, security_list)
{
}
public override Handle create<C>(Action<Handle, FillEntry> more_on_fill = null,
Action<Handle, OrderStatus> more_on_status = null)
{
if(typeof(C) == this.GetType())
{
Log.assert(false);
return null;
//return AlgoBase.activate_self(this, side, price, size, asof, more_on_fill, more_on_status);
}
else
{
Action<Handle, FillEntry> of = new Action<Handle, FillEntry>((h, f) => on_child_fill(h, f));
if (more_on_fill != null)
of += more_on_fill;
Action<Handle, OrderStatus> os = new Action<Handle, OrderStatus>((h, s) =>
{
on_child_status(h, s);
if (s.is_terminal())
_children.Remove(h);
});
if (more_on_status != null)
os += more_on_status;
var handle = base_create<C>(of, os);
_children.Add(handle);
return handle;
}
}
protected Handle base_create<C>(Action<Handle, FillEntry> of, Action<Handle, OrderStatus> os)
where C : AlgoBase
{
return base.create<C>(of, os);
}
protected override void do_update(Timestamp asof, double price, uint size = uint.MinValue)
{
foreach(var child in _children.ToArray())
child?.update(asof, price, size);
}
protected override void get_done(Timestamp asof)
{
base.get_done(asof);
foreach (var child in _children.ToArray())
child?.get_done(asof);
}
protected override void do_cancel(Timestamp asof)
{
foreach (var child in _children.ToArray())
child?.cancel(asof);
}
protected virtual void on_child_fill(Handle child, FillEntry fill) { }
protected abstract void on_child_status(Handle child, OrderStatus stat);
}
public abstract class CompositeAlgo<Child> : CompositeBase<Child, NullAlgo>
{
public CompositeAlgo(IOrderSink sink, string[] security_list) : base(sink, security_list) { }
public override bool is_completed()
{
bool comp = true;
foreach (var child in _children)
comp &= child.algo.is_completed();
return comp;
}
public override object report()
{
string c = "";
foreach (var child in _children)
c+= child.algo.report();
return $"{c}";
}
public override void set_param(string name, string val)
{
base.set_param(name, val);
foreach (var child in _children)
child?.algo.set_param(name, val);
}
public override void process_book(string security_desc, uint security_key, co2.BookMessage current_book, co2.BookMessage working_book,
MarketDataIncrementalRefresh packet)
{
base.process_book(security_desc, security_key, current_book, working_book, packet);
foreach (var child in _children.ToArray()) //copy because this could remove / add a child
child?.algo.process_book(security_desc, security_key, current_book, working_book, packet);
}
}
public abstract class CompositeHedgeAlgo<Child, Hedge> : CompositeBase<Child, Hedge>
where Hedge : AlgoBase
{
protected int _payupcount;
protected Dictionary<Handle, Hedge> _hedges = new Dictionary<Handle, Hedge>();
public CompositeHedgeAlgo(IOrderSink sink, string[] security_list) : base(sink, security_list) {}
public override bool is_completed()
{
bool comp = true;
foreach (var child in _children)
comp &= child.algo.is_completed();
foreach (var sub in _hedges.Values)
{
var hc = sub.is_completed();
if(!hc)
Log.assert(true);
comp &= hc;
}
return comp;
}
protected override void get_done(Timestamp asof)
{
base.get_done(asof);
foreach (var child in _children.ToArray())
child?.get_done(asof);
foreach (var sub in _hedges.Keys.ToArray())
sub.get_done(asof);
}
public override object report()
{
string c = "";
foreach (var child in _children)
c+= child.algo.report();
int ih = 0;
string sh = string.Empty;
foreach (var sub in _hedges.Values)
{
if(sub.report() is string sr)
sh += sr;
if(sub.report() is int ir)
ih += ir;
}
return $"{c} Hedge Payups {sh} {ih+_payupcount} Incomplete {_hedges.Values.Sum( x => x.is_completed() ? 0u : 1u) } ";
}
public override void set_param(string name, string val)
{
base.set_param(name, val);
foreach (var child in _children)
child?.algo.set_param(name, val);
foreach (var sub in _hedges.Values)
sub.set_param(name, val);
}
public override void process_book(string security_desc, uint security_key, co2.BookMessage current_book, co2.BookMessage working_book,
MarketDataIncrementalRefresh packet)
{
base.process_book(security_desc, security_key, current_book, working_book, packet);
foreach (var child in _children.ToArray())
child?.algo.process_book(security_desc, security_key, current_book, working_book, packet);
foreach (var sub in _hedges.Values.ToArray())
sub.process_book(security_desc, security_key, current_book, working_book, packet);
}
public override Handle create<C>(Action<Handle, FillEntry> more_on_fill = null,
Action<Handle, OrderStatus> more_on_status = null)
{
if (typeof(Hedge) == typeof(C))
{
Action<Handle, FillEntry> of = new Action<Handle, FillEntry>((h, f) => {} );
if (more_on_fill != null)
of += more_on_fill;
Action<Handle, OrderStatus> os = new Action<Handle, OrderStatus>((h, s) => {} );
if (more_on_status != null)
os += more_on_status;
var handle = base_create<Hedge>(of, os);
_hedges[handle] = (Hedge)handle.algo;
return handle;
}
else
return base.create<C>(more_on_fill, more_on_status);
}
protected void send_hedge(string security_desc, api.Side side, double price, uint size, Timestamp asof,
Action<Handle, FillEntry> more_on_fill = null,
Action<Handle, OrderStatus> more_on_status = null)
{
send_hedge(new[] { security_desc }, side, price, size, asof, more_on_fill, more_on_status);
}
protected void send_hedge(string[] security_list, api.Side side, double price, uint size, Timestamp asof,
Action<Handle, FillEntry> more_on_fill = null,
Action<Handle, OrderStatus> more_on_status = null)
{
Action<Handle, FillEntry> hedge_on_fill = (hand, f) =>
{
if(more_on_fill != null)
more_on_fill(hand, f);
if (f.fully_filled)
{
if (_hedges.TryGetValue(hand, out Hedge h))
{
if (h.report() is int pay)
_payupcount += pay;
_hedges.Remove(hand);
}
}
};
Action<Handle, OrderStatus> hedge_on_status = (hand,s) =>
{
if(more_on_status != null)
more_on_status(hand, s);
if (s.is_terminal())
_hedges.Remove(hand);
};
var handle = this.create<Hedge>(hedge_on_fill, hedge_on_status);
handle.launch(security_list, side, price, size, asof);
}
}
}
@@ -1,70 +0,0 @@
using System;
using System.Collections.Generic;
using mbts.co2;
using bts.api;
using Google.Protobuf.WellKnownTypes;
using MathNet.Numerics.Statistics;
namespace bts.history
{
public class CoverAlgo<Child, Hedge> : CompositeHedgeAlgo<Child, Hedge>
where Child : AlgoBase
where Hedge : AlgoBase
{
public CoverAlgo(IOrderSink sink, string[] security_list) : base(sink, security_list) { }
//algo state
private MarketDataIncrementalRefresh _packet;
string[] _security_list;
//algo parameters
public double hedge_ticks { get; set; } = 0.0;
public double hedge_factor { get; set; } = 1.0;
protected override void do_launch(string[] security_list, Side side, double price, uint size, Timestamp asof, ulong order_key)
{
_security_list = security_list;
_child = this.create<Child>();
_child.launch(security_list, side, price, size, asof);
}
protected override void on_child_status(Handle child, OrderStatus stat)
{
if(_child?.Equals(child) ?? false)
this.on_status?.Invoke(stat);
}
protected override void do_update(Timestamp asof, double price, uint size = uint.MinValue)
{
_child.update(asof, price, size);
}
protected override void do_cancel(Timestamp asof)
{
_child.cancel(asof);
}
protected override void on_book(string security_desc, uint security_key, co2.BookMessage current_book, co2.BookMessage working_book,
MarketDataIncrementalRefresh packet)
{
_packet = packet;
}
protected override void on_child_fill(Handle child, FillEntry fill)
{
if(!child.Equals(_child))
return;
base.on_child_fill(child, fill);
var side = Utils.opposite_side(fill.order.side);
uint size = (uint)(fill.size*this.hedge_factor);
double price = (side == Side.Buy) ?
fill.price - this.hedge_ticks :
fill.price + this.hedge_ticks;
send_hedge(fill.order.security_desc, side, price, size, fill.TransactTime);
}
}
}
@@ -1,13 +0,0 @@
namespace bts.history
{
static class IDGenerator
{
static uint __myid = 999_999;
static public uint next_order_id()
{
return (++__myid);
}
}
}
@@ -1,153 +0,0 @@
using System;
using Google.Protobuf.WellKnownTypes;
using MathNet.Numerics.Statistics;
using mbts.co2;
namespace bts.history
{
public class JoinAlgo<Child> : CompositeAlgo<Child>
where Child : AlgoBase
{
enum AlgoState
{
Begin, WaitingForJoin, Joined, Done
}
//algo state
AlgoState _state;
OrderStatus _status;
api.Side _myside;
uint _mysize;
Timestamp _myasof;
co2.BookMessage _snapshot, _currentbook;
int _turncount, _pilecount;
public JoinAlgo(IOrderSink sink, string[] security_list) : base(sink, security_list) { }
//algo parameters
public bool initial_pile { get; set; } = false;
public bool should_chase { get; set; } = true;
public double join_factor { get; set; } = 1.0;
public uint join_quantity{ get; set; } = 0;
protected override void do_launch(string[] security_list, api.Side side, double price, uint size, Timestamp asof, ulong order_key)
{
_state = AlgoState.Begin;
_myside = side;
_mysize = size;
_myasof = asof;
_child = null;
}
public override bool is_completed()
{
return _state == AlgoState.Done;
}
public override object report()
{
var b = base.report();
return $"{b} Turns,Piles,Join(Size,Price,piq)={_turncount},{_pilecount},({_status?.state?.Quantity},{_status?.state?.Price})";
}
protected override void on_child_status(Handle child, OrderStatus stat)
{
_status = stat;
if(stat.is_terminal())
_state = AlgoState.Done;
this.on_status?.Invoke(_status);
}
bool has_turned()
{
bool turn = ((_myside == api.Side.Buy &&
_currentbook.side_at(_myside, 0) > _snapshot.side_at(_myside, 0)) || //new top level bid price greater than old, market turn
(_myside == api.Side.Sell &&
_currentbook.side_at(_myside, 0) < _snapshot.side_at(_myside, 0))); //new top level ask price less than old, market turn
return turn;
}
protected override void on_book(string security_desc, uint security_key, co2.BookMessage current_book, co2.BookMessage working_book,
MarketDataIncrementalRefresh packet)
{
if(_snapshot == null)
_snapshot = current_book.Clone();
_currentbook = current_book;
switch (_state)
{
case AlgoState.Begin:
{
if(initial_pile)
{
var thresh = (this.join_quantity > 0 ? this.join_quantity : this.join_factor * _mysize);
if(_currentbook.sidesize_at(_myside, 0) >= thresh)
{
_pilecount++;
deploy_join_function(packet, security_desc, _currentbook.side_at(_myside, 0));
_state = AlgoState.Joined;
_snapshot = _currentbook.Clone();
}
}
else
_state = AlgoState.WaitingForJoin;
}
break;
case AlgoState.WaitingForJoin:
{
bool turn = has_turned();
var thresh = (this.join_quantity > 0 ? this.join_quantity : this.join_factor * _mysize);
if(turn &&_currentbook.sidesize_at(_myside, 0) >= thresh)
{
_turncount++;
deploy_join_function(packet, security_desc, _currentbook.side_at(_myside, 0));
_state = AlgoState.Joined;
}
_snapshot = _currentbook.Clone();
}
break;
case AlgoState.Joined:
{
if (this.should_chase)
{
bool turn = has_turned();
var thresh = (this.join_quantity > 0 ? this.join_quantity : this.join_factor * _mysize);
if (turn && _currentbook.sidesize_at(_myside, 0) >= thresh)
{
_turncount++;
deploy_join_function(packet, security_desc, _currentbook.side_at(_myside, 0));
_snapshot = _currentbook.Clone();
}
}
}
break;
case AlgoState.Done:
break;
default:
Log.assert(false, "invalid algo state");
break;
}
}
void deploy_join_function(MarketDataIncrementalRefresh packet, string security_desc, double joinprice)
{
Log.Testing.info("deploy_join_function ");
if(_currentbook.bid_at(0) == _currentbook.ask_at(0))
{
Log.Testing.error("crossed book");
return;
}
if(_child == null)
{
_child = this.create<Child>();
_child.launch(new[] { security_desc }, _myside, joinprice, _mysize, packet.timestamp());
}
else
{
_child.update(packet.timestamp(), joinprice);
}
}
}
}
@@ -1,125 +0,0 @@
using System;
using System.Collections.Generic;
using mbts.co2;
using System.Linq;
using Google.Protobuf.WellKnownTypes;
using MathNet.Numerics.Statistics;
namespace bts.history
{
public class LeanAlgo<Child> : CompositeAlgo<Child>
where Child : AlgoBase
{
enum AlgoState
{
LeanWatch, Payup, Done
}
//algo state
AlgoState _state;
OrderStatus _status;
api.Side _myside;
double _myprice;
uint _mysize;
co2.BookMessage _snapshot, _currentbook;
int _payupcount;
public LeanAlgo(IOrderSink sink, string[] security_list) : base(sink, security_list) { }
//algo parameters
public double lean_factor { get; set; } = 3.0;
public uint lean_quantity { get; set; } = 0;
protected override void do_launch(string[] security_list, api.Side side, double price, uint size, Timestamp asof, ulong order_key)
{
_state = AlgoState.LeanWatch;
_myside = side;
_mysize = size;
_myprice = price;
_child = this.create<Child>();
_child.launch(security_list, side, price, size, asof);
}
public override bool is_completed()
{
return _state == AlgoState.Done;
}
public override object report()
{
return _payupcount;
}
protected override void on_child_status(Handle child, OrderStatus stat)
{
_status = stat;
if (stat.is_terminal())
_state = AlgoState.Done;
this.on_status?.Invoke(_status);
}
protected override void on_book(string security_desc, uint security_key, co2.BookMessage current_book, co2.BookMessage working_book,
MarketDataIncrementalRefresh packet)
{
if (_snapshot == null)
_snapshot = current_book.Clone();
_currentbook = current_book;
switch (_state)
{
case AlgoState.LeanWatch:
{
bool payupprice = false, payupsize = false;
var leansize = (this.lean_quantity == 0) ? this.lean_factor * this._mysize : this.lean_quantity;
if (_myside == api.Side.Buy)
{
double best_ask = _snapshot.ask_at(0);
var best_ask_size = _snapshot.asksize_at(0);
payupprice = _currentbook.ask_at(0) > best_ask;
payupsize = best_ask_size < leansize;
}
else
{
double best_bid = _snapshot.bid_at(0);
var best_bid_size = _snapshot.bidsize_at(0);
payupprice = _currentbook.bid_at(0) < best_bid;
payupsize = best_bid_size < leansize;
}
if (payupprice || payupsize)
{
_payupcount++;
_state = AlgoState.Payup;
payup_function(packet.timestamp());
}
}
break;
case AlgoState.Payup:
break;
case AlgoState.Done:
break;
default:
Log.assert(false, "invalid algo state");
break;
}
}
protected override void get_done(Timestamp asof)
{
payup_function(asof);
}
void payup_function(Timestamp asof)
{
double newprice = 0.0;
//plow through
if (_myside == api.Side.Sell)
newprice = _currentbook.all_bids().Min();
else
newprice = _currentbook.all_asks().Max();
//this should precipitate a fill
_child.update(asof, newprice);
Log.Testing.info($"payup_function ");
}
}
}
@@ -1,62 +0,0 @@
using System;
using bts.api;
using Google.Protobuf.WellKnownTypes;
using MathNet.Numerics.Statistics;
namespace bts.history
{
public class LimitOrder : AlgoBase
{
public LimitOrder(IOrderSink sink, string[] security_list) : base(sink, security_list) { }
protected OrderEntry _myorder;
OrderStatus _status;
uint _mysize;
double _debug_price;
public override object report() { return string.Empty; }
protected override void do_launch(string[] security_list, api.Side side, double price, uint size, Timestamp asof, ulong order_key)
{
setup_order(security_list, side, price, size, asof, order_key);
_sink.send(_myorder);
}
protected void setup_order(string[] security_list, Side side, double price, uint size, Timestamp asof, ulong order_key)
{
_debug_price = price;
_mysize = size;
Log.assert(security_list.Length == 1);
var security_desc = security_list[0];
Action<FillEntry> fill_action = f =>
{
if (this.on_fill != null)
this.on_fill(f);
};
Action<OrderStatus> status_action = s =>
{
_status = s;
if (this.on_status != null)
this.on_status(s.clone());
};
Log.assert(_myorder == null);
_myorder = new OrderEntry(asof, order_key, security_desc, side, price, size, fill_action, status_action);
}
protected override void do_update(Timestamp asof, double price, uint size = uint.MinValue)
{
if(size == _mysize)
size = uint.MinValue;
_debug_price = price;
_sink.update(_myorder.security_desc, asof, _myorder.order_id, price, size);
}
protected override void do_cancel(Timestamp asof)
{
if(_myorder == null)
return;
_sink.cancel(_myorder.security_desc, asof, _myorder.order_id);
}
public override bool is_completed() => _status?.is_terminal() ?? false;
}
}
@@ -1,19 +0,0 @@
using System;
using bts.api;
using Google.Protobuf.WellKnownTypes;
using MathNet.Numerics.Statistics;
namespace bts.history
{
public class MarketOrder : LimitOrder
{
public MarketOrder(IOrderSink sink, string[] security_list) : base(sink, security_list) { }
protected override void do_launch(string[] security_list, api.Side side, double price, uint size, Timestamp asof, ulong order_key)
{
setup_order(security_list, side, price, size, asof, order_key);
_myorder.market_order = true;
_sink.send(_myorder);
}
}
}
@@ -1,83 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
namespace bts.history
{
static class AlgoTestNativeMethods
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal unsafe delegate void child_launch_callback(byte* OrderDefinition, ulong length, uint order_key, double price, uint size);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal unsafe delegate void child_update_callback(byte* Update, ulong length, uint order_key);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal unsafe delegate void child_cancel_callback(uint order_key);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal unsafe delegate void child_status_callback(byte* OrderState, ulong length, uint order_key);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal unsafe delegate void child_fill_callback(byte* Fill, ulong length, uint order_key);
[DllImport("libspark")]
internal static extern IntPtr try_create_algo(api.orderman.CustomOrderDefinition.CustomOneofCase algo_type);
[DllImport("libspark")]
internal static extern IntPtr create_algo_driver(byte[] Security, int seclength,
byte[] OrderDefinition, int deflength,
child_launch_callback launch_cb,
child_update_callback update_cb,
child_cancel_callback cancel_cb,
child_status_callback stat_cb,
child_fill_callback fill_cb);
[DllImport("libspark")]
internal static extern void destroy_algo_driver(IntPtr algo_driver);
[DllImport("libspark")]
internal static extern void destroy_algo(IntPtr algo_driver);
[DllImport("libspark")]
internal static extern void launch_algo(IntPtr algo_driver, uint order_key, double price, uint size);
[DllImport("libspark")]
internal static extern void update_price(IntPtr algo_driver, double price);
[DllImport("libspark")]
internal static extern void update_size(IntPtr algo_driver, uint size);
[DllImport("libspark")]
internal static extern void cancel(IntPtr algo_driver);
[DllImport("libspark")]
internal static extern void advance_time(IntPtr algo_driver, ulong microsecond, uint steps);
[DllImport("libspark")]
internal static extern void update_book(IntPtr algo_driver, uint security_id, byte[] BookMessage, int length);
[DllImport("libspark")]
internal static extern void update_ticker(IntPtr algo_driver, uint security_id, byte[] TradeMessage, int length);
[DllImport("libspark")]
internal static extern void fill(IntPtr algo_driver, uint order_key, double price, uint quantity);
//see AlgoTestDriver.h
internal enum AlgoDriverState
{
CREATED,
// before_Launch() ->
READY,
// launch() ->
RUNNING,
CANCELED,
TERMINATED,
COMPLETED
};
[DllImport("libspark")]
internal static extern AlgoDriverState algo_driver_state(IntPtr algo_driver);
internal static bool state_is_terminal(AlgoDriverState st)
{
return st == AlgoDriverState.CANCELED || st == AlgoDriverState.TERMINATED || st == AlgoDriverState.COMPLETED;
}
}
}
@@ -1,320 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using Google.Protobuf;
using Google.Protobuf.WellKnownTypes;
using MathNet.Numerics.Statistics;
using mbts.co2;
namespace bts.history
{
public class NativeAlgo : CompositeAlgo<AlgoBase>
{
readonly Dictionary<ulong, api.orderman.OrderState> _order_key_vs_state = new Dictionary<ulong, api.orderman.OrderState>();
api.Side _myside;
double _myprice;
uint _mysize;
Timestamp _myasof;
api.Security _sec;
readonly api.orderman.OrderDefinition _def;
IntPtr _proxy;
readonly AlgoTestNativeMethods.child_launch_callback _launchcb;
readonly AlgoTestNativeMethods.child_update_callback _updatecb;
readonly AlgoTestNativeMethods.child_cancel_callback _cancelcb;
readonly AlgoTestNativeMethods.child_status_callback _statcb;
readonly AlgoTestNativeMethods.child_fill_callback _fillcb;
MessageParser<api.orderman.OrderDefinition> _defparser = new MessageParser<api.orderman.OrderDefinition>(() => new api.orderman.OrderDefinition());
MessageParser<api.orderman.Update> _updateparser = new MessageParser<api.orderman.Update>(() => new api.orderman.Update());
MessageParser<api.orderman.OrderState> _stateparser = new MessageParser<api.orderman.OrderState>(() => new api.orderman.OrderState());
MessageParser<api.orderman.Fill> _fillparser = new MessageParser<api.orderman.Fill>(() => new api.orderman.Fill());
OrderEntry _fake_order_for_status;
public NativeAlgo(IOrderSink sink, string[] security_list,
api.orderman.OrderDefinition def) : base(sink, security_list)
{
_def = def;
unsafe
{
_launchcb =
(byte * OrderDefinition, ulong length, uint order_key, double price, uint size) => {
on_native_launch(OrderDefinition, length, order_key, price, size); } ;
_updatecb =
(byte* Update, ulong length, uint order_key) => {
on_native_update(Update, length, order_key); };
_cancelcb =
(uint order_key) => {
on_native_cancel(order_key); };
_statcb =
(byte * OrderState, ulong length, uint order_key) => {
on_native_status(OrderState, length, order_key); } ;
_fillcb =
(byte * Fill, ulong length, uint order_key) => {
on_native_fill(Fill, length, order_key); } ;
}
init_proxy(security_list);
}
void init_proxy(string[] security_list)
{
Log.assert(security_list != null && security_list.Length == 1);
_sec = new api.Security { Id = _def.SecurityKey, Symbol = security_list[0] };
if (_sec.Symbol.Contains(':') || _sec.Symbol.Contains('-'))
_sec.Spread = new api.SpreadContract() { Normalized = true };
else
_sec.Future = new api.FutureContract();
reset();
}
void reset()
{
unsafe
{
if(_proxy != IntPtr.Zero)
{
AlgoTestNativeMethods.destroy_algo_driver(_proxy);
_order_key_vs_state.Clear();
}
var secser = _sec.ToByteArray();
var defser = _def.ToByteArray();
_proxy = AlgoTestNativeMethods.create_algo_driver(secser, secser.Length, defser, defser.Length,
_launchcb, _updatecb, _cancelcb,
_statcb, _fillcb);
Log.assert(_proxy != IntPtr.Zero);
}
}
protected override void do_launch(string[] security_list, api.Side side, double price, uint size, Timestamp asof, ulong order_key)
{
Log.assert(security_list != null && security_list.Length == 1);
Log.assert(side == _def.Side);
_myside = side;
_myprice = price;
_mysize = size;
_myasof = asof;
AlgoTestNativeMethods.launch_algo(_proxy, (uint)order_key, price, size);
_fake_order_for_status = new OrderEntry(asof, order_key, security_list[0], side, price, size, null, null, "Native");
}
Handle hookup_child(AlgoBase child, string[] security_list, api.Side side,
double price, uint size, Timestamp asof, uint order_key)
{
Action<Handle, FillEntry> of = new Action<Handle, FillEntry>((h, f) =>
on_child_fill(h, f));
Action<Handle, OrderStatus> os = new Action<Handle, OrderStatus>((h, s) =>
{
on_child_status(h, s);
if (s.is_terminal())
_children.Remove(h);
});
var handle = this.hookup_child(child, of, os);
_children.Add(handle);
handle.launch(security_list, side, price, size, asof, order_key);
return handle;
}
// callback when this child launches other guys
unsafe void on_native_launch(byte* OrderDefinition, ulong length, uint order_key, double price, uint size)
{
byte[] arr = new byte[length];
Marshal.Copy((IntPtr)OrderDefinition, arr, 0, (int)length);
api.orderman.OrderDefinition def = _defparser.ParseFrom(arr);
switch(def.CustomDef.CustomCase)
{
case api.orderman.CustomOrderDefinition.CustomOneofCase.Market:
{
var child = AlgoBase.algo_factory(typeof(MarketOrder), _sink, this.security_list);
hookup_child(child, this.security_list, def.Side, price, size, _myasof, order_key);
}
break;
case api.orderman.CustomOrderDefinition.CustomOneofCase.Limit:
case api.orderman.CustomOrderDefinition.CustomOneofCase.GlbxIceberg:
{
var child = AlgoBase.algo_factory(typeof(LimitOrder), _sink, this.security_list);
hookup_child(child, this.security_list, def.Side, price, size, _myasof, order_key);
}
break;
case api.orderman.CustomOrderDefinition.CustomOneofCase.Stop:
case api.orderman.CustomOrderDefinition.CustomOneofCase.StopLimit:
Log.assert(false);
break;
case api.orderman.CustomOrderDefinition.CustomOneofCase.Dynamic:
Log.assert(false);
break;
default:
{
IntPtr native = AlgoTestNativeMethods.try_create_algo(def.CustomDef.CustomCase);
if(native != IntPtr.Zero)
{
AlgoTestNativeMethods.destroy_algo(native); //TODO, boolean
var child = new NativeAlgo(_sink, this.security_list, def);
hookup_child(child, this.security_list, def.Side, price, size, _myasof, order_key);
// var handle = this.hookup_child(child, security_list, def.Side, price, size, _myasof, null, null, order_key);
// _children.Add(handle);
}
}
break;
}
}
unsafe void on_native_update(byte* Update, ulong length, uint order_key)
{
byte[] arr = new byte[length];
Marshal.Copy((IntPtr)Update, arr, 0, (int)length);
api.orderman.Update upd = _updateparser.ParseFrom(arr);
var f = _children.FirstOrDefault(h => h.order_key == order_key);
if(f != null)
f.update(_lastmd.timestamp(), upd.Price, upd.Quantity);
}
unsafe void on_native_cancel(uint order_key)
{
var f = _children.FirstOrDefault(h => h.order_key == order_key);
if(f != null)
f.cancel(_lastmd.timestamp());
}
protected override void on_child_status(Handle child, OrderStatus stat)
{
_order_key_vs_state[child.order_key] = stat.state;
process_status(stat.state);
}
protected override void on_child_fill(Handle child, FillEntry fill)
{
AlgoTestNativeMethods.fill(_proxy, (uint)fill.order.order_id, fill.price, (uint)fill.size);
this.on_fill?.Invoke(fill);
}
unsafe void on_native_status(byte* OrderState, ulong length, uint order_key)
{
byte[] arr = new byte[length];
Marshal.Copy((IntPtr)OrderState, arr, 0, (int)length);
api.orderman.OrderState curr = _stateparser.ParseFrom(arr);
_order_key_vs_state[order_key] = curr;
process_status(curr);
}
private void process_status(api.orderman.OrderState curr)
{
bool done = is_completed();
api.orderman.OrderState aggstate = new api.orderman.OrderState
{
Status = done ? api.orderman.OrderStatus.Completed : curr.Status,
Price = curr.Price,
Quantity = curr.Quantity,
AvgPrice = _order_key_vs_state.Values.Average(x => x.Price),
FilledQuantity = _order_key_vs_state.Values.Sum(x => x.FilledQuantity),
LastChange = curr.LastChange,
LastMsg = curr.LastMsg,
LastPrice = curr.LastPrice
};
OrderStatus agg = new OrderStatus(_fake_order_for_status, aggstate);
agg.TransactTime = curr.LastChange ?? _lastmd?.SendingTime;
agg.SendingTime = curr.LastChange ?? _lastmd?.SendingTime;
this.on_status?.Invoke(agg);
}
unsafe void on_native_fill(byte* Fill, ulong length, uint order_key)
{
byte[] arr = new byte[length];
Marshal.Copy((IntPtr)Fill, arr, 0, (int)length);
api.orderman.Fill fill = _fillparser.ParseFrom(arr);
//this method is called as a result of us sending a fill down in AlgoTestNativeMethods.fill so we do nothing
}
~NativeAlgo()
{
AlgoTestNativeMethods.destroy_algo_driver(_proxy);
}
public override bool is_completed()
{
bool done = false;
if(_order_key_vs_state.Count > 0)
{
var astate = AlgoTestNativeMethods.algo_driver_state(_proxy);
done = AlgoTestNativeMethods.state_is_terminal(astate);
foreach(var st in _order_key_vs_state.Values)
done &= OrderStatus.is_terminal(st);
}
return done;
}
public override object report()
{
return $"Native";
}
protected override void do_update(Timestamp asof, double price, uint size = uint.MinValue)
{
base.do_update(asof, price, size);
AlgoTestNativeMethods.update_price(_proxy, price);
if(size != uint.MinValue)
{
AlgoTestNativeMethods.update_size(_proxy, size);
}
}
protected override void do_cancel(Timestamp asof)
{
base.do_cancel(asof);
AlgoTestNativeMethods.cancel(_proxy);
}
MarketDataIncrementalRefresh _lastmd;
protected override void on_book(string security_desc, uint security_key, co2.BookMessage current_book, co2.BookMessage working_book,
MarketDataIncrementalRefresh packet)
{
security_key = _def.SecurityKey; //to fake this up for the AlgoTestDriver
var book = current_book.ToByteArray();
AlgoTestNativeMethods.update_book(_proxy, security_key, book, book.Length);
advance_time(packet);
}
protected override void on_trades(string security_desc, uint security_key, IEnumerable<co2.TradeMessage> trades,
MarketDataIncrementalRefresh packet)
{
security_key = _def.SecurityKey;
foreach(var trade in trades)
{
var tr = trade.ToByteArray();
AlgoTestNativeMethods.update_ticker(_proxy, security_key, tr, tr.Length);
}
advance_time(packet);
}
void advance_time(MarketDataIncrementalRefresh packet)
{
if (_lastmd != null)
{
var dt = packet.timestamp() - _lastmd.timestamp();
if (dt.Seconds >= 0 && dt.Nanos > 0)
{
ulong us = (ulong)dt.Seconds * 1000_000ul + ((ulong)dt.Nanos / 1000ul);
AlgoTestNativeMethods.advance_time(_proxy, us, 1);
}
}
_lastmd = packet;
}
}
}
@@ -1,22 +0,0 @@
using System;
using bts.api;
using Google.Protobuf.WellKnownTypes;
using MathNet.Numerics.Statistics;
namespace bts.history
{
public class NullAlgo : AlgoBase
{
public NullAlgo(IOrderSink sink, string[] security_list) : base(sink, security_list) { }
public override bool is_completed() => true;
public override object report() { return string.Empty; }
protected override void do_launch(string[] security_list, Side side, double price, uint size, Timestamp asof, ulong order_key) { }
protected override void do_update(Timestamp asof, double price, uint size = uint.MinValue) { }
protected override void do_cancel(Timestamp asof) { }
}
}
@@ -1,324 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Google.Protobuf.WellKnownTypes;
using MathNet.Numerics.Statistics;
using mbts.co2;
namespace bts.history
{
public class SpreaderAlgo<Child, Hedge> : CompositeHedgeAlgo<Child, Hedge>
where Child : AlgoBase
where Hedge : AlgoBase
{
enum AlgoState
{
Begin, Quoting, Done
}
//algo state
string[] _security_list;
AlgoState _state;
double _myprice;
uint _mysize;
bool _sizeupdate;
api.Side _myside;
SortedList<string, co2.BookMessage> _current_book = new SortedList<string, co2.BookMessage>();
OrderStatus _buystatus, _sellstatus;
Handle _buychild;
Handle _sellchild;
OrderEntry _fake_order_for_status;
private MarketDataIncrementalRefresh _packet;
public SpreaderAlgo(IOrderSink sink, string[] security_list) : base(sink, security_list) { }
//algo parameters
public double profit_ticks { get; set; } = 0.0;
public double[] tick_size { get; set; }
public double[] hedge_factors { get; set; }
public double[] price_factors { get; set; }
public double lean_factor { get; set; } = 1.0;
public bool accumulate_delta { get; set; } = false;
public bool dont_cross { get; set; } = false;
public bool wait_for_opposite_side_to_continue { get; set; } = false;
Dictionary<string, double> _tick_size = new Dictionary<string, double>();
Dictionary<string, double> _hedge_factors = new Dictionary<string, double>();
Dictionary<string, double> _price_factors = new Dictionary<string, double>();
Dictionary<string, double> _delta = new Dictionary<string, double>();
string _quote_leg;
readonly List<bool> _sides = new List<bool>();
protected override void do_launch(string[] security_list, api.Side side, double price, uint size, Timestamp asof, ulong order_key)
{
_security_list = security_list;
for(int i = 0; i < _security_list.Length; i++)
{
_current_book[_security_list[i]] = null;
_tick_size[_security_list[i]] = tick_size[i];
_hedge_factors[_security_list[i]] = hedge_factors[i];
if(price_factors == null || price_factors.Length < _security_list.Length)
_price_factors[_security_list[i]] = hedge_factors[i];
else
_price_factors[_security_list[i]] = price_factors[i];
_delta[_security_list[i]] = 0.0;
_quote_leg = _security_list[i]; //last
}
_state = AlgoState.Begin;
_myprice = price;
_mysize = size;
_myside = side;
_fake_order_for_status = new OrderEntry(asof, order_key, string.Join("_", security_list.Select(x=>x)),
side, price, size, null, null, "SpreaderAlgo");
if (_myside == api.Side.Buy)
_sides.Add(false);
else if (_myside == api.Side.Sell)
_sides.Add(true);
else
{
_sides.Add(false);
_sides.Add(true);
}
}
protected override void do_update(Timestamp asof, double price, uint size = uint.MinValue)
{
_myprice = price;
if(size > uint.MinValue)
{
_mysize = size;
_sizeupdate = true;
}
}
public override bool is_completed()
{
return base.is_completed() && _state == AlgoState.Done;
}
public override object report()
{
var b = base.report();
string qtleg = _security_list.Last();
return b;
}
protected override void on_child_status(Handle child, OrderStatus stat)
{
if(stat.side == api.Side.Buy && (_buychild?.Equals(child) ?? false))
{
_buystatus = stat;
if(stat.is_terminal() && !this.wait_for_opposite_side_to_continue)
_sellchild?.cancel(_buystatus.SendingTime);
this.on_status?.Invoke(_buystatus);
}
else if(stat.side == api.Side.Sell && (_sellchild?.Equals(child) ?? false))
{
_sellstatus = stat;
if(stat.is_terminal() && !this.wait_for_opposite_side_to_continue)
_buychild?.cancel(_sellstatus.SendingTime);
this.on_status?.Invoke(_sellstatus);
}
//hedges are looked after elsewhere
if( (_buystatus?.is_terminal() ?? true) && (_sellstatus?.is_terminal() ?? true) )
_state = AlgoState.Done;
send_my_status(stat);
}
private void send_my_status(OrderStatus curr)
{
bool done = is_completed();
api.orderman.OrderState aggstate = new api.orderman.OrderState
{
Status = done ? api.orderman.OrderStatus.Completed : api.orderman.OrderStatus.Working,
Price = _myprice,
Quantity = _mysize,
AvgPrice = 0.0,
FilledQuantity = done ? _mysize : 0,
LastChange = curr.TransactTime,
LastMsg = curr.state.LastMsg,
LastPrice = curr.state.LastPrice
};
uint bqty = _buystatus?.state.FilledQuantity ?? 0;
uint sqty = _sellstatus?.state.FilledQuantity ?? 0;
aggstate.FilledQuantity = (uint) ( (bqty + sqty) / this._hedge_factors[_quote_leg] );
OrderStatus agg = new OrderStatus(_fake_order_for_status, aggstate);
agg.TransactTime = curr.TransactTime ?? _fake_order_for_status.last_change;
agg.SendingTime = curr.SendingTime ?? _fake_order_for_status.last_change;
this.on_status?.Invoke(agg);
}
protected override void on_child_fill(Handle child, FillEntry fill)
{
var ff = factor_side(this._hedge_factors[_quote_leg]);
bool invert = ff != fill.order.side;
foreach(var sec in _security_list)
{
if(sec == _quote_leg)
continue;
var hedgeside = factor_side(this._hedge_factors[sec], invert);
var ratio = Math.Abs(this._hedge_factors[sec] / this._hedge_factors[_quote_leg]);
double price = (hedgeside == api.Side.Buy) ? _current_book[sec].ask_at(0) : _current_book[sec].bid_at(0);
uint hedgesize_available = (hedgeside == api.Side.Buy) ? _current_book[sec].asksize_at(0) : _current_book[sec].bidsize_at(0);
uint size = (uint)(fill.size * ratio);
if(this.accumulate_delta)
{
_delta[sec] += fill.size * ratio - size;
if(_delta[sec] > 1.0)
{
var usize = (uint)_delta[sec];
size += usize;
_delta[sec] -= usize;
}
}
if(size > 0)
send_hedge(sec, hedgeside, price, size, fill.TransactTime, handle_hedge_fill, handle_hedge_status);
else
fill.tag = (fill.tag ?? "") + $"SmallHedge: {price.ToString("0")} {hedgesize_available}";
}
}
private void handle_hedge_status(Handle handle, OrderStatus stat)
{
Log.assert(true);
}
private void handle_hedge_fill(Handle handle, FillEntry fill)
{
Log.assert(true);
}
api.Side factor_side(double mult, bool invert = false)
{
api.Side sd = api.Side.Undefined;
if(mult >= 0.0)
sd = api.Side.Buy;
else
sd = api.Side.Sell;
if(invert)
sd = Utils.opposite_side(sd);
return sd;
}
static double round_tick_up(double input, double tick)
{
return Math.Ceiling(input / tick) * tick;
}
static double round_tick_dn(double input, double tick)
{
return Math.Floor(input / tick) * tick;
}
protected override void on_book(string security_desc, uint security_key, co2.BookMessage current_book, co2.BookMessage working_book,
MarketDataIncrementalRefresh packet)
{
_packet = packet;
_current_book[security_desc] = current_book;
var look_book = _current_book;
switch (_state)
{
case AlgoState.Begin:
{
if( !_current_book.Values.Any(x => x == null) )
_state = AlgoState.Quoting;
}
break;
case AlgoState.Quoting:
{
double qtbid = _myprice - profit_ticks; uint szbid = 0;
double qtask = _myprice + profit_ticks; uint szask = 0;
foreach(var sec in _security_list)
{
var book = look_book[sec];
if (sec != _quote_leg)
{
var hedge_sidebid = factor_side(this._hedge_factors[sec], false);
var hedge_sideask = factor_side(this._hedge_factors[sec], true);
var cross_sidebid = Utils.opposite_side(hedge_sidebid);
var cross_sideask = Utils.opposite_side(hedge_sideask);
var legbid = this._price_factors[sec] * book.side_at(cross_sidebid, 0);
var legask = this._price_factors[sec] * book.side_at(cross_sideask, 0);
qtbid -= legbid;
qtask -= legask;
var hratio = Math.Abs(this._hedge_factors[sec] / this._hedge_factors[_quote_leg]);
hratio *= this.lean_factor;
var quote_size = (uint) (_mysize * Math.Abs(this._hedge_factors[_quote_leg]));
szbid = Math.Min(quote_size, (uint) (book.sidesize_at(cross_sidebid, 0) / hratio));
szask = Math.Min(quote_size, (uint) (book.sidesize_at(cross_sideask, 0) / hratio));
}
else
{
qtbid /= this._price_factors[_quote_leg];
qtask /= this._price_factors[_quote_leg];
double temp = qtbid;
qtbid = qtask;
qtask = temp;
double tick = _tick_size[sec];
qtbid = round_tick_dn(qtbid, tick);
qtask = round_tick_up(qtask, tick);
if (this.dont_cross)
{
qtbid = Math.Min(qtbid, book.bid_at(0));
qtask = Math.Max(qtask, book.ask_at(0));
}
}
}
foreach (var invert in _sides)
{
api.Side quoteside = factor_side(this._hedge_factors[_quote_leg], invert);
if(quoteside == api.Side.Buy && szbid > 0 && (_buystatus?.state?.Price != qtbid || _sizeupdate) && (!_buystatus?.is_terminal() ?? true))
quote_function(packet, _quote_leg, quoteside, qtbid, szbid);
else if(quoteside == api.Side.Sell && szask > 0 && (_sellstatus?.state?.Price != qtask || _sizeupdate) && (!_sellstatus?.is_terminal() ?? true))
quote_function(packet, _quote_leg, quoteside, qtask, szask);
}
}
break;
case AlgoState.Done:
break;
default:
Log.assert(false, "invalid algo state");
break;
}
}
void quote_function(MarketDataIncrementalRefresh packet, string qtleg,
api.Side quoteside, double qt, uint sz)
{
if (quoteside == api.Side.Buy)
{
if (_buychild == null)
{
_buychild = this.create<Child>();
_buychild.launch(new[] { qtleg }, quoteside, qt, sz, packet.timestamp());
}
else if(_buystatus != null)
{
_buychild.update(packet.timestamp(), qt, sz);
_sizeupdate = false;
}
}
else
{
if (_sellchild == null)
{
_sellchild = this.create<Child>();
_sellchild.launch(new[] { qtleg }, quoteside, qt, sz, packet.timestamp());
}
else if (_sellstatus != null)
{
_sellchild.update(packet.timestamp(), qt, sz);
_sizeupdate = false;
}
}
}
}
}
@@ -1,106 +0,0 @@
using System;
using System.Collections.Generic;
using Google.Protobuf.WellKnownTypes;
namespace bts.history
{
public class StackerAlgo<Child> : CompositeAlgo<Child>
where Child : AlgoBase
{
Handle[] _handles;
Dictionary<Handle, OrderStatus> _status = new Dictionary<Handle, OrderStatus>();
api.Side _myside;
double _myprice;
public StackerAlgo(IOrderSink sink, string[] security_list) : base(sink, security_list) { }
public double[] tick_size { get; set; }
public uint stack_length { get; set; } = 2;
double _tick_size;
protected override void do_launch(string[] security_list, api.Side side, double price, uint size, Timestamp asof, ulong order_key)
{
_myside = side;
_myprice = price;
_handles = new Handle[this.stack_length];
for (int i = 0; i < this.security_list.Length; i++)
{
if(this.security_list[i] == security_list[0])
_tick_size = tick_size[i];
}
if(this.stack_length <= 1)
throw new NotSupportedException("StackerAlgo must have stack_length > 1");
for(int i = 0; i < this.stack_length; i++)
{
if(side == api.Side.Buy)
{
var h = _handles[i] = this.create<Child>();
h.launch(security_list, side, price - i * _tick_size, size, asof);
}
else
{
var h = _handles[i] = this.create<Child>();
h.launch(security_list, side, price + i * _tick_size, size, asof);
}
}
}
protected override void do_update(Timestamp asof, double price, uint size = uint.MinValue)
{
bool better = (_myside == api.Side.Buy ? price > _myprice : price < _myprice);
if(price == _myprice)
{
Log.Testing.error("update of StackerAlgo for same price");
return;
}
double px = _myprice;
if(better)
{
double tick = (_myside == api.Side.Buy ? _tick_size : -_tick_size);
while(Math.Abs(price - px) > _tick_size / 10.0)
{
px += tick;
var mover = _handles[_handles.Length - 1];
for(int j = _handles.Length-1; j >= 1; j--)
_handles[j] = _handles[j-1];
_handles[0] = mover;
mover.update(asof, px, size);
}
var stat0 = _status[_handles[0]];
var stat1 = _status[_handles[1]];
Log.assert(stat0.state.Price == price);
Log.assert(stat1.state.Price == price - tick);
}
else
{
double tick = (_myside == api.Side.Buy ? -_tick_size : _tick_size);
while (Math.Abs(price - px) > _tick_size / 10.0)
{
var mover = _handles[0];
for (int j = 0; j < _handles.Length-1; j++)
_handles[j] = _handles[j+1];
_handles[_handles.Length-1] = mover;
double endprice = px + tick * (_handles.Length);
mover.update(asof, endprice, size);
px += tick;
}
var stat0 = _status[_handles[0]];
var stat1 = _status[_handles[1]];
Log.assert(stat0.state.Price == price);
Log.assert(stat1.state.Price == price + tick);
on_child_status(_handles[0], stat0); //to force status update since this order didn't actually get updated
}
_myprice = px;
}
protected override void on_child_status(Handle child, OrderStatus stat)
{
_status[child] = stat;
if(_handles[0]?.Equals(child) ?? false)
{
this.on_status?.Invoke(stat);
}
}
}
}
@@ -1,96 +0,0 @@
using System;
using Google.Protobuf.WellKnownTypes;
using MathNet.Numerics.Statistics;
using mbts.co2;
namespace bts.history
{
public class TopAlgo<Child> : CompositeAlgo<Child>
where Child : AlgoBase
{
enum AlgoState
{
WaitingToCancel, CancelRequested, Done
}
//algo state
AlgoState _state;
OrderStatus _status;
api.Side _myside;
uint _mysize;
co2.BookMessage _currentbook;
int _topcount;
public TopAlgo(IOrderSink sink, string[] security_list) : base(sink, security_list) { }
//algo parameters
public double top_factor { get; set; } = 1.0;
public uint top_quantity { get; set; } = 0;
protected override void do_launch(string[] security_list, api.Side side, double price, uint size, Timestamp asof, ulong order_key)
{
_state = AlgoState.WaitingToCancel;
_myside = side;
_mysize = size;
_child = this.create<Child>();
_child.launch(security_list, side, price, size, asof);
}
public override bool is_completed()
{
return _state == AlgoState.Done;
}
public override object report()
{
var b = base.report();
return $"{b} Cancels { _topcount }";
}
protected override void on_child_status(Handle child, OrderStatus stat)
{
_status = stat;
if (stat.is_terminal())
_state = AlgoState.Done;
this.on_status?.Invoke(_status);
}
protected override void on_book(string security_desc, uint security_key, co2.BookMessage current_book, co2.BookMessage working_book,
MarketDataIncrementalRefresh packet)
{
_currentbook = current_book;
switch (_state)
{
case AlgoState.WaitingToCancel:
{
bool top = _currentbook.side_at(_myside, 0) == _status?.state?.Price;
var thresh = (this.top_quantity > 0 ? this.top_quantity : this.top_factor * _mysize);
if(top && _currentbook.sidesize_at(_myside, 0) < thresh)
{
cancel_top_function(packet,
security_desc, _currentbook.side_at(_myside, 0));
_state = AlgoState.CancelRequested;
_topcount++;
}
}
break;
case AlgoState.CancelRequested:
break;
case AlgoState.Done:
break;
default:
Log.assert(false, "invalid algo state");
break;
}
}
void cancel_top_function(MarketDataIncrementalRefresh packet, string security_desc, object param)
{
Log.Testing.info("cancel_top_function ");
_child.cancel(packet.timestamp());
_state = AlgoState.Done;
}
}
}
@@ -1,107 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using bts.api;
using Google.Protobuf.WellKnownTypes;
using MathNet.Numerics.Statistics;
namespace bts.history
{
public class JoinCoverLean : CoverAlgo<JoinAlgo<TopAlgo<LimitOrder>>, LeanAlgo<LimitOrder>>
{
public JoinCoverLean(IOrderSink sink, string[] security_list)
: base(sink, security_list)
{
}
}
public class PegCoverLean : CoverAlgo<JoinAlgo<TopAlgo<LimitOrder>>, LeanAlgo<LimitOrder>>
{
public PegCoverLean(IOrderSink sink, string[] security_list)
: base(sink, security_list)
{
this.set_param(nameof(JoinAlgo<LimitOrder>.initial_pile), true.ToString());
}
}
public class Spreader : SpreaderAlgo<LimitOrder, LeanAlgo<LimitOrder>>
{
public Spreader(IOrderSink sink, string[] security_list)
: base(sink, security_list)
{
}
}
public class StackSpreader : SpreaderAlgo<StackerAlgo<LimitOrder>, LeanAlgo<LimitOrder>>
{
public StackSpreader(IOrderSink sink, string[] security_list)
: base(sink, security_list)
{
}
}
//to differentiate types for factory
public class HedgeSpreader<Child, Hedge> : SpreaderAlgo<Child, Hedge>
where Child : AlgoBase
where Hedge : AlgoBase
{
public HedgeSpreader(IOrderSink sink, string[] security_list)
: base(sink, security_list)
{
}
}
public class DualSpreader : CompletionCoverAlgo< SpreaderAlgo<LimitOrder, LeanAlgo<LimitOrder>>, HedgeSpreader<LimitOrder, LeanAlgo<LimitOrder>> >
{
public DualSpreader(IOrderSink sink, string[] security_list)
: base(sink, security_list)
{
}
}
public class TWAP : NativeAlgo
{
public TWAP(IOrderSink sink, string[] security_list)
: base(sink, security_list, build_def())
{
}
static api.orderman.OrderDefinition build_def()
{
api.orderman.OrderDefinition def = new api.orderman.OrderDefinition();
def.SecurityKey = 51880u;
def.Side = api.Side.Buy;
def.CustomDef = new api.orderman.CustomOrderDefinition { Twap = new api.orderman.TWAPOrderDefinition() };
def.CustomDef.Twap.Duration = new api.orderman.TimeDuration() { DurationInMinutes = 6, IntervalInSeconds = 10 } ;
def.CustomDef.Twap.Aggression = new api.orderman.OrderAggression() { };
def.CustomDef.Twap.TacticalChild = new api.orderman.CustomOrderDefinition
{
Peg = new api.orderman.PegOrderDefinition()
{
Child = new api.orderman.CustomOrderDefinition { Limit = new api.orderman.LimitOrderDefinition() } ,
TickOffset = 0,
}
};
def.CustomDef.Twap.AggressiveChild = new api.orderman.CustomOrderDefinition
{
Peg = new api.orderman.PegOrderDefinition()
{
Child = new api.orderman.CustomOrderDefinition
{
Lean = new api.orderman.LeanOrderDefinition()
{
Child = new api.orderman.CustomOrderDefinition { Limit = new api.orderman.LimitOrderDefinition() },
CrossThreshold = new spark.QuantityMeasure { Ratio = 3.0 },
TradeTowardBehavior = api.orderman.LeanOrderDefinition.Types.OnToward.NoChange,
MaxChaseTicks = 10,
}
},
TickOffset = 0,
}
};
return def;
}
}
}
Loaded 100 of 277 files, more files were not shown because too many files have changed in this diff. Show more