Compare commits

..
45 Commits
Author SHA1 Message Date
Kevin Darby 25805cf675 Merge branch 'master' of bitbucket.org:bluetradesys/spark into fix 2020-01-08 17:22:14 -05:00
Kevin Darby 1621ad03bf Merge branch 'master' of bitbucket.org:bluetradesys/spark into fix 2019-10-13 14:09:45 -04:00
Kevin Darby 193f248f06 merge deleted some of my files 2019-10-07 17:40:01 -04:00
Kevin Darby 5212fb272e Merge branch 'master' of bitbucket.org:bluetradesys/spark into fix 2019-10-07 17:27:12 -04:00
Kevin Darby 6772c77e01 rudimentary fix orders seem to work 2019-10-07 17:18:20 -04:00
Kevin Darby 95c589f594 hooking up to run this fix server 2019-09-30 15:00:30 -04:00
Kevin Darby 699c7c5bfe Merge branch 'master' of bitbucket.org:bluetradesys/spark into fix 2019-09-30 12:02:13 -04:00
Kevin Darby 7de82b5685 Merge branch 'master' of bitbucket.org:bluetradesys/spark into fix 2019-09-30 11:45:44 -04:00
Kevin Darby a8e9d0d7d8 ordersession and dropcopy session code complete for native orders, time to debug 2019-09-27 18:21:35 -04:00
Kevin Darby d078e73179 order session 2019-09-27 17:58:36 -04:00
Kevin Darby 4351d6e66a drop copy session code complete 2019-09-27 17:04:42 -04:00
Kevin Darby 9850d6bde0 rx-cpp requires concurrent use with prescription medicine 2019-09-27 14:29:22 -04:00
Kevin Darby d23a072ad6 rx 2019-09-26 18:27:41 -04:00
Kevin Darby 6ef0808f49 never thought I'd use rxcpp...it's truly terrible; I feel physical pain 2019-09-26 18:16:48 -04:00
Kevin Darby e1c2d8aaaf it builds, ship it 2019-09-26 12:33:42 -04:00
Kevin Darby 719fd03063 nothing builds 2019-09-26 11:45:08 -04:00
Kevin Darby d436dae7cd more fix 2019-09-24 18:22:09 -04:00
Kevin Darby f66004b465 fix port 2019-09-24 14:37:30 -04:00
Kevin Darby aa8a56787b fix fix fix 2019-09-23 18:16:05 -04:00
Kevin Darby 35a69396f1 Merge branch 'master' of bitbucket.org:bluetradesys/spark into fix 2019-09-23 17:08:56 -04:00
Kevin Darby ddfb6d1105 update externals 2019-09-23 17:03:49 -04:00
Kevin Darby 005c0f9a5d c++ fix 2019-09-23 16:59:39 -04:00
Kevin Darby 57af89b628 Merge branch 'master' of bitbucket.org:bluetradesys/spark into fix 2019-08-28 16:47:20 -04:00
Kevin Darby feab3cbb89 Merge branch 'master' of bitbucket.org:bluetradesys/spark into fix 2019-01-22 16:10:16 -05:00
Kevin Darby 1f7c1be194 Merge branch 'master' of bitbucket.org:bluetradesys/spark into fix 2018-12-28 13:51:59 -05:00
Kevin Darby f78f18b3b4 Merge branch 'master' of bitbucket.org:bluetradesys/spark into fix 2018-12-20 16:20:19 -05:00
Kevin Darby 6e7fa91718 ready for testing 2018-12-14 10:39:34 -05:00
Kevin Darby 8cac406547 fix error handling 2018-12-12 17:33:25 -05:00
Kevin Darby 0d83f28cbc fix lives 2018-12-12 14:26:03 -05:00
Kevin Darby 941f4bf837 Merge branch 'cleanup_mdclient' of bitbucket.org:bluetradesys/spark into fix 2018-12-11 23:05:35 -05:00
Kevin Darby 8bbe9cfd98 Merge branch 'master' of bitbucket.org:bluetradesys/spark into sdk_doc2 2018-12-06 12:56:02 -05:00
Kevin Darby ba633532eb hit a wall here with MDClient, going to refactor 2018-12-06 12:55:21 -05:00
Kevin Darby 7bf50415ca nearly ready for testing 2018-12-05 17:55:06 -05:00
Kevin Darby edbaa9c435 looks like we have dropcopy 2018-12-05 15:35:49 -05:00
Kevin Darby 7789f39c9d handle some messages 2018-12-04 18:20:23 -05:00
Kevin Darby 6e188b4f73 shaping up 2018-12-04 16:37:41 -05:00
Kevin Darby 33e8ff58c5 Merge branch 'master' of bitbucket.org:bluetradesys/spark into sdk_doc2 2018-12-04 09:42:30 -05:00
Kevin Darby 24ae03a9f8 access permissions api so fix session can report fills and orders 2018-12-03 18:19:20 -05:00
Kevin Darby 5fe0335e1a Merge branch 'master' of bitbucket.org:bluetradesys/spark into sdk_doc2 2018-12-03 17:02:34 -05:00
Kevin Darby 6cbf707094 Merge branch 'sdk_doc' of bitbucket.org:bluetradesys/spark into sdk_doc2 2018-12-03 16:06:58 -05:00
Kevin Darby 7e4ad55d9d established a session 2018-12-03 15:32:45 -05:00
Kevin Darby 35a0074014 bts fix44 adapter 2018-12-03 14:49:35 -05:00
Kevin Darby b8dd5c119d Merge branch 'sdk_doc' of bitbucket.org:bluetradesys/spark into sdk_doc2 2018-12-03 10:41:34 -05:00
Kevin Darby 8ada73aa64 Merge branch 'sdk_doc' of bitbucket.org:bluetradesys/spark into sdk_doc2 2018-11-30 18:37:39 -05:00
Kevin Darby a16ff30873 lets see how hard this is 2018-11-30 18:32:51 -05:00
134 changed files with 92549 additions and 1360 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",
+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 -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
+++
@@ -71,12 +71,12 @@ The first step is to start the spark_sdk Docker container with the examples dire
Windows Command Prompt:
{% clipable() %}
docker run --rm -it -v %CD%:/examples -u bts -w /examples --shm-size 2048m --name spark_sdk -h spark_sdk --cap-add=SYS_PTRACE --security-opt seccomp=unconfined -p 9000:9000 -p 9001:9001 spark_sdk bash
docker run --rm -it -v %CD%:/examples -u bts -w /examples --shm-size 1024m --name spark_sdk -h spark_sdk --cap-add=SYS_PTRACE --security-opt seccomp=unconfined -p 9000:9000 -p 9001:9001 spark_sdk bash
{% end %}
**Powershell** / Linux / Mac:
{% clipable() %}
docker run --rm -it -v ${PWD}:/examples -u bts -w /examples --shm-size 2048m --name spark_sdk -h spark_sdk --cap-add=SYS_PTRACE --security-opt seccomp=unconfined -p 9000:9000 -p 9001:9001 spark_sdk bash
docker run --rm -it -v ${PWD}:/examples -u bts -w /examples --shm-size 1024m --name spark_sdk -h spark_sdk --cap-add=SYS_PTRACE --security-opt seccomp=unconfined -p 9000:9000 -p 9001:9001 spark_sdk bash
{% end %}
### Attach
@@ -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 %}
+1 -1
View File
@@ -1 +1 @@
set(sources /spark/doc/user/build.sh;content/_index.md;content/bts_spark/Glossary/_index.md;content/bts_spark/Help/_index.md;content/bts_spark/Help/about_spark.png;content/bts_spark/Help/image39.png;content/bts_spark/Help/image58.png;content/bts_spark/Launcher/_index.md;content/bts_spark/Launcher/image38.png;content/bts_spark/Launcher/image68.png;content/bts_spark/Logging-In-to-the-System/_index.md;content/bts_spark/Logging-In-to-the-System/image3.png;content/bts_spark/Logging-In-to-the-System/image64.png;content/bts_spark/Market/_index.md;content/bts_spark/Market/change_securities.png;content/bts_spark/Market/image11.png;content/bts_spark/Market/image14.png;content/bts_spark/Market/image20.png;content/bts_spark/Market/image21.png;content/bts_spark/Market/image23.png;content/bts_spark/Market/image24.png;content/bts_spark/Market/image34.png;content/bts_spark/Market/image49.png;content/bts_spark/Market/image53.png;content/bts_spark/Market/image66.png;content/bts_spark/Market/image69.png;content/bts_spark/Market/market_view.png;content/bts_spark/Market/settings_icon.png;content/bts_spark/Market/time_and_sales.png;content/bts_spark/My-Windows/_index.md;content/bts_spark/My-Windows/image15.png;content/bts_spark/My-Windows/image16.png;content/bts_spark/My-Windows/image37.png;content/bts_spark/Settings/_index.md;content/bts_spark/Settings/image51.png;content/bts_spark/Settings/image9.png;content/bts_spark/Spreader/_index.md;content/bts_spark/Spreader/image10.png;content/bts_spark/Spreader/image13.png;content/bts_spark/Spreader/image18.png;content/bts_spark/Spreader/image19.png;content/bts_spark/Spreader/image28.png;content/bts_spark/Spreader/image29.png;content/bts_spark/Spreader/image31.png;content/bts_spark/Spreader/image35.png;content/bts_spark/Spreader/image40.png;content/bts_spark/Spreader/image43.png;content/bts_spark/Spreader/image54.png;content/bts_spark/Spreader/image55.png;content/bts_spark/Spreader/image56.png;content/bts_spark/Spreader/image6.png;content/bts_spark/Spreader/image7.png;content/bts_spark/Spreader/image70.png;content/bts_spark/Spreader/image72.png;content/bts_spark/Spreader/image8.png;content/bts_spark/Trading/OrderTypes/index.md;content/bts_spark/Trading/_index.md;content/bts_spark/Trading/algo_studio.png;content/bts_spark/Trading/collapse_all_icon.png;content/bts_spark/Trading/cover_algo_control.png;content/bts_spark/Trading/expand_all_icon.png;content/bts_spark/Trading/image1.png;content/bts_spark/Trading/image17.png;content/bts_spark/Trading/image2.png;content/bts_spark/Trading/image25.png;content/bts_spark/Trading/image27.png;content/bts_spark/Trading/image33.png;content/bts_spark/Trading/image42.png;content/bts_spark/Trading/image44.png;content/bts_spark/Trading/image47.png;content/bts_spark/Trading/image48.png;content/bts_spark/Trading/image5.png;content/bts_spark/Trading/image50.png;content/bts_spark/Trading/image52.png;content/bts_spark/Trading/image57.png;content/bts_spark/Trading/image59.png;content/bts_spark/Trading/image60.png;content/bts_spark/Trading/image61.png;content/bts_spark/Trading/image62.png;content/bts_spark/Trading/image73.png;content/bts_spark/Trading/image74.png;content/bts_spark/Trading/join_algo_control.png;content/bts_spark/Trading/ladder.png;content/bts_spark/Trading/ladder_badges.png;content/bts_spark/Trading/ladder_main_part.png;content/bts_spark/Trading/lean_algo_control.png;content/bts_spark/Trading/mini_orderbook.png;content/bts_spark/Trading/oco_algo_control.png;content/bts_spark/Trading/offset_algo_control.png;content/bts_spark/Trading/pnl_calculation.png;content/bts_spark/Trading/pnl_window.png;content/bts_spark/Trading/recreate_icon.png;content/bts_spark/Trading/settings_icon.png;content/bts_spark/Trading/spark_menu_order_book.png;content/bts_spark/Trading/top_algo_control.png;content/bts_spark/Trading/trigger_algo_control.png;content/bts_spark/_index.md;content/release_notes/_index.md;content/system_requirements/_index.md;static/book.js;static/favicon.ico;static/image.js;templates/index.html;templates/page.html;templates/section.html;templates/shortcodes/back_button.html)
set(sources /home/ppinto/Dropbox/bts/spark/doc/user/build.sh;content/_index.md;content/bts_spark/Glossary/_index.md;content/bts_spark/Help/_index.md;content/bts_spark/Help/about_spark.png;content/bts_spark/Help/image39.png;content/bts_spark/Help/image58.png;content/bts_spark/Launcher/_index.md;content/bts_spark/Launcher/image38.png;content/bts_spark/Launcher/image68.png;content/bts_spark/Logging-In-to-the-System/_index.md;content/bts_spark/Logging-In-to-the-System/image3.png;content/bts_spark/Logging-In-to-the-System/image64.png;content/bts_spark/Market/_index.md;content/bts_spark/Market/change_securities.png;content/bts_spark/Market/image11.png;content/bts_spark/Market/image14.png;content/bts_spark/Market/image20.png;content/bts_spark/Market/image21.png;content/bts_spark/Market/image23.png;content/bts_spark/Market/image24.png;content/bts_spark/Market/image34.png;content/bts_spark/Market/image49.png;content/bts_spark/Market/image53.png;content/bts_spark/Market/image66.png;content/bts_spark/Market/image69.png;content/bts_spark/Market/market_view.png;content/bts_spark/Market/settings_icon.png;content/bts_spark/Market/time_and_sales.png;content/bts_spark/My-Windows/_index.md;content/bts_spark/My-Windows/image15.png;content/bts_spark/My-Windows/image16.png;content/bts_spark/My-Windows/image37.png;content/bts_spark/Settings/_index.md;content/bts_spark/Settings/image51.png;content/bts_spark/Settings/image9.png;content/bts_spark/Spreader/_index.md;content/bts_spark/Spreader/image10.png;content/bts_spark/Spreader/image13.png;content/bts_spark/Spreader/image18.png;content/bts_spark/Spreader/image19.png;content/bts_spark/Spreader/image28.png;content/bts_spark/Spreader/image29.png;content/bts_spark/Spreader/image31.png;content/bts_spark/Spreader/image35.png;content/bts_spark/Spreader/image40.png;content/bts_spark/Spreader/image43.png;content/bts_spark/Spreader/image54.png;content/bts_spark/Spreader/image55.png;content/bts_spark/Spreader/image56.png;content/bts_spark/Spreader/image6.png;content/bts_spark/Spreader/image7.png;content/bts_spark/Spreader/image70.png;content/bts_spark/Spreader/image72.png;content/bts_spark/Spreader/image8.png;content/bts_spark/Trading/OrderTypes/index.md;content/bts_spark/Trading/_index.md;content/bts_spark/Trading/algo_studio.png;content/bts_spark/Trading/collapse_all_icon.png;content/bts_spark/Trading/cover_algo_control.png;content/bts_spark/Trading/expand_all_icon.png;content/bts_spark/Trading/image1.png;content/bts_spark/Trading/image17.png;content/bts_spark/Trading/image2.png;content/bts_spark/Trading/image25.png;content/bts_spark/Trading/image27.png;content/bts_spark/Trading/image33.png;content/bts_spark/Trading/image42.png;content/bts_spark/Trading/image44.png;content/bts_spark/Trading/image47.png;content/bts_spark/Trading/image48.png;content/bts_spark/Trading/image5.png;content/bts_spark/Trading/image50.png;content/bts_spark/Trading/image52.png;content/bts_spark/Trading/image57.png;content/bts_spark/Trading/image59.png;content/bts_spark/Trading/image60.png;content/bts_spark/Trading/image61.png;content/bts_spark/Trading/image62.png;content/bts_spark/Trading/image73.png;content/bts_spark/Trading/image74.png;content/bts_spark/Trading/join_algo_control.png;content/bts_spark/Trading/ladder.png;content/bts_spark/Trading/ladder_badges.png;content/bts_spark/Trading/ladder_main_part.png;content/bts_spark/Trading/lean_algo_control.png;content/bts_spark/Trading/mini_orderbook.png;content/bts_spark/Trading/oco_algo_control.png;content/bts_spark/Trading/offset_algo_control.png;content/bts_spark/Trading/pnl_calculation.png;content/bts_spark/Trading/pnl_window.png;content/bts_spark/Trading/recreate_icon.png;content/bts_spark/Trading/settings_icon.png;content/bts_spark/Trading/spark_menu_order_book.png;content/bts_spark/Trading/top_algo_control.png;content/bts_spark/Trading/trigger_algo_control.png;content/bts_spark/_index.md;content/release_notes/_index.md;content/system_requirements/_index.md;static/book.js;static/favicon.ico;static/image.js;templates/index.html;templates/page.html;templates/section.html;templates/shortcodes/back_button.html)
-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
+22
View File
@@ -23,6 +23,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "spark_test", "src\client\sp
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "spark_excel", "src\client\spark_excel\spark_excel.csproj", "{BE9F27C3-B583-47DF-95FA-1F8BBC89DCCB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "spark_fix", "src\client\spark_fix\spark_fix.csproj", "{D8031C13-7BEA-430A-BB60-40927D15CFC3}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -219,6 +221,26 @@ Global
{BE9F27C3-B583-47DF-95FA-1F8BBC89DCCB}.RelWithDebInfo|x64.Build.0 = Release|x64
{BE9F27C3-B583-47DF-95FA-1F8BBC89DCCB}.RelWithDebInfo|x86.ActiveCfg = Release|x64
{BE9F27C3-B583-47DF-95FA-1F8BBC89DCCB}.RelWithDebInfo|x86.Build.0 = Release|x64
{D8031C13-7BEA-430A-BB60-40927D15CFC3}.Debug|Any CPU.ActiveCfg = Debug|x64
{D8031C13-7BEA-430A-BB60-40927D15CFC3}.Debug|x64.ActiveCfg = Debug|x64
{D8031C13-7BEA-430A-BB60-40927D15CFC3}.Debug|x64.Build.0 = Debug|x64
{D8031C13-7BEA-430A-BB60-40927D15CFC3}.Debug|x86.ActiveCfg = Debug|x64
{D8031C13-7BEA-430A-BB60-40927D15CFC3}.MinSizeRel|Any CPU.ActiveCfg = Release|x64
{D8031C13-7BEA-430A-BB60-40927D15CFC3}.MinSizeRel|Any CPU.Build.0 = Release|x64
{D8031C13-7BEA-430A-BB60-40927D15CFC3}.MinSizeRel|x64.ActiveCfg = Release|x64
{D8031C13-7BEA-430A-BB60-40927D15CFC3}.MinSizeRel|x64.Build.0 = Release|x64
{D8031C13-7BEA-430A-BB60-40927D15CFC3}.MinSizeRel|x86.ActiveCfg = Release|x64
{D8031C13-7BEA-430A-BB60-40927D15CFC3}.MinSizeRel|x86.Build.0 = Release|x64
{D8031C13-7BEA-430A-BB60-40927D15CFC3}.Release|Any CPU.ActiveCfg = Release|x64
{D8031C13-7BEA-430A-BB60-40927D15CFC3}.Release|x64.ActiveCfg = Release|x64
{D8031C13-7BEA-430A-BB60-40927D15CFC3}.Release|x64.Build.0 = Release|x64
{D8031C13-7BEA-430A-BB60-40927D15CFC3}.Release|x86.ActiveCfg = Release|x64
{D8031C13-7BEA-430A-BB60-40927D15CFC3}.RelWithDebInfo|Any CPU.ActiveCfg = Release|x64
{D8031C13-7BEA-430A-BB60-40927D15CFC3}.RelWithDebInfo|Any CPU.Build.0 = Release|x64
{D8031C13-7BEA-430A-BB60-40927D15CFC3}.RelWithDebInfo|x64.ActiveCfg = Release|x64
{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
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
+1 -3
View File
@@ -9,7 +9,6 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Configurations>Debug;Release</Configurations>
<Platforms>x64</Platforms>
<RuntimeIdentifiers>win7-x64</RuntimeIdentifiers>
<PlatformTarget>AnyCPU</PlatformTarget>
<LanguageTargets>$(MSBuildExtensionsPath)\$(VisualStudioVersion)\Bin\Microsoft.CSharp.targets</LanguageTargets>
<ApplicationIcon>logo.ico</ApplicationIcon>
@@ -19,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" />
@@ -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);
@@ -3,4 +3,5 @@ using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("spark_core")]
[assembly: InternalsVisibleTo("sparkcmd")]
[assembly: InternalsVisibleTo("spark_test")]
[assembly: InternalsVisibleTo("spark_fix")]
@@ -3,7 +3,7 @@ using System.Collections.Generic;
using static bts.api.Security;
namespace bts.api {
struct FutureLeg {
public struct FutureLeg {
public readonly Venue exchange;
public readonly string symbol, exchange_desc;
public readonly FutureContractImmutable future;
@@ -4,7 +4,7 @@ using System.Linq;
using static bts.api.Security;
namespace bts.api {
internal static class SecurityHelper {
public static class SecurityHelper {
public static IEnumerable<FutureLeg> get_flat_future_legs(SecurityImmutable sec) {
switch (sec.ContractCase) {
case ContractOneofCase.Spread: return _get_flat_future_legs(sec.Spread.Legs, 1);
+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>
+3 -1
View File
@@ -36,6 +36,7 @@ namespace bts {
Plugin,
Sdk,
Http,
Fix
// Please keep this list in sync with logging.h/logging.cpp
}
@@ -102,9 +103,10 @@ namespace bts {
internal static Logger Assert => new Logger(Subsystem.Assert);
internal static Logger Ui => new Logger(Subsystem.Ui);
internal static Logger Testing => new Logger(Subsystem.Testing);
internal static Logger DataFlow => new Logger(Subsystem.DataFlow);
internal static Logger DataFlow => new Logger(Subsystem.DataFlow);
public static Logger Sdk => new Logger(Subsystem.Sdk);
public static Logger Http => new Logger(Subsystem.Http);
internal static Logger FIX => new Logger(Subsystem.Fix);
internal static void log_at(this Logger logger, Level level, string message) {
switch (level) {
@@ -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}";
}
}
}
@@ -0,0 +1,64 @@
using bts;
using bts.api.admin;
using System;
using System.Collections.Generic;
using System.Linq;
namespace bts.api.core
{
public class AdminModelWrapper
{
readonly AdminDataImmutable? _admin_data;
public AdminDataImmutable? admin_data => _admin_data;
readonly string _user_name;
readonly List<BTSAccountImmutable> _allowed_accounts;
readonly Dictionary<string, string> _allowed_account_dict = new Dictionary<string, string>();
public AdminModelWrapper(AdminDataImmutable? admin_data = null, string user_name = null)
{
_admin_data = admin_data;
_user_name = user_name ?? string.Empty;
_allowed_accounts = search_admin(u => u.Name == _user_name).Where(x =>
{
return (x.Item2 != null && x.Item2.HasPermissions) || (x.Item3 != null && x.Item3.HasPermissions);
}).Select(xx => xx.Item1).ToList();
foreach (var val in _allowed_accounts)
_allowed_account_dict[val.Name] = val.Name;
}
public IEnumerable<BTSAccountImmutable> viewable_accounts()
{
return _allowed_accounts;
}
public bool can_view_account(string account)
{
return _allowed_account_dict.ContainsKey(account) || _user_name.ToLower().Equals("bts");
}
IEnumerable<Tuple<BTSAccountImmutable, TradingPermissionUnit, AdminPermissionUnit>>
search_admin(Func<BTSUserImmutable, bool> predicate)
{
var rv = new List<Tuple<BTSAccountImmutable, TradingPermissionUnit, AdminPermissionUnit>>();
if (_admin_data.HasValue)
{
var users = _admin_data.Value.Users.Where(predicate);
if (users != null && users.Count() == 1)
{
var user = users.ElementAt(0);
if (user.HasUserData && user.UserData.HasAccountPermissions)
{
foreach (var kv in user.UserData.AccountPermissions.AccountPermissions)
{
var account_id = kv.Key;
var accounts = _admin_data.Value.Accounts.Where(a => a.Id == account_id);
if (accounts != null && accounts.Count() == 1)
{
var account = accounts.ElementAt(0);
rv.Add(Tuple.Create(account, kv.Value.TradingPermission, kv.Value.AdminPermission));
}
}
}
}
}
return rv;
}
}
}
@@ -0,0 +1,64 @@
using bts;
using bts.api;
using bts.api.core;
using bts.api.orderman;
using bts.api.position;
using bts.spark;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Collections.Specialized;
using System.Linq;
using System.Reactive.Concurrency;
using System.Reactive.Linq;
namespace bts.api.core
{
public static class PermissionFilters
{
public static IObservable<Update<PositionUnitImmutable, int>>
PermissionFilter(this IObservable<Update<PositionUnitImmutable, int>> source, IObservable<AdminModelWrapper> am)
{
var pred = Observable.Create<Func<PositionUnitImmutable, bool>>(observer =>
{
return am.Subscribe(x =>
{
Func<PositionUnitImmutable, bool> filter = (z => x.can_view_account(z.Account));
observer.OnNext(filter);
});
});
return source.Filter(pred);
}
public static IObservable<Update<OrderRecordImmutable, uint>>
PermissionFilter(this IObservable<Update<OrderRecordImmutable, uint>> source, IObservable<AdminModelWrapper> am)
{
var pred = Observable.Create<Func<OrderRecordImmutable, bool>>(observer =>
{
return am.Subscribe(x =>
{
Func<OrderRecordImmutable, bool> filter = (z => x.can_view_account(z.Def.Account ?? string.Empty));
observer.OnNext(filter);
});
});
return source.Filter(pred);
}
public static IObservable<Update<FillImmutable, string>>
PermissionFilter(this IObservable<Update<FillImmutable, string>> source, IObservable<AdminModelWrapper> am)
{
var pred = Observable.Create<Func<FillImmutable, bool>>(observer =>
{
return am.Subscribe(x =>
{
Func<FillImmutable, bool> filter = (z => x.can_view_account(z.Account));
observer.OnNext(filter);
});
});
return source.Filter(pred);
}
}
}
+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>
@@ -66,7 +66,6 @@ namespace mbts {
}
}
}
public static void sync_with_models<T, TModel>(this IList<T> target, IEnumerable<TModel> models, Func<TModel, T> add_factory, Func<T, TModel, T> update_factory) {
var model_list = models as IList<TModel> ?? models.ToList();
if (model_list.Count == 0) {
@@ -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;
}
+1 -2
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>
Binary file not shown.
+61
View File
@@ -0,0 +1,61 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using QuickFix;
using QuickFix.Fields;
namespace bts.fix
{
public class FixInit
{
static FixInit()
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
var exception = e.ExceptionObject as Exception;
Log.FIX.error($"Unhandled Exception: {e.ExceptionObject} {exception?.StackTrace}");
if (e.IsTerminating)
{
Log.system_is_crashing("Unhandled exception", e.ExceptionObject);
}
}
public static int start_acceptor(string settings_file, bool orders_allowed, string http_address = null)
{
SessionSettings settings = new SessionSettings(settings_file);
IApplication app = new FixRouter( (th, sess) =>
{
if(orders_allowed)
return new OrderSession(th, sess);
else
return new DropCopySession(th, sess);
});
IMessageStoreFactory storeFactory = new FileStoreFactory(settings);
ILogFactory logFactory = new FileLogFactory(settings);
IAcceptor acceptor = new ThreadedSocketAcceptor(app, storeFactory, settings, logFactory);
acceptor.Start();
HttpServer srv = null;
if (!string.IsNullOrEmpty(http_address))
{
if(!http_address.StartsWith("http"))
http_address = "http://127.0.0.1:5080/";
srv = new HttpServer(http_address, settings);
srv.Start();
}
Console.WriteLine("press <q> to quit");
while (Console.Read() != 'q') { }
acceptor.Stop();
if(srv != null)
srv.Stop();
return 0;
}
}
}
+231
View File
@@ -0,0 +1,231 @@
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Linq;
using System.Reactive.Linq;
using System.Reactive.Concurrency;
using System.Text;
using QuickFix;
using QuickFix.Fields;
using bts.api;
using bts.api.core;
using bts.api.orderman;
using bts.api.user;
using bts.md;
using bts.api.admin;
using security_key = System.UInt32;
namespace bts.fix
{
interface IFixRouter
{
IEnumerable<SecurityImmutable> get_securities();
SecurityImmutable? lookup(security_key key);
SecurityImmutable? lookup(string desc);
void send(Message mess, SessionID sess);
void send_session_reject(SessionID sess, string text, Message refmessage = null);
void send_biz_reject(SessionID sess, string text, Message refmessage, int reason_code = 0);
}
class FixRouter : QuickFix.MessageCracker, IFIXSession, IFixRouter
{
readonly ConcurrentDictionary<SessionID, QuickFix.IApplication> _sessions = new ConcurrentDictionary<SessionID, IApplication>();
readonly Func<IFixRouter, SessionID, IApplication> _factory;
readonly MarketDataClient _md = new MarketDataClient();
readonly object _lock = new object();
public FixRouter(Func<IFixRouter, SessionID, IApplication> factory)
{
_factory = factory;
}
IApplication session(SessionID sessionID)
{
IApplication app;
if (!_sessions.TryGetValue(sessionID, out app))
{
app = _factory(this, sessionID);
_sessions[sessionID] = app;
}
return app;
}
public void send(Message mess, SessionID sess)
{
lock (_lock)
{
try
{
Session.SendToTarget(mess, sess);
}
catch (SessionNotFound)
{
Log.assert(false, "session not found " + sess);
}
catch (Exception ex)
{
Log.FIX.error(sess.ToString() + " " + ex.Message + " " + sess);
}
}
}
public void send_session_reject(SessionID sess, string text, Message refmessage = null)
{
QuickFix.FIX44.Reject rej = null;
if (refmessage != null && refmessage.Header.IsSetField(Tags.MsgSeqNum))
rej = new QuickFix.FIX44.Reject(new QuickFix.Fields.RefSeqNum(refmessage.Header.GetInt(Tags.MsgSeqNum)));
else
rej = new QuickFix.FIX44.Reject();
rej.Text = new Text(text);
send(rej, sess);
}
public void send_biz_reject(SessionID sess, string text, Message refmessage, int reason_code = 0)
{
QuickFix.FIX44.BusinessMessageReject rej = new QuickFix.FIX44.BusinessMessageReject();
rej.RefMsgType = new QuickFix.Fields.RefMsgType(refmessage.Header.GetString(Tags.MsgType));
rej.RefSeqNum = new QuickFix.Fields.RefSeqNum(refmessage.Header.GetInt(Tags.MsgSeqNum));
rej.BusinessRejectReason = new QuickFix.Fields.BusinessRejectReason(reason_code);
rej.Text = new Text(text);
send(rej, sess);
}
void handle_session_exception(Exception ex, SessionID sessionID, Message message = null)
{
string msg = "==ERROR in session " + sessionID.ToString() + "== ";
msg += message?.GetType().Name ?? string.Empty;
msg += ex?.ToString() ?? string.Empty;
if(!string.IsNullOrEmpty(ex.StackTrace))
msg += Environment.NewLine + ex.StackTrace;
bts.Log.FIX.error(msg);
Console.WriteLine(msg);
//now shut this fucker down
try
{
var sess = Session.LookupSession(sessionID);
if(sess != null)
sess.Disconnect(msg);
}
catch { }
}
void handle_field_not_found(FieldNotFoundException ex, SessionID sess, Message message)
{
if(ex.Field > 0)
send_biz_reject(sess, $"Field {ex.Field} was expected but not found", message, 5 );
//QF does not include the tag number....
//throw new FieldNotFoundException($"Field {ex.Field} was expected but not found", ex);
else
throw ex;
}
public void FromAdmin(Message message, SessionID sessionID)
{
try
{
session(sessionID).FromAdmin(message, sessionID);
}
catch (FieldNotFoundException ex) { handle_field_not_found(ex, sessionID, message); }
catch (UnsupportedMessageType) { throw; }
catch (IncorrectTagValue) { throw; }
catch (Exception ex) { handle_session_exception(ex, sessionID, message); }
}
public void FromApp(Message message, SessionID sessionID)
{
try
{
session(sessionID).FromApp(message, sessionID);
}
catch (FieldNotFoundException ex) { handle_field_not_found(ex, sessionID, message); }
catch (UnsupportedMessageType) { throw; }
catch (IncorrectTagValue) { throw; }
catch (Exception ex) { handle_session_exception(ex, sessionID, message); }
}
public void OnCreate(SessionID sessionID)
{
try
{
session(sessionID).OnCreate(sessionID);
}
catch (Exception ex)
{
handle_session_exception(ex, sessionID);
}
}
public void OnLogon(SessionID sessionID)
{
try
{
session(sessionID).OnLogon(sessionID);
}
catch (Exception ex)
{
handle_session_exception(ex, sessionID);
}
}
public void OnLogout(SessionID sessionID)
{
try
{
//TODO stackoverflow?
session(sessionID).OnLogout(sessionID);
}
catch (Exception ex)
{
handle_session_exception(ex, sessionID);
}
}
public void ToAdmin(Message message, SessionID sessionID)
{
try
{
session(sessionID).ToAdmin(message, sessionID);
}
catch (FieldNotFoundException ex) { handle_field_not_found(ex, sessionID, message); }
catch (UnsupportedMessageType) { throw; }
catch (IncorrectTagValue) { throw; }
catch (Exception ex) { handle_session_exception(ex, sessionID, message); }
}
public void ToApp(Message message, SessionID sessionID)
{
try
{
session(sessionID).ToApp(message, sessionID);
}
catch (FieldNotFoundException ex) { handle_field_not_found(ex, sessionID, message); }
catch (UnsupportedMessageType) { throw; }
catch (IncorrectTagValue) { throw; }
catch (Exception ex) { handle_session_exception(ex, sessionID, message); }
}
IEnumerable<SecurityImmutable> IFixRouter.get_securities()
{
return _md.securities;
}
SecurityImmutable? IFixRouter.lookup(uint key)
{
return _md.lookup(key);
}
SecurityImmutable? IFixRouter.lookup(string desc)
{
if (_md.lookup_security_key_from_desc(desc, out uint key))
return _md.lookup(key);
else
return null;
}
}
}
+585
View File
@@ -0,0 +1,585 @@
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;
using System.Web;
using QuickFix;
namespace bts.fix
{
public class HttpServer : IDisposable
{
private readonly HttpListener _httpListener;
private Thread _connectionThread;
private Boolean _running, _disposed;
private readonly SessionSettings _sessionSettings;
private StringBuilder _sbHtmlHeader;
public HttpServer(string prefix, SessionSettings settings)
{
if (!HttpListener.IsSupported)
{
// Requires at least a Windows XP with Service Pack 2
throw new NotSupportedException(
"The Http Server cannot run on this operating system.");
}
_httpListener = new HttpListener();
_httpListener.Prefixes.Add(prefix);
_sessionSettings = settings;
}
public void Start()
{
if (!_httpListener.IsListening)
{
_httpListener.Start();
_running = true;
// Use a thread to listen to the Http requests
_connectionThread = new Thread(ConnectionThreadStart);
_connectionThread.Start();
}
}
public void Stop()
{
if (_httpListener.IsListening)
{
_running = false;
_httpListener.Stop();
}
}
private void ConnectionThreadStart()
{
try
{
while (_running)
{
// Grab the context and pass it to the processor methods to handle it
HttpListenerContext context = _httpListener.GetContext();
HttpListenerRequest request = context.Request;
HttpListenerResponse response = context.Response;
string responseString;
_sbHtmlHeader = new StringBuilder(@"<HEAD><CENTER><TITLE>QuickFIX Engine Web Interface</TITLE><H1>QuickFIX Engine Web Interface</H1></CENTER>");
_sbHtmlHeader.AppendFormat(@"<CENTER>[<A HREF='/'>HOME</A>]&nbsp;[<A HREF='{0}'>RELOAD</A>]</CENTER><HR/></HEADER><BODY>", request.Url.OriginalString);
switch (request.Url.AbsolutePath)
{
case "/":
responseString = ProcessRoot(request);
break;
case "/session":
responseString = SessionDetails(request);
break;
case "/resetSession":
responseString = ResetSession(request);
break;
case "/resetSessions":
responseString = ResetSessions(request);
break;
case "/refreshSession":
responseString = RefreshSession(request);
break;
case "/refreshSessions":
responseString = RefreshSessions(request);
break;
case "/enableSessions":
responseString = EnableSessions(request);
break;
case "/disableSessions":
responseString = DisableSessions(request);
break;
default:
responseString = ProcessRoot(request);
break;
}
byte[] buffer = Encoding.UTF8.GetBytes(responseString);
response.ContentLength64 = buffer.Length;
Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
output.Close();
}
}
catch (HttpListenerException)
{
Console.WriteLine("HTTP server was shut down.");
}
}
private string DisableSessions(HttpListenerRequest request)
{
bool confirm = false;
StringBuilder sbHtmlPageBody = _sbHtmlHeader;
if (request.QueryString["confirm"] != null)
{
if (Convert.ToInt16(request.QueryString["confirm"]) != 0)
{
confirm = true;
foreach (SessionID session in _sessionSettings.GetSessions())
{
Session sessionDetails = Session.LookupSession(session);
sessionDetails.Logout();
}
}
}
if (confirm)
{
sbHtmlPageBody = new StringBuilder();
sbHtmlPageBody.AppendFormat(@"<HEAD><META http-equiv='refresh' content=2;URL={0} /><CENTER><TITLE>QuickFIX Engine Web Interface</TITLE><H1>QuickFIX Engine Web Interface</H1></CENTER>", "/");
sbHtmlPageBody.AppendFormat("<CENTER><h2><A HREF='{0}'>Sessions</A> have been disabled</h2></CENTER>", "/");
}
else
{
sbHtmlPageBody.Append("<CENTER><h2>Are you sure you want to disable all sessions ?</h2></CENTER>");
sbHtmlPageBody.AppendFormat("<CENTER>[<A HREF='{0}?confirm=1'>YES, disable sessions</A>]&nbsp;[<A HREF='/'>NO, do not disable sessions</A>]</CENTER>", request.Url.OriginalString);
}
return sbHtmlPageBody.ToString();
}
private string EnableSessions(HttpListenerRequest request)
{
bool confirm = false;
string urlOriginalString = request.Url.OriginalString;
StringBuilder sbHtmlPageBody = _sbHtmlHeader;
if (request.QueryString["confirm"] != null)
{
if (Convert.ToInt16(request.QueryString["confirm"]) != 0)
{
confirm = true;
foreach (SessionID session in _sessionSettings.GetSessions())
{
Session sessionDetails = Session.LookupSession(session);
sessionDetails.Logon();
}
}
}
if (confirm)
{
sbHtmlPageBody = new StringBuilder();
sbHtmlPageBody.AppendFormat(@"<HEAD><META http-equiv='refresh' content=2;URL={0} /><CENTER><TITLE>QuickFIX Engine Web Interface</TITLE><H1>QuickFIX Engine Web Interface</H1></CENTER>", "/");
sbHtmlPageBody.AppendFormat("<CENTER><h2><A HREF='{0}'>Sessions</A> have been enabled</h2></CENTER>", "/");
}
else
{
sbHtmlPageBody.Append("<CENTER><h2>Are you sure you want to enable all sessions ?</h2></CENTER>");
sbHtmlPageBody.AppendFormat("<CENTER>[<A HREF='{0}?confirm=1'>YES, enable sessions</A>]&nbsp;[<A HREF='/'>NO, do not enable sessions</A>]</CENTER>", urlOriginalString);
}
return sbHtmlPageBody.ToString();
}
private string RefreshSession(HttpListenerRequest request)
{
SessionID sessionId = new SessionID(request.QueryString["beginstring"], request.QueryString["sendercompid"], request.QueryString["targetcompid"]);
Session sessionDetails = Session.LookupSession(sessionId);
if (sessionDetails == null) throw new Exception("Session not found");
StringBuilder sbHtmlPageBody = _sbHtmlHeader;
bool confirm = false;
string urlOriginalString = request.Url.OriginalString;
string url = "/session?" + GetParameterList(urlOriginalString);
if (request.QueryString["confirm"] != null)
{
if (Convert.ToInt16(request.QueryString["confirm"]) != 0)
{
confirm = true;
sessionDetails.Refresh();
url = RemoveQueryStringByKey(urlOriginalString, "confirm");
}
}
if (confirm)
{
sbHtmlPageBody = new StringBuilder();
sbHtmlPageBody.AppendFormat(@"<HEAD><META http-equiv='refresh' content=2;URL=/session?{0} /><CENTER><TITLE>QuickFIX Engine Web Interface</TITLE><H1>QuickFIX Engine Web Interface</H1></CENTER>", GetParameterList(urlOriginalString));
sbHtmlPageBody.AppendFormat(@"<CENTER>[<A HREF='/'>HOME</A>]&nbsp;[<A HREF='{0}'>RELOAD</A>]</CENTER><HR/></HEAD><BODY>", urlOriginalString);
sbHtmlPageBody.AppendFormat("<CENTER><h2><A HREF='/session?{0}'>{1}</A> has been refreshed</h2></CENTER>", GetParameterList(url), sessionId);
}
else
{
sbHtmlPageBody.AppendFormat("<CENTER><h2>Are you sure you want to refresh session <A HREF='{0}'>{1}</A>?</h2></CENTER>", url, sessionId);
sbHtmlPageBody.AppendFormat("<CENTER>[<A HREF='{0}&confirm=1'>YES, refresh session</A>]&nbsp;[<A HREF='{0}'>NO, do not refresh session</A>]</CENTER>", url);
}
return sbHtmlPageBody.ToString();
}
private string RefreshSessions(HttpListenerRequest request)
{
bool confirm = false;
string urlOriginalString = request.Url.OriginalString;
StringBuilder sbHtmlPageBody = _sbHtmlHeader;
if (request.QueryString["confirm"] != null)
{
if (Convert.ToInt16(request.QueryString["confirm"]) != 0)
{
confirm = true;
foreach (SessionID session in _sessionSettings.GetSessions())
{
Session sessionDetails = Session.LookupSession(session);
sessionDetails.Refresh();
}
}
}
if (confirm)
{
sbHtmlPageBody = new StringBuilder();
sbHtmlPageBody.AppendFormat(@"<HEAD><META http-equiv='refresh' content=2;URL={0} /><CENTER><TITLE>QuickFIX Engine Web Interface</TITLE><H1>QuickFIX Engine Web Interface</H1></CENTER>", "/");
sbHtmlPageBody.AppendFormat("<CENTER><h2><A HREF='{0}'>Sessions</A> have been refreshed</h2></CENTER>", "/");
}
else
{
sbHtmlPageBody.Append("<CENTER><h2>Are you sure you want to refresh all sessions ?</h2></CENTER>");
sbHtmlPageBody.AppendFormat("<CENTER>[<A HREF='{0}?confirm=1'>YES, refresh sessions</A>]&nbsp;[<A HREF='/'>NO, do not refresh sessions</A>]</CENTER>", urlOriginalString);
}
return sbHtmlPageBody.ToString();
}
private string ResetSessions(HttpListenerRequest request)
{
bool confirm = false;
string urlOriginalString = request.Url.OriginalString;
StringBuilder sbHtmlPageBody = _sbHtmlHeader;
if (request.QueryString["confirm"] != null)
{
if (Convert.ToInt16(request.QueryString["confirm"]) != 0)
{
confirm = true;
foreach (SessionID session in _sessionSettings.GetSessions())
{
Session sessionDetails = Session.LookupSession(session);
sessionDetails.Reset("Reset from WebInterface");
}
}
}
if (confirm)
{
sbHtmlPageBody = new StringBuilder();
sbHtmlPageBody.AppendFormat(@"<HEAD><META http-equiv='refresh' content=2;URL={0} /><CENTER><TITLE>QuickFIX Engine Web Interface</TITLE><H1>QuickFIX Engine Web Interface</H1></CENTER>", "/");
sbHtmlPageBody.AppendFormat("<CENTER><h2><A HREF='{0}'>Sessions</A> have been reset</h2></CENTER>", "/");
}
else
{
sbHtmlPageBody.Append("<CENTER><h2>Are you sure you want to reset all sessions ?</h2></CENTER>");
sbHtmlPageBody.AppendFormat("<CENTER>[<A HREF='{0}?confirm=1'>YES, reset sessions</A>]&nbsp;[<A HREF='/'>NO, do not reset sessions</A>]</CENTER>", urlOriginalString);
}
return sbHtmlPageBody.ToString();
}
private string ResetSession(HttpListenerRequest request)
{
SessionID sessionId = new SessionID(request.QueryString["beginstring"], request.QueryString["sendercompid"], request.QueryString["targetcompid"]);
Session sessionDetails = Session.LookupSession(sessionId);
if (sessionDetails == null) throw new Exception("Session not found");
StringBuilder sbHtmlPageBody = _sbHtmlHeader;
bool confirm = false;
string urlOriginalString = request.Url.OriginalString;
string url = "/session?" + GetParameterList(urlOriginalString);
if (request.QueryString["confirm"] != null)
{
if (Convert.ToInt16(request.QueryString["confirm"]) != 0)
{
confirm = true;
sessionDetails.Reset("Reset from WebInterface");
url = RemoveQueryStringByKey(urlOriginalString, "confirm");
}
}
if (confirm)
{
sbHtmlPageBody = new StringBuilder();
sbHtmlPageBody.AppendFormat(@"<HEAD><META http-equiv='refresh' content=2;URL=/session?{0} /><CENTER><TITLE>QuickFIX Engine Web Interface</TITLE><H1>QuickFIX Engine Web Interface</H1></CENTER>", GetParameterList(urlOriginalString));
sbHtmlPageBody.AppendFormat(@"<CENTER>[<A HREF='/'>HOME</A>]&nbsp;[<A HREF='{0}'>RELOAD</A>]</CENTER><HR/></HEAD><BODY>", urlOriginalString);
sbHtmlPageBody.AppendFormat("<CENTER><h2><A HREF='/session?{0}'>{1}</A> has been reset</h2></CENTER>", GetParameterList(url), sessionId);
}
else
{
sbHtmlPageBody.AppendFormat("<CENTER><h2>Are you sure you want to reset session <A HREF='{0}'>{1}</A>?</h2></CENTER>", url, sessionId);
sbHtmlPageBody.AppendFormat("<CENTER>[<A HREF='{0}&confirm=1'>YES, reset session</A>]&nbsp;[<A HREF='{0}'>NO, do not reset session</A>]</CENTER>", url);
}
return sbHtmlPageBody.ToString();
}
private string ProcessRoot(HttpListenerRequest request)
{
StringBuilder sbHtmlPageBody = _sbHtmlHeader;
//Session count
sbHtmlPageBody.AppendFormat("<CENTER><b><i>{0} Sessions managed by QuickFIX</b></i></CENTER><HR/>", _sessionSettings.GetSessions().Count);
//session management links
sbHtmlPageBody.AppendFormat(@"<CENTER><A HREF='/resetSessions{0}'>RESET</A>&nbsp;<A HREF='/refreshSessions'>REFRESH</A>&nbsp;<A HREF='/enableSessions'>ENABLE</A>&nbsp;<A HREF='/disableSessions'>DISABLE</A></CENTER><HR/></HEADER><BODY>", GetParameterList(request.Url.OriginalString));
//Start the table generation
sbHtmlPageBody.Append("<table id=\"sessionlist\" style=\"border-width:1; padding:2; width:100%\">");
sbHtmlPageBody.Append("<tr>");
sbHtmlPageBody.Append(AddCell("Session", true));
sbHtmlPageBody.Append(AddCell("Type", true));
sbHtmlPageBody.Append(AddCell("Enabled", true));
sbHtmlPageBody.Append(AddCell("Session Time", true));
sbHtmlPageBody.Append(AddCell("Logged On", true));
sbHtmlPageBody.Append(AddCell("Next Incoming", true));
sbHtmlPageBody.Append(AddCell("Next Outgoing", true));
sbHtmlPageBody.Append("</tr>");
foreach (SessionID session in _sessionSettings.GetSessions())
{
Session sessionDetails = Session.LookupSession(session);
sbHtmlPageBody.Append("<tr>");
sbHtmlPageBody.Append(AddCell(String.Format(
"<a href=\"session?BeginString={0}&SenderCompID={1}&TargetCompID={2}\">{0}:{1}->{2}</a>",
session.BeginString, session.SenderCompID, session.TargetCompID)));
sbHtmlPageBody.Append(AddCell(sessionDetails.IsInitiator ? "initiator" : "acceptor"));
sbHtmlPageBody.Append(AddCell(sessionDetails.IsEnabled ? "yes" : "no"));
sbHtmlPageBody.Append(AddCell(sessionDetails.IsSessionTime ? "yes" : "no"));
sbHtmlPageBody.Append(AddCell(sessionDetails.IsLoggedOn ? "yes" : "no"));
sbHtmlPageBody.Append(AddCell(sessionDetails.NextTargetMsgSeqNum.ToString()));
sbHtmlPageBody.Append(AddCell(sessionDetails.NextSenderMsgSeqNum.ToString()));
sbHtmlPageBody.Append("</tr>");
}
sbHtmlPageBody.Append("</table>");
return sbHtmlPageBody.ToString();
}
public string SessionDetails(HttpListenerRequest request)
{
SessionID sessionId = new SessionID(request.QueryString["beginstring"], request.QueryString["sendercompid"], request.QueryString["targetcompid"]);
Session sessionDetails = Session.LookupSession(sessionId);
if (sessionDetails == null) throw new Exception("Session not found");
StringBuilder sbHtmlPageBody = _sbHtmlHeader;
string url = request.Url.OriginalString;
string urlOriginalString = request.Url.OriginalString;
if (request.QueryString["enabled"] != null)
{
if (!Convert.ToBoolean(request.QueryString["enabled"]))
sessionDetails.Logout();
else
sessionDetails.Logon();
url = RemoveQueryStringByKey(urlOriginalString, "Enabled");
}
if (request.QueryString["next incoming"] != null)
{
int value = Convert.ToInt16(request.QueryString["next incoming"]);
sessionDetails.NextTargetMsgSeqNum = value <= 0 ? 1 : value;
url = RemoveQueryStringByKey(urlOriginalString, "next incoming");
}
if (request.QueryString["Next Outgoing"] != null)
{
int value = Convert.ToInt16(request.QueryString["Next Outgoing"]);
sessionDetails.NextSenderMsgSeqNum = value <= 0 ? 1 : value;
url = RemoveQueryStringByKey(urlOriginalString, "Next Outgoing");
}
if (request.QueryString["SendRedundantResendRequests"] != null)
{
sessionDetails.SendRedundantResendRequests = Convert.ToBoolean(request.QueryString["SendRedundantResendRequests"]);
url = RemoveQueryStringByKey(urlOriginalString, "SendRedundantResendRequests");
}
if (request.QueryString["CheckCompId"] != null)
{
sessionDetails.CheckCompID = Convert.ToBoolean(request.QueryString["CheckCompId"]);
url = RemoveQueryStringByKey(urlOriginalString, "CheckCompId");
}
if (request.QueryString["CheckLatency"] != null)
{
sessionDetails.CheckLatency = Convert.ToBoolean(request.QueryString["CheckLatency"]);
url = RemoveQueryStringByKey(urlOriginalString, "CheckLatency");
}
if (request.QueryString["MaxLatency"] != null)
{
int value = Convert.ToInt16(request.QueryString["MaxLatency"]);
sessionDetails.MaxLatency = value <= 0 ? 1 : value;
url = RemoveQueryStringByKey(urlOriginalString, "MaxLatency");
}
if (request.QueryString["LogonTimeout"] != null)
{
int value = Convert.ToInt16(request.QueryString["LogonTimeout"]);
sessionDetails.LogonTimeout = value <= 0 ? 1 : value;
url = RemoveQueryStringByKey(urlOriginalString, "LogonTimeout");
}
if (request.QueryString["LogoutTimeout"] != null)
{
int value = Convert.ToInt16(request.QueryString["LogoutTimeout"]);
sessionDetails.LogoutTimeout = value <= 0 ? 1 : value;
url = RemoveQueryStringByKey(urlOriginalString, "LogoutTimeout");
}
if (request.QueryString["ResetOnLogon"] != null)
{
sessionDetails.ResetOnLogon = Convert.ToBoolean(request.QueryString["ResetOnLogon"]);
url = RemoveQueryStringByKey(urlOriginalString, "ResetOnLogon");
}
if (request.QueryString["ResetOnLogout"] != null)
{
sessionDetails.ResetOnLogout = Convert.ToBoolean(request.QueryString["ResetOnLogout"]);
url = RemoveQueryStringByKey(urlOriginalString, "ResetOnLogout");
}
if (request.QueryString["ResetOnDisconnect"] != null)
{
sessionDetails.ResetOnDisconnect = Convert.ToBoolean(request.QueryString["ResetOnDisconnect"]);
url = RemoveQueryStringByKey(urlOriginalString, "ResetOnDisconnect");
}
if (request.QueryString["RefreshOnLogon"] != null)
{
sessionDetails.RefreshOnLogon = Convert.ToBoolean(request.QueryString["RefreshOnLogon"]);
url = RemoveQueryStringByKey(urlOriginalString, "RefreshOnLogon");
}
if (request.QueryString["MillisecondsInTimestamp"] != null)
{
sessionDetails.MillisecondsInTimeStamp = Convert.ToBoolean(request.QueryString["MillisecondsInTimestamp"]);
url = RemoveQueryStringByKey(urlOriginalString, "MillisecondsInTimestamp");
}
if (request.QueryString["PersistMessages"] != null)
{
sessionDetails.PersistMessages = Convert.ToBoolean(request.QueryString["PersistMessages"]);
url = RemoveQueryStringByKey(urlOriginalString, "PersistMessages");
}
sbHtmlPageBody.AppendFormat(@"<CENTER>{0}</CENTER><HR/>", sessionId);
sbHtmlPageBody.AppendFormat(@"<CENTER>[<A HREF='/resetSession?{0}'>RESET</A>]&nbsp;[<A HREF='/refreshSession?{0}'>REFRESH</A>]</CENTER><HR/></HEADER><BODY>", GetParameterList(urlOriginalString));
sbHtmlPageBody.Append("<table id=\"session_details\" style=\"border-width:1; padding:2; width:100%\">");
sbHtmlPageBody.Append(AddRow("Enabled", sessionDetails.IsEnabled, url));
sbHtmlPageBody.Append(AddRow("ConnectionType", sessionDetails.IsInitiator ? "initiator" : "acceptor"));
sbHtmlPageBody.Append(AddRow("SessionTime", sessionDetails.IsSessionTime));
sbHtmlPageBody.Append(AddRow("LoggedOn", sessionDetails.IsLoggedOn));
sbHtmlPageBody.Append(AddRow("Next Incoming", sessionDetails.NextTargetMsgSeqNum, url));
sbHtmlPageBody.Append(AddRow("Next Outgoing", sessionDetails.NextSenderMsgSeqNum, url));
sbHtmlPageBody.Append(AddRow("SendRedundantResendRequests", sessionDetails.SendRedundantResendRequests, url));
sbHtmlPageBody.Append(AddRow("CheckCompId", sessionDetails.CheckCompID, url));
sbHtmlPageBody.Append(AddRow("CheckLatency", sessionDetails.CheckLatency, url));
sbHtmlPageBody.Append(AddRow("MaxLatency", sessionDetails.MaxLatency, url));
sbHtmlPageBody.Append(AddRow("LogonTimeout", sessionDetails.LogonTimeout, url));
sbHtmlPageBody.Append(AddRow("LogoutTimeout", sessionDetails.LogoutTimeout, url));
sbHtmlPageBody.Append(AddRow("ResetOnLogon", sessionDetails.ResetOnLogon, url));
sbHtmlPageBody.Append(AddRow("ResetOnLogout", sessionDetails.ResetOnLogout, url));
sbHtmlPageBody.Append(AddRow("ResetOnDisconnect", sessionDetails.ResetOnDisconnect, url));
sbHtmlPageBody.Append(AddRow("RefreshOnLogon", sessionDetails.RefreshOnLogon, url));
sbHtmlPageBody.Append(AddRow("MillisecondsInTimestamp", sessionDetails.MillisecondsInTimeStamp, url));
sbHtmlPageBody.Append(AddRow("PersistMessages", sessionDetails.PersistMessages, url));
sbHtmlPageBody.Append("</table>");
return sbHtmlPageBody.ToString();
}
public static string RemoveQueryStringByKey(string url, string key)
{
var uri = new Uri(url);
// this gets all the query string key value pairs as a collection
var newQueryString = HttpUtility.ParseQueryString(uri.Query);
// this removes the key if exists
newQueryString.Remove(key);
// this gets the page path from root without QueryString
string pagePathWithoutQueryString = uri.GetLeftPart(UriPartial.Path);
return newQueryString.Count > 0
? $"{pagePathWithoutQueryString}?{newQueryString}"
: pagePathWithoutQueryString;
}
public static string GetParameterList(string url)
{
return HttpUtility.ParseQueryString((new Uri(url).Query)).ToString();
}
private static string AddRow(string colName, bool value, string url = "")
{
string valueAsStr = value ? "yes" : "no";
string innerHtml = url.Length > 0
? $"<a href=\" {url}&{colName}={!value} \">toggle</a>"
: "";
return AddRow(colName, valueAsStr, innerHtml);
}
private static string AddRow(string colName, int value, string url = "")
{
string innerHtml = $"<a href=\" {url}&{colName}={value - 10} \"> << </a>" +
$"<a href=\" {url}&{colName}={value - 1} \"> < </a>" +
" | " +
$"<a href=\" {url}&{colName}={value + 1} \"> > </a>" +
$"<a href=\" {url}&{colName}={value + 10} \"> >> </a>";
return AddRow(colName, value.ToString(), innerHtml);
}
private static string AddRow(string colName, string value, string innerHtml = "")
{
StringBuilder row = new StringBuilder();
row.Append("<tr>");
row.Append(AddCell(colName));
row.Append(AddCell(value));
row.Append(AddCell(innerHtml));
row.Append("</tr>");
return row.ToString();
}
private static string AddCell(string cellContent, bool header = false)
{
string entryType = header ? "th" : "td";
return "<" + entryType + " align=\"left\">" + cellContent + "</" + entryType + ">";
}
public virtual void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (_disposed)
{
return;
}
if (disposing)
{
if (_running)
{
Stop();
}
if (_connectionThread != null)
{
_connectionThread.Abort();
_connectionThread = null;
}
}
_disposed = true;
}
}
}
@@ -0,0 +1,2 @@
using System.Runtime.CompilerServices;
+2
View File
@@ -0,0 +1,2 @@
# BTS Spark FIX Adapter
@@ -0,0 +1,269 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Linq;
using System.Reactive.Concurrency;
using System.Text;
using QuickFix;
using QuickFix.Fields;
using bts.api;
using bts.api.core;
using bts.api.orderman;
using bts.api.user;
using bts.api.admin;
using System.Collections.Concurrent;
using System.Runtime.CompilerServices;
namespace bts.fix
{
class DropCopySession : SessionBase
{
protected IDisposable _fillsdisp;
protected IDisposable _ordersdisp;
protected static Lazy<OrderService> _orderservice = new Lazy<OrderService>(() => bts.api.Locator.locate<OrderService>(), true);
protected readonly ConcurrentDictionary<uint, OrderRecordImmutable> _order_cache = new ConcurrentDictionary<uint, OrderRecordImmutable>();
protected readonly ConcurrentDictionary<uint, string> _fix_clorderids = new ConcurrentDictionary<uint, string>();
public DropCopySession(IFixRouter router, SessionID sess) : base(router, sess)
{
}
override public void OnLogon(SessionID sessionID)
{
Log.assert_d(sessionID.Equals(_sess));
var msg = sessionID.ToString() + " Logged on";
log_info(msg);
subscribe_fills_and_orders(sessionID);
}
override public void OnLogout(SessionID sessionID)
{
Log.assert_d(sessionID.Equals(_sess));
var msg = sessionID.ToString() + " Logged out";
log_info(msg);
if (_ordersdisp != null)
_ordersdisp.Dispose();
if (_fillsdisp != null)
_fillsdisp.Dispose();
}
override public void FromApp(Message message, SessionID sessionID)
{
Log.assert_d(sessionID.Equals(_sess));
MsgType type = Message.IdentifyType(message.ToString());
switch (type.getValue())
{
case MsgType.ORDER_STATUS_REQUEST:
case MsgType.SECURITYDEFINITIONREQUEST:
log_info("IN: " + message);
Crack(message, sessionID);
break;
default:
log_info("UNSUPPORTED MESSAGE IN: " + type.getValue());
throw new UnsupportedMessageType();
}
}
virtual public void OnMessage(QuickFix.FIX44.OrderStatusRequest req, SessionID s)
{
uint oid = uint.Parse(req.OrderID.getValue());
if (_order_cache.TryGetValue(oid, out OrderRecordImmutable order))
{
var ostat = build_order_status(s, order);
ostat.OrdStatusReqID = new OrdStatusReqID(req.OrdStatusReqID.getValue());
_router.send(ostat, s);
}
}
virtual public void OnMessage(QuickFix.FIX44.SecurityDefinitionRequest req, SessionID s)
{
if (req.SecurityRequestType.getValue() == SecurityRequestType.REQUEST_LIST_SECURITIES)
{
var secs = _router.get_securities();
if (req.IsSetSymbol())
secs = secs.Where(x => x.Symbol.ToLower() == req.Symbol.getValue().ToLower());
if (req.IsSetSecurityType())
secs = secs.Where(x => security_types_equal(x.security_type(), req.SecurityType));
if (req.IsSetSecurityExchange())
secs = secs.Where(x => exchanges_equal(x.Exchange, req.SecurityExchange));
var def = new QuickFix.FIX44.SecurityDefinition(req.SecurityReqID,
new SecurityResponseID(Guid.NewGuid().ToString()),
new SecurityResponseType(SecurityResponseType.LIST_OF_SECURITIES_RETURNED_PER_REQUEST));
_router.send(def, s);
}
else
throw new IncorrectTagValue(req.SecurityRequestType.Tag);
}
virtual protected void subscribe_fills_and_orders(SessionID sessionID)
{
var scheduler = TaskPoolScheduler.Default;
var interval = TimeSpan.FromMilliseconds(500);
var on_orders = _orderservice.Value.subscribei_orders().Naggle(interval, scheduler).PermissionFilter(_adminobservable).Table().Cache();
var on_fills = _orderservice.Value.subscribei_fills().Naggle(interval, scheduler).PermissionFilter(_adminobservable).Table().Cache();
_ordersdisp = on_orders.Subscribe(o =>
{
foreach (var order in o.added)
{
var ostat = build_order_status(sessionID, order);
_order_cache[order.Key] = order;
_router.send(ostat, sessionID);
}
foreach (var order in o.changed)
{
var ostat = build_order_status(sessionID, order, true);
_router.send(ostat, sessionID);
}
});
_fillsdisp = on_fills.Subscribe(f =>
{
foreach (var fill in f.added)
{
var fi = build_fill(sessionID, fill);
_router.send(fi, sessionID);
}
foreach (var fill in f.changed)
{
var fi = build_fill(sessionID, fill, true);
_router.send(fi, sessionID);
}
});
}
virtual protected void process_order_state(in OrderStateImmutable state, ref uint filled, ref uint leaves, ref double avgprx,
ref QuickFix.Fields.OrdStatus fstatus, ref NativeOrderStateImmutable? native, FillImmutable? fill = null)
{
filled = state.FilledQuantity;
leaves = state.Quantity - state.FilledQuantity;
avgprx = state.AvgPrice;
fstatus = translate_status(state, ref native);
}
protected bts.api.SecurityImmutable? resolve_execution_report_security(bts.api.SecurityImmutable? sec, QuickFix.FIX44.ExecutionReport report)
{
report.SecurityExchange = convert_exchange(sec.Value.Exchange);
var sectype = sec.Value.security_type();
report.SecurityType = convert_security_type(sectype);
if (sec.Value.HasGlbx)
report.SecurityDesc = new SecurityDesc(sec.Value.Glbx.SecurityDesc);
switch (sectype)
{
case bts.api.SecurityType.Future:
report.MaturityMonthYear = new MaturityMonthYear(sec.Value.EarliestExpiration().ToString("yyyyMMdd"));
break;
case bts.api.SecurityType.Spread: //TODO this is not quite right for spreads of spreads
var leg = sec.Value.Spread.Legs.OrderBy(x => x.Security.EarliestExpiration()).First();
report.MaturityMonthYear = new MaturityMonthYear(leg.Security.EarliestExpiration().ToString("yyyyMMdd"));
break;
default:
throw new UnsupportedMessageType();
}
return sec;
}
virtual protected QuickFix.FIX44.ExecutionReport build_fill(SessionID sess, in FillImmutable fill, bool change = false)
{
var exec = new QuickFix.Fields.ExecType(QuickFix.Fields.ExecType.PARTIAL_FILL);
QuickFix.Fields.OrdStatus status = new QuickFix.Fields.OrdStatus();
uint filled = 0; uint leaves = 0; double prx = 0.0;
OrderRecordImmutable order; NativeOrderStateImmutable? native = null;
if (_order_cache.TryGetValue(fill.OrderKey, out order))
{
process_order_state(order.State, ref filled, ref leaves, ref prx, ref status, ref native);
if(Convert.ToDouble(order.State.Quantity) == fill.LastShares)
exec = new QuickFix.Fields.ExecType(QuickFix.Fields.ExecType.FILL);
}
if (change)
exec = new QuickFix.Fields.ExecType(QuickFix.Fields.ExecType.TRADE_CORRECT);
var sec = _router.lookup(fill.SecurityKey);
QuickFix.FIX44.ExecutionReport report = new QuickFix.FIX44.ExecutionReport(
new OrderID(fill.OrderKey.ToString()),
new ExecID(fill.FillKey.ToString()),
exec,
status,
new Symbol(sec?.Symbol ?? string.Empty),
new QuickFix.Fields.Side(fill.Side == bts.api.Side.Buy ? QuickFix.Fields.Side.BUY : QuickFix.Fields.Side.SELL),
new LeavesQty(leaves),
new CumQty(filled),
new AvgPx(Convert.ToDecimal(prx)));
report.Account = new Account(fill.Account);
report.LastQty = new LastQty(Convert.ToDecimal(fill.LastShares));
report.LastPx = new LastPx(Convert.ToDecimal(fill.LastPrice));
var ts = fill.HasTimestamp ? fill.Timestamp.ToDateTime() : DateTime.MinValue;
report.TransactTime = new TransactTime(ts, true);
report.TradeDate = new TradeDate(ts.ToString("yyyyMMdd"));
sec = resolve_execution_report_security(sec, report);
if (native.HasValue && !string.IsNullOrEmpty(native.Value.ExchangeOrderId))
report.SecondaryOrderID = new SecondaryOrderID(native.Value.ExchangeOrderId);
if (sec.HasValue && sec.Value.security_type() == bts.api.SecurityType.Spread ||
sec.Value.security_type() == bts.api.SecurityType.Synthetic)
{
if (fill.FillKind == bts.api.orderman.Fill.Types.FillKind.Leg)
report.MultiLegReportingType = new MultiLegReportingType('2');
else
report.MultiLegReportingType = new MultiLegReportingType('3');
}
return report;
}
virtual protected QuickFix.FIX44.ExecutionReport build_order_status(SessionID sess, in OrderRecordImmutable order, bool change = false)
{
var exec = new QuickFix.Fields.ExecType(QuickFix.Fields.ExecType.NEW);
if (_order_cache.TryGetValue(order.Key, out OrderRecordImmutable _))
exec = new QuickFix.Fields.ExecType(QuickFix.Fields.ExecType.ORDER_STATUS);
QuickFix.Fields.OrdStatus status = new QuickFix.Fields.OrdStatus();
uint filled = 0; uint leaves = 0; double prx = 0.0; NativeOrderStateImmutable? native = null;
process_order_state(order.State, ref filled, ref leaves, ref prx, ref status, ref native);
var sec = _router.lookup(order.Def.SecurityKey);
QuickFix.FIX44.ExecutionReport report = new QuickFix.FIX44.ExecutionReport(
new OrderID(order.Key.ToString()),
new ExecID("0"),
exec,
status,
new Symbol(sec?.Symbol ?? string.Empty),
new QuickFix.Fields.Side(order.Def.Side == bts.api.Side.Buy ? QuickFix.Fields.Side.BUY : QuickFix.Fields.Side.SELL),
new LeavesQty(leaves),
new CumQty(filled),
new AvgPx(Convert.ToDecimal(prx)));
report.Account = new Account(order.Def.Account);
report.OrderQty = new OrderQty(order.State.Quantity);
report.Price = new Price(Convert.ToDecimal(order.State.Price));
report.TimeInForce = new QuickFix.Fields.TimeInForce((char)order.Def.TimeInForce);
var ts = order.State.LastChange.ToDateTime();
report.TransactTime = new TransactTime(ts, true);
if(!string.IsNullOrEmpty(order.State.LastMsg))
report.Text = new Text(order.State.LastMsg);
sec = resolve_execution_report_security(sec, report);
if (native.HasValue)
{
report.OrdType = new OrdType((char)native.Value.NativeType);
if(!string.IsNullOrEmpty(native.Value.ExchangeOrderId))
report.SecondaryOrderID = new SecondaryOrderID(native.Value.ExchangeOrderId);
}
//TODO Big race here, we need a correlation id of some sort
if (_fix_clorderids.TryGetValue(order.Key, out string clorderid))
{
report.ClOrdID = new ClOrdID(clorderid);
}
return report;
}
}
}
@@ -0,0 +1,8 @@
using System;
namespace bts.fix
{
interface IFIXSession : QuickFix.IApplication
{
}
}
@@ -0,0 +1,167 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using QuickFix;
using QuickFix.Fields;
using bts.api;
using bts.api.orderman;
namespace bts.fix
{
/* Some test fix
order for 4 lot CLZ8
8=FIX.4.49=15635=D49=SPARK56=CLIENT134=150=3073797=Y52=20000809-20:20:5011=900010081=ACC A21=255=SIM:CLZ854=138=440=259=044=7460=20000809-18:20:32207=SIM10=045
order for 4 lot CLZ8-CLH9
8=FIX.4.49=15635=D49=SPARK56=CLIENT134=150=3073797=Y52=20000809-20:20:5011=900010081=ACC A21=255=SIM:CLZ8-CLH954=138=440=259=044=7460=20000809-18:20:32207=SIM10=045
*/
class OrderSession : DropCopySession
{
public OrderSession(IFixRouter router, SessionID sess) : base(router, sess)
{
}
override public void FromApp(Message message, SessionID sessionID)
{
Log.assert_d(sessionID.Equals(_sess));
MsgType type = Message.IdentifyType(message.ToString());
switch (type.getValue())
{
case MsgType.ORDER_STATUS_REQUEST: //handled in DropCopySession
case MsgType.SECURITYDEFINITIONREQUEST: //handled in DropCopySession
case MsgType.NEWORDERSINGLE:
case MsgType.ORDERCANCELREPLACEREQUEST:
case MsgType.ORDERCANCELREQUEST:
log_info("IN: " + message);
Crack(message, sessionID);
break;
default:
log_info("UNSUPPORTED MESSAGE IN: " + type.getValue());
throw new UnsupportedMessageType();
}
}
virtual public void OnMessage(QuickFix.FIX44.OrderCancelRequest cancel, SessionID s)
{
var id = cancel.OrderID.getValue();
if(!uint.TryParse(id, out uint key))
throw new IncorrectTagValue(cancel.OrderID.Tag);
var resp = _orderservice.Value.cancel_order(new Cancel { OrderKey = key });
if (resp.ErrorCode != OrderError.Ok)
{
send_cancel_reject(s, "Cancel Rejected: " + resp.ErrorCode.ToString() + " - " + resp.Msg, cancel);
}
}
virtual public void OnMessage(QuickFix.FIX44.OrderCancelReplaceRequest replace, SessionID s)
{
var id = replace.OrderID.getValue();
if (!uint.TryParse(id, out uint key))
throw new IncorrectTagValue(replace.OrderID.Tag);
double price = Convert.ToDouble(replace.Price.getValue());
uint sz = Convert.ToUInt32(Math.Abs(replace.OrderQty.getValue()));
var resp = _orderservice.Value.update_order(new Update
{
OrderKey = key,
Price = price,
Quantity = sz,
});
if (resp.ErrorCode != OrderError.Ok)
{
send_cancel_reject(s, "Cancel Rejected: " + resp.ErrorCode.ToString() + " - " + resp.Msg, replace);
}
}
virtual public void OnMessage(QuickFix.FIX44.NewOrderSingle create, SessionID s)
{
Venue ven = convert_exchange(create.SecurityExchange);
if (ven == bts.api.Venue.Unset)
throw new IncorrectTagValue(create.SecurityExchange.Tag);
var sec = _router.lookup(create.Symbol.getValue());
if (!sec.HasValue)
sec = _router.lookup(create.SecurityDesc.getValue());
if (!sec.HasValue)
throw new IncorrectTagValue(create.SecurityDesc.Tag);
OrderDefinition def = null;
try
{
string manual = "Y";
if(create.IsSetField(Tags.ManualOrderIndicator))
manual = create.GetField(Tags.ManualOrderIndicator);
def = new OrderDefinition()
{
Account = create.Account.getValue(),
AccountId = lookup_account(create.Account.getValue()),
SecurityKey = sec.Value.Id,
Side = (api.Side)(int)create.Side.getValue(),
TimeInForce = (api.orderman.TimeInForce)(int)create.TimeInForce.getValue(),
User = _user_name,
UserId = lookup_user(_user_name),
ManualOrderIndicator = manual == "Y" ? bts.api.orderman.ManualOrderIndicator.Yes : bts.api.orderman.ManualOrderIndicator.No,
};
}
catch
{
throw new IncorrectTagValue(create.TimeInForce.Tag);
}
set_ordertype(def, create, out bool price_req);
Create cr = new Create();
cr.NewOrder = def;
try
{
if (price_req)
cr.Price = Convert.ToDouble(create.Price.getValue());
}
catch
{
throw new IncorrectTagValue(create.Price.Tag);
}
try
{
cr.Quantity = Convert.ToUInt32(Math.Abs(create.OrderQty.getValue()));
}
catch
{
throw new IncorrectTagValue(create.OrderQty.Tag);
}
var resp = _orderservice.Value.create_order(cr);
if (resp.ErrorCode != OrderError.Ok)
{
_router.send_biz_reject(s, "Order Rejected: " + resp.ErrorCode.ToString() + " - " + resp.Msg, create);
}
}
private void set_ordertype(OrderDefinition def, QuickFix.FIX44.NewOrderSingle req, out bool price_req)
{
price_req = false;
switch (req.OrdType.getValue())
{
case '1':
def.CustomDef = new CustomOrderDefinition { Market = new MarketOrderDefinition() };
break;
case '2':
def.CustomDef = new CustomOrderDefinition { Limit = new LimitOrderDefinition() };
price_req = true;
break;
case '3':
def.CustomDef = new CustomOrderDefinition { Stop = new StopOrderDefinition() {StopPrice = Convert.ToDouble(req.StopPx.getValue()) } };
break;
case '4':
def.CustomDef = new CustomOrderDefinition { StopLimit = new StopLimitOrderDefinition() { StopPrice = Convert.ToDouble(req.StopPx.getValue()) } };
price_req = true;
break;
default:
throw new IncorrectTagValue(req.OrdType.Tag);
}
}
}
}
+361
View File
@@ -0,0 +1,361 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Linq;
using System.Reactive.Concurrency;
using System.Text;
using System.Collections.Concurrent;
using System.Runtime.CompilerServices;
using QuickFix;
using QuickFix.Fields;
using mbts;
using bts.api;
using bts.api.core;
using bts.api.orderman;
using bts.api.user;
using bts.api.admin;
namespace bts.fix
{
abstract class SessionBase : QuickFix.MessageCracker, IFIXSession
{
protected static AuthService _authservice = bts.api.Locator.locate<AuthService>();
protected static Lazy<AdminService> _adminservice = new Lazy<AdminService>(() => bts.api.Locator.locate<AdminService>(), true);
protected static Lazy<bts.metrics.ShellLatencyService> _latencyservice =
new Lazy<bts.metrics.ShellLatencyService>(() => bts.api.Locator.locate<bts.metrics.ShellLatencyService>(), true);
protected string _user_name;
protected AuthToken _token;
protected IDisposable _admindisp;
protected IObservable<AdminModelWrapper> _adminobservable;
protected AdminDataImmutable? _admin_data;
protected readonly IFixRouter _router;
protected readonly SessionID _sess;
public SessionBase(IFixRouter router, SessionID sess)
{
_router = router;
_sess = sess;
_clockdisp = _latencyservice.Value.subscribe_clock().Subscribe(x =>
{
var t = x.all.FirstOrDefault();
if(t != null)
_clock = t.Timestamp;
});
_adminobservable = _adminservice.Value.subscribei_admin_data().Select(x =>
{
return new AdminModelWrapper(x.all.TryFirst(), _user_name);
});
_admindisp = _adminobservable.Subscribe(x => _admin_data = x.admin_data);
}
abstract public void FromApp(Message message, SessionID sessionID);
abstract public void OnLogon(SessionID sessionID); //subscribe to your stuff
abstract public void OnLogout(SessionID sessionID); //unsub
virtual public void ToApp(Message message, SessionID sessionID)
{
Log.assert_d(sessionID.Equals(_sess));
log_info("OUT: " + message);
}
readonly IDisposable _clockdisp; ulong _clock = 0;
virtual public void FromAdmin(Message message, SessionID sessionID)
{
Log.assert_d(sessionID.Equals(_sess));
MsgType type = Message.IdentifyType(message.ToString());
switch (type.getValue())
{
case MsgType.LOGON:
{
try
{
QuickFix.FIX44.Logon msg = (QuickFix.FIX44.Logon)message;
_user_name = msg.Username.getValue();
string pass = string.Empty;
if(msg.IsSetPassword())
pass = msg.Password.getValue();
var resp = _authservice.authenticate_login(new AuthenticateLoginRequest {
Login = msg.Username.getValue(), Password = pass});
if (resp != null && resp.IsValid)
_token = resp.Token;
else
throw new RejectLogon("Logon rejected " + resp?.Reason ?? string.Empty);
}
catch (RejectLogon)
{
throw;
}
catch (Exception ex)
{
throw new RejectLogon("Logon rejected " + ex.ToString());
}
}
break;
case MsgType.HEARTBEAT:
{
QuickFix.FIX44.Heartbeat hb = (QuickFix.FIX44.Heartbeat)message;
handle_heartbeat(hb, sessionID);
}
break;
default:
log_info("ADMININ: " + message);
break;
}
}
async protected void handle_heartbeat(QuickFix.FIX44.Heartbeat hb, SessionID sessionID)
{
var resp = await _latencyservice.Value.report_async(new bts.metrics.Report { HostName = "BTSFIX_" + sessionID.ToString(),
Timestamp = _clock, User = _user_name });
if (resp.success)
_router.send(hb, sessionID);
}
virtual public void ToAdmin(Message message, SessionID sessionID)
{
Log.assert_d(sessionID.Equals(_sess));
log_info("ADMINOUT: " + message);
}
virtual public void OnCreate(SessionID sessionID)
{
log_info("CREATE");
}
virtual public void OnMessage(QuickFix.FIX44.BusinessMessageReject n, SessionID s)
{
//Log.assert(false, "biz reject wtf " + n.EncodedText.getValue());
Log.FIX.warn(_sess.ToString() + " Business Reject " + n.BusinessRejectReason.getValue() + " " + n.Text.getValue());
}
virtual public void OnMessage(QuickFix.FIX44.News n, SessionID s)
{
log_info("news " + n.EncodedHeadline.getValue());
}
protected void log_info(string message, [CallerFilePath] string file = "", [CallerLineNumber] int line = 0)
{
Log.FIX.info(_sess.ToString() + " " + message, file, line);
}
protected void log_error(string message, [CallerFilePath] string file = "", [CallerLineNumber] int line = 0)
{
Log.FIX.error(_sess.ToString() + " " + message, file, line);
}
protected void send_cancel_reject(SessionID sess, string text, Message refmessage)
{
QuickFix.FIX44.OrderCancelReject rej = new QuickFix.FIX44.OrderCancelReject();
if (refmessage is QuickFix.FIX44.OrderCancelRequest cancel)
{
if (cancel.IsSetClOrdID())
rej.SetField(cancel.ClOrdID);
if (cancel.IsSetOrigClOrdID())
rej.SetField(cancel.OrigClOrdID);
if (cancel.IsSetOrderID())
rej.SetField(cancel.OrderID);
rej.CxlRejResponseTo = new CxlRejResponseTo('1');
rej.Text = new Text(text);
_router.send(rej, sess);
}
else if (refmessage is QuickFix.FIX44.OrderCancelReplaceRequest replace)
{
if (replace.IsSetClOrdID())
rej.SetField(replace.ClOrdID);
if (replace.IsSetOrigClOrdID())
rej.SetField(replace.OrigClOrdID);
if (replace.IsSetOrderID())
rej.SetField(replace.OrderID);
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)
{
return btstype == convert_security_type(fixtype);
}
protected QuickFix.Fields.SecurityType convert_security_type(bts.api.SecurityType btstype)
{
switch (btstype)
{
case bts.api.SecurityType.Future:
return new QuickFix.Fields.SecurityType("FUT");
case bts.api.SecurityType.Option:
return new QuickFix.Fields.SecurityType("OPT");
case bts.api.SecurityType.Spread:
return new QuickFix.Fields.SecurityType("MLEG");
case bts.api.SecurityType.Stock:
return new QuickFix.Fields.SecurityType("CS");
case bts.api.SecurityType.Synthetic:
return new QuickFix.Fields.SecurityType("SYNTH");
default:
return new QuickFix.Fields.SecurityType();
}
}
protected bts.api.SecurityType convert_security_type(QuickFix.Fields.SecurityType fixtype)
{
switch (fixtype.getValue())
{
case "FUT":
return bts.api.SecurityType.Future;
case "OPT":
return bts.api.SecurityType.Option;
case "MLEG":
return bts.api.SecurityType.Spread;
case "CS":
return bts.api.SecurityType.Stock;
case "SYNTH":
return bts.api.SecurityType.Synthetic;
default:
return bts.api.SecurityType.Unset;
}
}
protected bool exchanges_equal(bts.api.Venue btstype, QuickFix.Fields.SecurityExchange fixtype)
{
return btstype == convert_exchange(fixtype);
}
protected QuickFix.Fields.SecurityExchange convert_exchange(bts.api.Venue btstype)
{
switch (btstype)
{
case bts.api.Venue.Bts:
return new QuickFix.Fields.SecurityExchange("BTS");
case bts.api.Venue.Cboe:
return new QuickFix.Fields.SecurityExchange("XCBO");
case bts.api.Venue.Cboecfe:
return new QuickFix.Fields.SecurityExchange("XCBF");
case bts.api.Venue.Glbx:
return new QuickFix.Fields.SecurityExchange("XCME");
case bts.api.Venue.Ice:
return new QuickFix.Fields.SecurityExchange("IEPA");
case bts.api.Venue.Sim:
return new QuickFix.Fields.SecurityExchange("SIM");
default:
return new QuickFix.Fields.SecurityExchange();
}
}
protected bts.api.Venue convert_exchange(QuickFix.Fields.SecurityExchange fixtype)
{
switch (fixtype.getValue())
{
case "BTS":
return bts.api.Venue.Bts;
case "XCBO":
return bts.api.Venue.Cboe;
case "XCBF":
return bts.api.Venue.Cboecfe;
case "GLBX":
case "XCME":
case "XCBT":
case "XCEC":
case "XNYM":
return bts.api.Venue.Glbx;
case "IEPA":
case "IFUS":
case "IFEU":
case "IFLL":
return bts.api.Venue.Ice;
case "SIM":
return bts.api.Venue.Sim;
default:
return bts.api.Venue.Unset;
}
}
protected QuickFix.Fields.OrdStatus translate_status(in bts.api.orderman.OrderStateImmutable state,
ref bts.api.orderman.NativeOrderStateImmutable? native)
{
native = null;
if (state.HasMarket && state.Market.HasNativeState && state.Market.NativeState.NativeStatus != NativeOrderStatus.Unacknowledged)
{
native = state.Market.NativeState;
return new OrdStatus((char)native?.NativeStatus);
}
else if (state.HasLimit && state.Limit.HasNativeState && state.Limit.NativeState.NativeStatus != NativeOrderStatus.Unacknowledged)
{
native = state.Limit.NativeState;
return new OrdStatus((char)native?.NativeStatus);
}
else if (state.HasStop && state.Stop.HasNativeState && state.Stop.NativeState.NativeStatus != NativeOrderStatus.Unacknowledged)
{
native = state.Stop.NativeState;
return new OrdStatus((char)native?.NativeStatus);
}
else if (state.HasStopLimit && state.StopLimit.HasNativeState && state.StopLimit.NativeState.NativeStatus != NativeOrderStatus.Unacknowledged)
{
native = state.StopLimit.NativeState;
return new OrdStatus((char)native?.NativeStatus);
}
else
{
switch (state.Status)
{
case OrderStatus.Canceled:
return new OrdStatus(OrdStatus.CANCELED);
case OrderStatus.Completed:
return new OrdStatus(OrdStatus.FILLED);
case OrderStatus.Disconnected:
return new OrdStatus(OrdStatus.STOPPED);
case OrderStatus.Error:
return new OrdStatus(OrdStatus.REJECTED);
case OrderStatus.Inactive:
return new OrdStatus(OrdStatus.PENDING_NEW);
case OrderStatus.PendingWorking:
return new OrdStatus(OrdStatus.PENDING_NEW);
case OrderStatus.RejectedBySpark:
return new OrdStatus(OrdStatus.REJECTED);
case OrderStatus.Working:
{
if (state.FilledQuantity < state.Quantity)
return new OrdStatus(OrdStatus.PARTIALLY_FILLED);
else
return new OrdStatus(OrdStatus.NEW);
}
default:
return new OrdStatus();
}
}
}
protected uint lookup_account(string acct)
{
if (_admin_data.HasValue)
{
var ac = _admin_data.Value.Accounts.Where(x => x.Name == acct).TryFirst();
if(ac.HasValue)
return ac.Value.Id;
}
throw new IncorrectTagValue(new Account().Tag);
}
protected uint lookup_user(string user)
{
if (_admin_data.HasValue)
{
var ac = _admin_data.Value.Users.Where(x => x.Name == user).TryFirst();
if (ac.HasValue)
return ac.Value.Id;
}
throw new IncorrectTagValue(new Username().Tag);
}
}
}
+42
View File
@@ -0,0 +1,42 @@
#http://www.quickfixengine.org/quickfix/doc/html/configuration.html
#https://www.onixs.biz/fix-dictionary.html
[DEFAULT]
ConnectionType=acceptor
SocketAcceptPort=5001
SocketReuseAddress=Y
StartTime=00:00:00
EndTime=00:00:00
FileLogPath=log
UseDataDictionary=Y
ResetOnLogon=Y
ResetOnLogout=Y
ResetOnDisconnect=Y
HeartBtInt=30
LogonTimeout=30
SSLEnable=N
# SSLEnable=Y
# # It is recommended to install the certificate and refer to it by name instead of using filename + password
# SSLCertificate=QuickFixn-TestServer.pfx
# SSLCertificatePassword=QuickFixn-TestServer
# # For production refer to certificate by name instead: SSLCertificate=CN=QuickFixn-TestServer
# SSLCACertificate=QuickFixn-TestCA.cer
# SSLCheckCertificateRevocation=N
[SESSION]
BeginString=FIX.4.4
SenderCompID=SPARK
TargetCompID=CLIENT1
FileStorePath=store
DataDictionary=./spec/fix/FIX44.xml
[SESSION]
BeginString=FIX.4.4
SenderCompID=SPARK
TargetCompID=CLIENT2
FileStorePath=store
DataDictionary=./spec/fix/FIX44.xml
+41
View File
@@ -0,0 +1,41 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<Authors>Blue Trading Systems</Authors>
<Company>Blue Trading Systems</Company>
<Product>Spark</Product>
<Description />
<Platforms>x64</Platforms>
<PlatformTarget>AnyCPU</PlatformTarget>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<WarningsAsErrors />
<LangVersion>7.2</LangVersion>
<Version>1.0.0</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Google.Protobuf" Version="3.6.1" />
<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="QuickFix.Net.NETCore" Version="1.8.1" />
<PackageReference Include="QuickFix.Net.NETCore.FIX44" Version="1.8.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../spark_api/spark_api.csproj"/>
<ProjectReference Include="../spark_core/spark_core.csproj"/>
</ItemGroup>
<Target Name="copy_fix" AfterTargets="PostBuildEvent" >
<Copy SourceFiles="./spark_fix.cfg" DestinationFolder="$(OutputPath)\" SkipUnchangedFiles="true" />
<Copy SourceFiles="./spec/fix/FIX44.xml" DestinationFolder="$(OutputPath)/spec/fix/" SkipUnchangedFiles="true" />
</Target>
<Target Name="copy_fix471" AfterTargets="PostBuildEvent" >
<Copy SourceFiles="./spark_fix.cfg" DestinationFolder="$(OutputPath)/../net471" SkipUnchangedFiles="true" />
<Copy SourceFiles="./spec/fix/FIX44.xml" DestinationFolder="$(OutputPath)/../net471/spec/fix/" SkipUnchangedFiles="true" />
</Target>
</Project>
+828
View File
@@ -0,0 +1,828 @@
<fix major="4" minor="0">
<header>
<field name="BeginString" required="Y"/>
<field name="BodyLength" required="Y"/>
<field name="MsgType" required="Y"/>
<field name="SenderCompID" required="Y"/>
<field name="TargetCompID" required="Y"/>
<field name="OnBehalfOfCompID" required="N"/>
<field name="DeliverToCompID" required="N"/>
<field name="SecureDataLen" required="N"/>
<field name="SecureData" required="N"/>
<field name="MsgSeqNum" required="Y"/>
<field name="SenderSubID" required="N"/>
<field name="TargetSubID" required="N"/>
<field name="OnBehalfOfSubID" required="N"/>
<field name="DeliverToSubID" required="N"/>
<field name="PossDupFlag" required="N"/>
<field name="PossResend" required="N"/>
<field name="SendingTime" required="Y"/>
<field name="OrigSendingTime" required="N"/>
</header>
<trailer>
<field name="SignatureLength" required="N"/>
<field name="Signature" required="N"/>
<field name="CheckSum" required="Y"/>
</trailer>
<messages>
<message name="Heartbeat" msgtype="0" msgcat="admin">
<field name="TestReqID" required="N"/>
</message>
<message name="Logon" msgtype="A" msgcat="admin">
<field name="EncryptMethod" required="Y"/>
<field name="HeartBtInt" required="Y"/>
<field name="RawDataLength" required="N"/>
<field name="RawData" required="N"/>
</message>
<message name="TestRequest" msgtype="1" msgcat="admin">
<field name="TestReqID" required="Y"/>
</message>
<message name="ResendRequest" msgtype="2" msgcat="admin">
<field name="BeginSeqNo" required="Y"/>
<field name="EndSeqNo" required="Y"/>
</message>
<message name="Reject" msgtype="3" msgcat="admin">
<field name="RefSeqNum" required="Y"/>
<field name="Text" required="N"/>
</message>
<message name="SequenceReset" msgtype="4" msgcat="admin">
<field name="GapFillFlag" required="N"/>
<field name="NewSeqNo" required="Y"/>
</message>
<message name="Logout" msgtype="5" msgcat="admin">
<field name="Text" required="N"/>
</message>
<message name="Advertisement" msgtype="7" msgcat="app">
<field name="AdvId" required="Y"/>
<field name="AdvTransType" required="Y"/>
<field name="AdvRefID" required="N"/>
<field name="Symbol" required="Y"/>
<field name="SymbolSfx" required="N"/>
<field name="SecurityID" required="N"/>
<field name="IDSource" required="N"/>
<field name="Issuer" required="N"/>
<field name="SecurityDesc" required="N"/>
<field name="AdvSide" required="Y"/>
<field name="Shares" required="Y"/>
<field name="Price" required="N"/>
<field name="Currency" required="N"/>
<field name="TransactTime" required="N"/>
<field name="Text" required="N"/>
</message>
<message name="IndicationofInterest" msgtype="6" msgcat="app">
<field name="IOIid" required="Y"/>
<field name="IOITransType" required="Y"/>
<field name="IOIRefID" required="N"/>
<field name="Symbol" required="Y"/>
<field name="SymbolSfx" required="N"/>
<field name="SecurityID" required="N"/>
<field name="IDSource" required="N"/>
<field name="Issuer" required="N"/>
<field name="SecurityDesc" required="N"/>
<field name="Side" required="Y"/>
<field name="IOIShares" required="Y"/>
<field name="Price" required="N"/>
<field name="Currency" required="N"/>
<field name="ValidUntilTime" required="N"/>
<field name="IOIQltyInd" required="N"/>
<field name="IOIOthSvc" required="N"/>
<field name="IOINaturalFlag" required="N"/>
<field name="IOIQualifier" required="N"/>
<field name="Text" required="N"/>
</message>
<message name="News" msgtype="B" msgcat="app">
<field name="OrigTime" required="N"/>
<field name="Urgency" required="N"/>
<field name="RelatdSym" required="N" repeating="Y"/>
<group name="LinesOfText" required="Y">
<field name="Text" required="Y"/>
</group>
<field name="RawDataLength" required="N"/>
<field name="RawData" required="N"/>
</message>
<message name="Email" msgtype="C" msgcat="app">
<field name="EmailType" required="Y"/>
<field name="OrigTime" required="N"/>
<field name="RelatdSym" required="N" repeating="Y"/>
<field name="OrderID" required="N"/>
<field name="ClOrdID" required="N"/>
<group name="LinesOfText" required="Y">
<field name="Text" required="Y"/>
</group>
<field name="RawDataLength" required="N"/>
<field name="RawData" required="N"/>
</message>
<message name="QuoteRequest" msgtype="R" msgcat="app">
<field name="QuoteReqID" required="Y"/>
<field name="Symbol" required="Y"/>
<field name="SymbolSfx" required="N"/>
<field name="SecurityID" required="N"/>
<field name="IDSource" required="N"/>
<field name="Issuer" required="N"/>
<field name="SecurityDesc" required="N"/>
<field name="PrevClosePx" required="N"/>
<field name="Side" required="N"/>
<field name="OrderQty" required="N"/>
</message>
<message name="Quote" msgtype="S" msgcat="app">
<field name="QuoteReqID" required="N"/>
<field name="QuoteID" required="Y"/>
<field name="Symbol" required="Y"/>
<field name="SymbolSfx" required="N"/>
<field name="SecurityID" required="N"/>
<field name="IDSource" required="N"/>
<field name="Issuer" required="N"/>
<field name="SecurityDesc" required="N"/>
<field name="BidPx" required="Y"/>
<field name="OfferPx" required="N"/>
<field name="BidSize" required="N"/>
<field name="OfferSize" required="N"/>
<field name="ValidUntilTime" required="N"/>
</message>
<message name="NewOrderSingle" msgtype="D" msgcat="app">
<field name="ClOrdID" required="Y"/>
<field name="ClientID" required="N"/>
<field name="ExecBroker" required="N"/>
<field name="Account" required="N"/>
<field name="SettlmntTyp" required="N"/>
<field name="FutSettDate" required="N"/>
<field name="HandlInst" required="Y"/>
<field name="ExecInst" required="N"/>
<field name="MinQty" required="N"/>
<field name="MaxFloor" required="N"/>
<field name="ExDestination" required="N"/>
<field name="ProcessCode" required="N"/>
<field name="Symbol" required="Y"/>
<field name="SymbolSfx" required="N"/>
<field name="SecurityID" required="N"/>
<field name="IDSource" required="N"/>
<field name="Issuer" required="N"/>
<field name="SecurityDesc" required="N"/>
<field name="PrevClosePx" required="N"/>
<field name="Side" required="Y"/>
<field name="LocateReqd" required="N"/>
<field name="OrderQty" required="Y"/>
<field name="OrdType" required="Y"/>
<field name="Price" required="N"/>
<field name="StopPx" required="N"/>
<field name="Currency" required="N"/>
<field name="IOIid" required="N"/>
<field name="QuoteID" required="N"/>
<field name="TimeInForce" required="N"/>
<field name="ExpireTime" required="N"/>
<field name="Commission" required="N"/>
<field name="CommType" required="N"/>
<field name="Rule80A" required="N"/>
<field name="ForexReq" required="N"/>
<field name="SettlCurrency" required="N"/>
<field name="Text" required="N"/>
</message>
<message name="ExecutionReport" msgtype="8" msgcat="app">
<field name="OrderID" required="Y"/>
<field name="ClOrdID" required="N"/>
<field name="ClientID" required="N"/>
<field name="ExecBroker" required="N"/>
<field name="ListID" required="N"/>
<field name="ExecID" required="Y"/>
<field name="ExecTransType" required="Y"/>
<field name="ExecRefID" required="N"/>
<field name="OrdStatus" required="Y"/>
<field name="OrdRejReason" required="N"/>
<field name="Account" required="N"/>
<field name="SettlmntTyp" required="N"/>
<field name="FutSettDate" required="N"/>
<field name="Symbol" required="Y"/>
<field name="SymbolSfx" required="N"/>
<field name="SecurityID" required="N"/>
<field name="IDSource" required="N"/>
<field name="Issuer" required="N"/>
<field name="SecurityDesc" required="N"/>
<field name="Side" required="Y"/>
<field name="OrderQty" required="Y"/>
<field name="OrdType" required="N"/>
<field name="Price" required="N"/>
<field name="StopPx" required="N"/>
<field name="Currency" required="N"/>
<field name="TimeInForce" required="N"/>
<field name="ExpireTime" required="N"/>
<field name="ExecInst" required="N"/>
<field name="Rule80A" required="N"/>
<field name="LastShares" required="Y"/>
<field name="LastPx" required="Y"/>
<field name="LastMkt" required="N"/>
<field name="LastCapacity" required="N"/>
<field name="CumQty" required="Y"/>
<field name="AvgPx" required="Y"/>
<field name="TradeDate" required="N"/>
<field name="TransactTime" required="N"/>
<field name="ReportToExch" required="N"/>
<field name="Commission" required="N"/>
<field name="CommType" required="N"/>
<group name="NoMiscFees" required="N">
<field name="MiscFeeAmt" required="N"/>
<field name="MiscFeeCurr" required="N"/>
<field name="MiscFeeType" required="N"/>
</group>
<field name="NetMoney" required="N"/>
<field name="SettlCurrAmt" required="N"/>
<field name="SettlCurrency" required="N"/>
<field name="Text" required="N"/>
</message>
<message name="DontKnowTrade" msgtype="Q" msgcat="app">
<field name="OrderID" required="N"/>
<field name="ExecID" required="N"/>
<field name="DKReason" required="Y"/>
<field name="Symbol" required="Y"/>
<field name="Side" required="Y"/>
<field name="OrderQty" required="Y"/>
<field name="LastShares" required="Y"/>
<field name="LastPx" required="Y"/>
<field name="Text" required="N"/>
</message>
<message name="OrderCancelReplaceRequest" msgtype="G" msgcat="app">
<field name="OrderID" required="N"/>
<field name="ClientID" required="N"/>
<field name="ExecBroker" required="N"/>
<field name="OrigClOrdID" required="Y"/>
<field name="ClOrdID" required="Y"/>
<field name="ListID" required="N"/>
<field name="Account" required="N"/>
<field name="SettlmntTyp" required="N"/>
<field name="FutSettDate" required="N"/>
<field name="HandlInst" required="Y"/>
<field name="ExecInst" required="N"/>
<field name="MinQty" required="N"/>
<field name="MaxFloor" required="N"/>
<field name="ExDestination" required="N"/>
<field name="Symbol" required="Y"/>
<field name="SymbolSfx" required="N"/>
<field name="SecurityID" required="N"/>
<field name="IDSource" required="N"/>
<field name="Issuer" required="N"/>
<field name="SecurityDesc" required="N"/>
<field name="Side" required="Y"/>
<field name="OrderQty" required="Y"/>
<field name="OrdType" required="Y"/>
<field name="Price" required="N"/>
<field name="StopPx" required="N"/>
<field name="Currency" required="N"/>
<field name="TimeInForce" required="N"/>
<field name="ExpireTime" required="N"/>
<field name="Commission" required="N"/>
<field name="CommType" required="N"/>
<field name="Rule80A" required="N"/>
<field name="ForexReq" required="N"/>
<field name="SettlCurrency" required="N"/>
<field name="Text" required="N"/>
</message>
<message name="OrderCancelRequest" msgtype="F" msgcat="app">
<field name="OrigClOrdID" required="Y"/>
<field name="OrderID" required="N"/>
<field name="ClOrdID" required="Y"/>
<field name="ListID" required="N"/>
<field name="CxlType" required="Y"/>
<field name="ClientID" required="N"/>
<field name="ExecBroker" required="N"/>
<field name="Symbol" required="Y"/>
<field name="SymbolSfx" required="N"/>
<field name="SecurityID" required="N"/>
<field name="IDSource" required="N"/>
<field name="Issuer" required="N"/>
<field name="SecurityDesc" required="N"/>
<field name="Side" required="Y"/>
<field name="OrderQty" required="Y"/>
<field name="Text" required="N"/>
</message>
<message name="OrderCancelReject" msgtype="9" msgcat="app">
<field name="OrderID" required="Y"/>
<field name="ClOrdID" required="Y"/>
<field name="ClientID" required="N"/>
<field name="ExecBroker" required="N"/>
<field name="ListID" required="N"/>
<field name="CxlRejReason" required="N"/>
<field name="Text" required="N"/>
</message>
<message name="OrderStatusRequest" msgtype="H" msgcat="app">
<field name="OrderID" required="N"/>
<field name="ClOrdID" required="Y"/>
<field name="ClientID" required="N"/>
<field name="ExecBroker" required="N"/>
<field name="Symbol" required="Y"/>
<field name="SymbolSfx" required="N"/>
<field name="Issuer" required="N"/>
<field name="SecurityDesc" required="N"/>
<field name="Side" required="Y"/>
</message>
<message name="Allocation" msgtype="J" msgcat="app">
<field name="AllocID" required="Y"/>
<field name="AllocTransType" required="Y"/>
<field name="RefAllocID" required="N"/>
<group name="NoOrders" required="Y">
<field name="ClOrdID" required="Y"/>
<field name="OrderID" required="N"/>
<field name="ListID" required="N"/>
<field name="WaveNo" required="N"/>
</group>
<group name="NoExecs" required="N">
<field name="ExecID" required="N"/>
<field name="LastShares" required="N"/>
<field name="LastPx" required="N"/>
<field name="LastMkt" required="N"/>
</group>
<field name="Side" required="Y"/>
<field name="Symbol" required="Y"/>
<field name="SymbolSfx" required="N"/>
<field name="SecurityID" required="N"/>
<field name="IDSource" required="N"/>
<field name="Issuer" required="N"/>
<field name="SecurityDesc" required="N"/>
<field name="Shares" required="Y"/>
<field name="AvgPx" required="Y"/>
<field name="Currency" required="N"/>
<field name="AvgPrxPrecision" required="N"/>
<field name="TradeDate" required="Y"/>
<field name="TransactTime" required="N"/>
<field name="SettlmntTyp" required="N"/>
<field name="FutSettDate" required="N"/>
<field name="NetMoney" required="N"/>
<group name="NoMiscFees" required="N">
<field name="MiscFeeAmt" required="N"/>
<field name="MiscFeeCurr" required="N"/>
<field name="MiscFeeType" required="N"/>
</group>
<field name="SettlCurrAmt" required="N"/>
<field name="SettlCurrency" required="N"/>
<field name="OpenClose" required="N"/>
<field name="Text" required="N"/>
<group name="NoAllocs" required="Y">
<field name="AllocAccount" required="Y"/>
<field name="AllocShares" required="Y"/>
<field name="ProcessCode" required="N"/>
<field name="ExecBroker" required="N"/>
<field name="ClientID" required="N"/>
<field name="Commission" required="N"/>
<field name="CommType" required="N"/>
<group name="NoDlvyInst" required="N">
<field name="BrokerOfCredit" required="N"/>
<field name="DlvyInst" required="N"/>
</group>
</group>
</message>
<message name="AllocationACK" msgtype="P" msgcat="app">
<field name="ClientID" required="N"/>
<field name="ExecBroker" required="N"/>
<field name="AllocID" required="Y"/>
<field name="TradeDate" required="Y"/>
<field name="TransactTime" required="N"/>
<field name="AllocStatus" required="Y"/>
<field name="AllocRejCode" required="N"/>
<field name="Text" required="N"/>
</message>
<message name="NewOrderList" msgtype="E" msgcat="app">
<field name="ListID" required="Y"/>
<field name="WaveNo" required="N"/>
<field name="ListSeqNo" required="Y"/>
<field name="ListNoOrds" required="Y"/>
<field name="ListExecInst" required="N"/>
<field name="ClOrdID" required="Y"/>
<field name="ClientID" required="N"/>
<field name="ExecBroker" required="N"/>
<field name="Account" required="N"/>
<field name="SettlmntTyp" required="N"/>
<field name="FutSettDate" required="N"/>
<field name="HandlInst" required="Y"/>
<field name="ExecInst" required="N"/>
<field name="MinQty" required="N"/>
<field name="MaxFloor" required="N"/>
<field name="ExDestination" required="N"/>
<field name="ProcessCode" required="N"/>
<field name="Symbol" required="Y"/>
<field name="SymbolSfx" required="N"/>
<field name="SecurityID" required="N"/>
<field name="IDSource" required="N"/>
<field name="Issuer" required="N"/>
<field name="SecurityDesc" required="N"/>
<field name="PrevClosePx" required="N"/>
<field name="Side" required="Y"/>
<field name="LocateReqd" required="N"/>
<field name="OrderQty" required="Y"/>
<field name="OrdType" required="Y"/>
<field name="Price" required="N"/>
<field name="StopPx" required="N"/>
<field name="Currency" required="N"/>
<field name="TimeInForce" required="N"/>
<field name="ExpireTime" required="N"/>
<field name="Commission" required="N"/>
<field name="CommType" required="N"/>
<field name="Rule80A" required="N"/>
<field name="ForexReq" required="N"/>
<field name="SettlCurrency" required="N"/>
<field name="Text" required="N"/>
</message>
<message name="ListStatus" msgtype="N" msgcat="app">
<field name="ListID" required="Y"/>
<field name="WaveNo" required="N"/>
<field name="NoRpts" required="Y"/>
<field name="RptSeq" required="Y"/>
<group name="NoOrders" required="Y">
<field name="ClOrdID" required="Y"/>
<field name="CumQty" required="Y"/>
<field name="CxlQty" required="Y"/>
<field name="AvgPx" required="Y"/>
</group>
</message>
<message name="ListExecute" msgtype="L" msgcat="app">
<field name="ListID" required="Y"/>
<field name="WaveNo" required="N"/>
<field name="Text" required="N"/>
</message>
<message name="ListCancelRequest" msgtype="K" msgcat="app">
<field name="ListID" required="Y"/>
<field name="WaveNo" required="N"/>
<field name="Text" required="N"/>
</message>
<message name="ListStatusRequest" msgtype="M" msgcat="app">
<field name="ListID" required="Y"/>
<field name="WaveNo" required="N"/>
<field name="Text" required="N"/>
</message>
</messages>
<fields>
<field number="1" name="Account" type="STRING"/>
<field number="2" name="AdvId" type="INT"/>
<field number="3" name="AdvRefID" type="INT"/>
<field number="4" name="AdvSide" type="STRING">
<value enum="B" description="BUY"/>
<value enum="S" description="SELL"/>
<value enum="X" description="CROSS"/>
<value enum="T" description="TRADE"/>
</field>
<field number="5" name="AdvTransType" type="STRING">
<value enum="N" description="NEW"/>
<value enum="C" description="CANCEL"/>
<value enum="R" description="REPLACE"/>
</field>
<field number="6" name="AvgPx" type="FLOAT"/>
<field number="7" name="BeginSeqNo" type="INT"/>
<field number="8" name="BeginString" type="STRING"/>
<field number="9" name="BodyLength" type="INT"/>
<field number="10" name="CheckSum" type="STRING"/>
<field number="11" name="ClOrdID" type="STRING"/>
<field number="12" name="Commission" type="FLOAT"/>
<field number="13" name="CommType" type="STRING">
<value enum="1" description="PER_SHARE"/>
<value enum="2" description="PERCENTAGE"/>
<value enum="3" description="ABSOLUTE"/>
</field>
<field number="14" name="CumQty" type="INT"/>
<field number="15" name="Currency" type="STRING"/>
<field number="16" name="EndSeqNo" type="INT"/>
<field number="17" name="ExecID" type="INT"/>
<field number="18" name="ExecInst" type="MULTIPLEVALUESTRING">
<value enum="1" description="NOT_HELD"/>
<value enum="2" description="WORK"/>
<value enum="3" description="GO_ALONG"/>
<value enum="4" description="OVER_THE_DAY"/>
<value enum="5" description="HELD"/>
<value enum="6" description="PARTICIPATE_DONT_INITIATE"/>
<value enum="7" description="STRICT_SCALE"/>
<value enum="8" description="TRY_TO_SCALE"/>
<value enum="9" description="STAY_ON_BIDSIDE"/>
<value enum="0" description="STAY_ON_OFFERSIDE"/>
<value enum="A" description="NO_CROSS"/>
<value enum="B" description="OK_TO_CROSS"/>
<value enum="C" description="CALL_FIRST"/>
<value enum="D" description="PERCENT_OF_VOLUME"/>
<value enum="E" description="DO_NOT_INCREASE_DNI"/>
<value enum="F" description="DO_NOT_REDUCE_DNR"/>
<value enum="G" description="ALL_OR_NONE_AON"/>
<value enum="I" description="INSTITUTIONS_ONLY"/>
<value enum="L" description="LAST_PEG"/>
<value enum="M" description="MIDPRICE_PEG"/>
<value enum="N" description="NONNEGOTIABLE"/>
<value enum="O" description="OPENING_PEG"/>
<value enum="P" description="MARKET_PEG"/>
<value enum="R" description="PRIMARY_PEG"/>
<value enum="S" description="SUSPEND"/>
</field>
<field number="19" name="ExecRefID" type="INT"/>
<field number="20" name="ExecTransType" type="STRING">
<value enum="0" description="NEW"/>
<value enum="1" description="CANCEL"/>
<value enum="2" description="CORRECT"/>
<value enum="3" description="STATUS"/>
</field>
<field number="21" name="HandlInst" type="STRING">
<value enum="1" description="AUTOMATED_EXECUTION_ORDER_PRIVATE_NO_BROKER_INTERVENTION"/>
<value enum="2" description="AUTOMATED_EXECUTION_ORDER_PUBLIC_BROKER_INTERVENTION_OK"/>
<value enum="3" description="MANUAL_ORDER_BEST_EXECUTION"/>
</field>
<field number="22" name="IDSource" type="STRING">
<value enum="1" description="CUSIP"/>
<value enum="2" description="SEDOL"/>
<value enum="3" description="QUIK"/>
<value enum="4" description="ISIN_NUMBER"/>
<value enum="5" description="RIC_CODE"/>
</field>
<field number="23" name="IOIid" type="INT"/>
<field number="24" name="IOIOthSvc" type="STRING"/>
<field number="25" name="IOIQltyInd" type="STRING">
<value enum="L" description="LOW"/>
<value enum="M" description="MEDIUM"/>
<value enum="H" description="HIGH"/>
</field>
<field number="26" name="IOIRefID" type="INT"/>
<field number="27" name="IOIShares" type="STRING"/>
<field number="28" name="IOITransType" type="STRING">
<value enum="N" description="NEW"/>
<value enum="C" description="CANCEL"/>
<value enum="R" description="REPLACE"/>
</field>
<field number="29" name="LastCapacity" type="STRING">
<value enum="1" description="AGENT"/>
<value enum="2" description="CROSS_AS_AGENT"/>
<value enum="3" description="CROSS_AS_PRINCIPAL"/>
<value enum="4" description="PRINCIPAL"/>
</field>
<field number="30" name="LastMkt" type="STRING"/>
<field number="31" name="LastPx" type="FLOAT"/>
<field number="32" name="LastShares" type="INT"/>
<field number="33" name="LinesOfText" type="INT"/>
<field number="34" name="MsgSeqNum" type="INT"/>
<field number="35" name="MsgType" type="STRING"/>
<field number="36" name="NewSeqNo" type="INT"/>
<field number="37" name="OrderID" type="STRING"/>
<field number="38" name="OrderQty" type="INT"/>
<field number="39" name="OrdStatus" type="STRING">
<value enum="0" description="NEW"/>
<value enum="1" description="PARTIALLY_FILLED"/>
<value enum="2" description="FILLED"/>
<value enum="3" description="DONE_FOR_DAY"/>
<value enum="4" description="CANCELED"/>
<value enum="5" description="REPLACED"/>
<value enum="6" description="PENDING_CANCELREPLACE"/>
<value enum="7" description="STOPPED"/>
<value enum="8" description="REJECTED"/>
<value enum="9" description="SUSPENDED"/>
<value enum="A" description="PENDING_NEW"/>
<value enum="B" description="CALCULATED"/>
<value enum="C" description="EXPIRED"/>
</field>
<field number="40" name="OrdType" type="STRING">
<value enum="1" description="MARKET"/>
<value enum="2" description="LIMIT"/>
<value enum="3" description="STOP"/>
<value enum="4" description="STOP_LIMIT"/>
<value enum="5" description="MARKET_ON_CLOSE"/>
<value enum="6" description="WITH_OR_WITHOUT"/>
<value enum="7" description="LIMIT_OR_BETTER"/>
<value enum="8" description="LIMIT_WITH_OR_WITHOUT"/>
<value enum="9" description="ON_BASIS"/>
<value enum="A" description="ON_CLOSE"/>
<value enum="B" description="LIMIT_ON_CLOSE"/>
<value enum="C" description="FOREX"/>
<value enum="D" description="PREVIOUSLY_QUOTED"/>
<value enum="E" description="PREVIOUSLY_INDICATED"/>
<value enum="P" description="PEGGED"/>
</field>
<field number="41" name="OrigClOrdID" type="STRING"/>
<field number="42" name="OrigTime" type="TIME"/>
<field number="43" name="PossDupFlag" type="STRING">
<value enum="Y" description="POSSIBLE_DUPLICATE"/>
<value enum="N" description="ORIGINAL_TRANSMISSION"/>
</field>
<field number="44" name="Price" type="FLOAT"/>
<field number="45" name="RefSeqNum" type="INT"/>
<field number="46" name="RelatdSym" type="STRING"/>
<field number="47" name="Rule80A" type="STRING">
<value enum="A" description="AGENCY_SINGLE_ORDER"/>
<value enum="D" description="PROGRAM_ORDER_INDEX_ARB_FOR_MEMBER_FIRMORG"/>
<value enum="C" description="PROGRAM_ORDER_NONINDEX_ARB_FOR_MEMBER_FIRMORG"/>
<value enum="J" description="PROGRAM_ORDER_INDEX_ARB_FOR_INDIVIDUAL_CUSTOMER"/>
<value enum="K" description="PROGRAM_ORDER_NONINDEX_ARB_FOR_INDIVIDUAL_CUSTOMER"/>
<value enum="U" description="PROGRAM_ORDER_INDEX_ARB_FOR_OTHER_AGENCY"/>
<value enum="Y" description="PROGRAM_ORDER_NONINDEX_ARB_FOR_OTHER_AGENCY"/>
<value enum="M" description="PROGRAM_ORDER_INDEX_ARB_FOR_OTHER_MEMBER"/>
<value enum="N" description="PROGRAM_ORDER_NONINDEX_ARB_FOR_OTHER_MEMBER"/>
<value enum="W" description="ALL_OTHER_ORDERS_AS_AGENT_FOR_OTHER_MEMBER"/>
</field>
<field number="48" name="SecurityID" type="STRING"/>
<field number="49" name="SenderCompID" type="STRING"/>
<field number="50" name="SenderSubID" type="STRING"/>
<field number="52" name="SendingTime" type="TIME"/>
<field number="53" name="Shares" type="INT"/>
<field number="54" name="Side" type="STRING">
<value enum="1" description="BUY"/>
<value enum="2" description="SELL"/>
<value enum="3" description="BUY_MINUS"/>
<value enum="4" description="SELL_PLUS"/>
<value enum="5" description="SELL_SHORT"/>
<value enum="6" description="SELL_SHORT_EXEMPT"/>
</field>
<field number="55" name="Symbol" type="STRING"/>
<field number="56" name="TargetCompID" type="STRING"/>
<field number="57" name="TargetSubID" type="STRING"/>
<field number="58" name="Text" type="STRING"/>
<field number="59" name="TimeInForce" type="STRING">
<value enum="0" description="DAY"/>
<value enum="1" description="GOOD_TILL_CANCEL"/>
<value enum="2" description="AT_THE_OPENING"/>
<value enum="3" description="IMMEDIATE_OR_CANCEL"/>
<value enum="4" description="FILL_OR_KILL"/>
<value enum="5" description="GOOD_TILL_CROSSING"/>
<value enum="6" description="GOOD_TILL_DATE"/>
</field>
<field number="60" name="TransactTime" type="TIME"/>
<field number="61" name="Urgency" type="STRING">
<value enum="0" description="NORMAL"/>
<value enum="1" description="FLASH"/>
<value enum="2" description="BACKGROUND"/>
</field>
<field number="62" name="ValidUntilTime" type="TIME"/>
<field number="63" name="SettlmntTyp" type="STRING">
<value enum="0" description="REGULAR"/>
<value enum="1" description="CASH"/>
<value enum="2" description="NEXT_DAY"/>
<value enum="3" description="TPLUS2"/>
<value enum="4" description="TPLUS3"/>
<value enum="5" description="TPLUS4"/>
<value enum="6" description="FUTURE"/>
<value enum="7" description="WHEN_ISSUED"/>
<value enum="8" description="SELLERS_OPTION"/>
<value enum="9" description="TPLUS5"/>
</field>
<field number="64" name="FutSettDate" type="DATE"/>
<field number="65" name="SymbolSfx" type="STRING"/>
<field number="66" name="ListID" type="STRING"/>
<field number="67" name="ListSeqNo" type="INT"/>
<field number="68" name="ListNoOrds" type="INT"/>
<field number="69" name="ListExecInst" type="STRING"/>
<field number="70" name="AllocID" type="INT"/>
<field number="71" name="AllocTransType" type="STRING">
<value enum="0" description="NEW"/>
<value enum="1" description="REPLACE"/>
<value enum="2" description="CANCEL"/>
</field>
<field number="72" name="RefAllocID" type="INT"/>
<field number="73" name="NoOrders" type="INT"/>
<field number="74" name="AvgPrxPrecision" type="INT"/>
<field number="75" name="TradeDate" type="DATE"/>
<field number="76" name="ExecBroker" type="STRING"/>
<field number="77" name="OpenClose" type="STRING"/>
<field number="78" name="NoAllocs" type="INT"/>
<field number="79" name="AllocAccount" type="STRING"/>
<field number="80" name="AllocShares" type="INT"/>
<field number="81" name="ProcessCode" type="STRING">
<value enum="0" description="REGULAR"/>
<value enum="1" description="SOFT_DOLLAR"/>
<value enum="2" description="STEPIN"/>
<value enum="3" description="STEPOUT"/>
<value enum="4" description="SOFTDOLLAR_STEPIN"/>
<value enum="5" description="SOFTDOLLAR_STEPOUT"/>
<value enum="6" description="PLAN_SPONSOR"/>
</field>
<field number="82" name="NoRpts" type="INT"/>
<field number="83" name="RptSeq" type="INT"/>
<field number="84" name="CxlQty" type="INT"/>
<field number="85" name="NoDlvyInst" type="INT"/>
<field number="86" name="DlvyInst" type="STRING"/>
<field number="87" name="AllocStatus" type="INT">
<value enum="0" description="ACCEPTED"/>
<value enum="1" description="REJECTED"/>
<value enum="2" description="PARTIAL_ACCEPT"/>
<value enum="3" description="RECEIVED"/>
</field>
<field number="88" name="AllocRejCode" type="INT">
<value enum="0" description="UNKNOWN_ACCOUNT"/>
<value enum="1" description="INCORRECT_QUANTITY"/>
<value enum="2" description="INCORRECT_AVERAGE_PRICE"/>
<value enum="3" description="UNKNOWN_EXECUTING_BROKER_MNEMONIC"/>
<value enum="4" description="COMMISSION_DIFFERENCE"/>
<value enum="5" description="UNKNOWN_ORDERID"/>
<value enum="6" description="UNKNOWN_LISTID"/>
<value enum="7" description="OTHER"/>
</field>
<field number="89" name="Signature" type="DATA"/>
<field number="90" name="SecureDataLen" type="INT"/>
<field number="91" name="SecureData" type="DATA"/>
<field number="92" name="BrokerOfCredit" type="STRING"/>
<field number="93" name="SignatureLength" type="INT"/>
<field number="94" name="EmailType" type="STRING">
<value enum="0" description="NEW"/>
<value enum="1" description="REPLY"/>
<value enum="2" description="ADMIN_REPLY"/>
</field>
<field number="95" name="RawDataLength" type="INT"/>
<field number="96" name="RawData" type="DATA"/>
<field number="97" name="PossResend" type="STRING"/>
<field number="98" name="EncryptMethod" type="INT">
<value enum="0" description="NONE_OTHER"/>
<value enum="1" description="PKCS"/>
<value enum="2" description="DES"/>
<value enum="3" description="PKCSDES"/>
<value enum="4" description="PGPDES"/>
<value enum="5" description="PGPDESMD5"/>
<value enum="6" description="PEMDESMD5"/>
</field>
<field number="99" name="StopPx" type="FLOAT"/>
<field number="100" name="ExDestination" type="STRING">
<value enum="0" description="NONE"/>
<value enum="4" description="POSIT"/>
</field>
<field number="102" name="CxlRejReason" type="INT">
<value enum="0" description="TOO_LATE_TO_CANCEL"/>
<value enum="1" description="UNKNOWN_ORDER"/>
</field>
<field number="103" name="OrdRejReason" type="INT">
<value enum="0" description="BROKER_OPTION"/>
<value enum="1" description="UNKNOWN_SYMBOL"/>
<value enum="2" description="EXCHANGE_CLOSED"/>
<value enum="3" description="ORDER_EXCEEDS_LIMIT"/>
<value enum="4" description="TOO_LATE_TO_ENTER"/>
</field>
<field number="104" name="IOIQualifier" type="STRING">
<value enum="X" description="CROSSING_OPPORTUNITY"/>
<value enum="O" description="AT_THE_OPEN"/>
<value enum="M" description="MORE_BEHIND"/>
<value enum="P" description="TAKING_A_POSITION"/>
<value enum="V" description="VERSUS"/>
<value enum="Q" description="CURRENT_QUOTE"/>
<value enum="C" description="AT_THE_CLOSE"/>
<value enum="S" description="PORTFOLIO_SHOWN"/>
<value enum="I" description="IN_TOUCH_WITH"/>
<value enum="W" description="INDICATION_WORKING_AWAY"/>
<value enum="A" description="ALL_OR_NONE"/>
<value enum="L" description="LIMIT"/>
<value enum="T" description="THROUGH_THE_DAY"/>
</field>
<field number="105" name="WaveNo" type="STRING"/>
<field number="106" name="Issuer" type="STRING"/>
<field number="107" name="SecurityDesc" type="STRING"/>
<field number="108" name="HeartBtInt" type="INT"/>
<field number="109" name="ClientID" type="STRING"/>
<field number="110" name="MinQty" type="INT"/>
<field number="111" name="MaxFloor" type="INT"/>
<field number="112" name="TestReqID" type="STRING"/>
<field number="113" name="ReportToExch" type="STRING">
<value enum="Y" description="YES"/>
<value enum="N" description="NO"/>
</field>
<field number="114" name="LocateReqd" type="STRING">
<value enum="Y" description="YES"/>
<value enum="N" description="NO"/>
</field>
<field number="115" name="OnBehalfOfCompID" type="STRING"/>
<field number="116" name="OnBehalfOfSubID" type="STRING"/>
<field number="117" name="QuoteID" type="STRING"/>
<field number="118" name="NetMoney" type="FLOAT"/>
<field number="119" name="SettlCurrAmt" type="FLOAT"/>
<field number="120" name="SettlCurrency" type="STRING"/>
<field number="121" name="ForexReq" type="STRING">
<value enum="Y" description="YES"/>
<value enum="N" description="NO"/>
</field>
<field number="122" name="OrigSendingTime" type="TIME"/>
<field number="123" name="GapFillFlag" type="STRING">
<value enum="Y" description="GAP_FILL_MESSAGE_MSGSEQNUM_FIELD_VALID"/>
<value enum="N" description="SEQUENCE_RESET_IGNORE_MSGSEQNUM"/>
</field>
<field number="124" name="NoExecs" type="INT"/>
<field number="125" name="CxlType" type="STRING">
<value enum="P" description="PARTIAL_CANCEL"/>
<value enum="F" description="FULL_REMAINING_QUANTITY"/>
</field>
<field number="126" name="ExpireTime" type="TIME"/>
<field number="127" name="DKReason" type="STRING">
<value enum="A" description="UNKNOWN_SYMBOL"/>
<value enum="B" description="WRONG_SIDE"/>
<value enum="C" description="QUANTITY_EXCEEDS_ORDER"/>
<value enum="D" description="NO_MATCHING_ORDER"/>
<value enum="E" description="PRICE_EXCEEDS_LIMIT"/>
<value enum="Z" description="OTHER" />
</field>
<field number="128" name="DeliverToCompID" type="STRING"/>
<field number="129" name="DeliverToSubID" type="STRING"/>
<field number="130" name="IOINaturalFlag" type="STRING">
<value enum="Y" description="NATURAL"/>
<value enum="N" description="NOT_NATURAL"/>
</field>
<field number="131" name="QuoteReqID" type="STRING"/>
<field number="132" name="BidPx" type="FLOAT"/>
<field number="133" name="OfferPx" type="FLOAT"/>
<field number="134" name="BidSize" type="INT"/>
<field number="135" name="OfferSize" type="INT"/>
<field number="136" name="NoMiscFees" type="INT"/>
<field number="137" name="MiscFeeAmt" type="FLOAT"/>
<field number="138" name="MiscFeeCurr" type="STRING"/>
<field number="139" name="MiscFeeType" type="STRING">
<value enum="1" description="REGULATORY"/>
<value enum="2" description="TAX"/>
<value enum="3" description="LOCAL_COMMISSION"/>
<value enum="4" description="EXCHANGE_FEES"/>
<value enum="5" description="STAMP"/>
<value enum="6" description="LEVY"/>
<value enum="7" description="OTHER"/>
</field>
<field number="140" name="PrevClosePx" type="FLOAT"/>
</fields>
</fix>
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+313
View File
@@ -0,0 +1,313 @@
<?xml version='1.0' encoding='UTF-8'?>
<fix type='FIXT' major='1' minor='1' servicepack='0'>
<header>
<field name='BeginString' required='Y'/>
<field name='BodyLength' required='Y'/>
<field name='MsgType' required='Y'/>
<field name='SenderCompID' required='Y'/>
<field name='TargetCompID' required='Y'/>
<field name='OnBehalfOfCompID' required='N'/>
<field name='DeliverToCompID' required='N'/>
<field name='SecureDataLen' required='N'/>
<field name='SecureData' required='N'/>
<field name='MsgSeqNum' required='Y'/>
<field name='SenderSubID' required='N'/>
<field name='SenderLocationID' required='N'/>
<field name='TargetSubID' required='N'/>
<field name='TargetLocationID' required='N'/>
<field name='OnBehalfOfSubID' required='N'/>
<field name='OnBehalfOfLocationID' required='N'/>
<field name='DeliverToSubID' required='N'/>
<field name='DeliverToLocationID' required='N'/>
<field name='PossDupFlag' required='N'/>
<field name='PossResend' required='N'/>
<field name='SendingTime' required='Y'/>
<field name='OrigSendingTime' required='N'/>
<field name='XmlDataLen' required='N'/>
<field name='XmlData' required='N'/>
<field name='MessageEncoding' required='N'/>
<field name='LastMsgSeqNumProcessed' required='N'/>
<component name='HopGrp' required='N'/>
<field name='ApplVerID' required='N'/>
<field name='CstmApplVerID' required='N'/>
</header>
<trailer>
<field name='SignatureLength' required='N'/>
<field name='Signature' required='N'/>
<field name='CheckSum' required='Y'/>
</trailer>
<messages>
<message msgcat='admin' msgtype='0' name='Heartbeat'>
<field name='TestReqID' required='N'/>
</message>
<message msgcat='admin' msgtype='1' name='TestRequest'>
<field name='TestReqID' required='Y'/>
</message>
<message msgcat='admin' msgtype='2' name='ResendRequest'>
<field name='BeginSeqNo' required='Y'/>
<field name='EndSeqNo' required='Y'/>
</message>
<message msgcat='admin' msgtype='3' name='Reject'>
<field name='RefSeqNum' required='Y'/>
<field name='RefTagID' required='N'/>
<field name='RefMsgType' required='N'/>
<field name='SessionRejectReason' required='N'/>
<field name='Text' required='N'/>
<field name='EncodedTextLen' required='N'/>
<field name='EncodedText' required='N'/>
</message>
<message msgcat='admin' msgtype='4' name='SequenceReset'>
<field name='GapFillFlag' required='N'/>
<field name='NewSeqNo' required='Y'/>
</message>
<message msgcat='admin' msgtype='5' name='Logout'>
<field name='Text' required='N'/>
<field name='EncodedTextLen' required='N'/>
<field name='EncodedText' required='N'/>
</message>
<message msgcat='admin' msgtype='A' name='Logon'>
<field name='EncryptMethod' required='Y'/>
<field name='HeartBtInt' required='Y'/>
<field name='RawDataLength' required='N'/>
<field name='RawData' required='N'/>
<field name='ResetSeqNumFlag' required='N'/>
<field name='NextExpectedMsgSeqNum' required='N'/>
<field name='MaxMessageSize' required='N'/>
<field name='TestMessageIndicator' required='N'/>
<field name='Username' required='N'/>
<field name='Password' required='N'/>
<field name='DefaultApplVerID' required='Y'/>
<component name='MsgTypeGrp' required='N'/>
</message>
</messages>
<components>
<component name='HopGrp'>
<group name='NoHops' required='N'>
<field name='HopCompID' required='N'/>
<field name='HopSendingTime' required='N'/>
<field name='HopRefID' required='N'/>
</group>
</component>
<component name='MsgTypeGrp'>
<group name='NoMsgTypes' required='N'>
<field name='RefMsgType' required='N'/>
<field name='MsgDirection' required='N'/>
<field name='RefApplVerID' required='N'/>
<field name='RefCstmApplVerID' required='N'/>
</group>
</component>
</components>
<fields>
<field name='BeginSeqNo' number='7' type='SEQNUM'/>
<field name='BeginString' number='8' type='STRING'/>
<field name='BodyLength' number='9' type='LENGTH'/>
<field name='CheckSum' number='10' type='STRING'/>
<field name='EndSeqNo' number='16' type='SEQNUM'/>
<field name='MsgSeqNum' number='34' type='SEQNUM'/>
<field number='35' name='MsgType' type='STRING'>
<value enum='0' description='HEARTBEAT'/>
<value enum='1' description='TEST_REQUEST'/>
<value enum='2' description='RESEND_REQUEST'/>
<value enum='3' description='REJECT'/>
<value enum='4' description='SEQUENCE_RESET'/>
<value enum='5' description='LOGOUT'/>
<value enum='6' description='INDICATION_OF_INTEREST'/>
<value enum='7' description='ADVERTISEMENT'/>
<value enum='8' description='EXECUTION_REPORT'/>
<value enum='9' description='ORDER_CANCEL_REJECT'/>
<value enum='A' description='LOGON'/>
<value enum='B' description='NEWS'/>
<value enum='C' description='EMAIL'/>
<value enum='D' description='ORDER_SINGLE'/>
<value enum='E' description='ORDER_LIST'/>
<value enum='F' description='ORDER_CANCEL_REQUEST'/>
<value enum='G' description='ORDER_CANCEL_REPLACE_REQUEST'/>
<value enum='H' description='ORDER_STATUS_REQUEST'/>
<value enum='J' description='ALLOCATION_INSTRUCTION'/>
<value enum='K' description='LIST_CANCEL_REQUEST'/>
<value enum='L' description='LIST_EXECUTE'/>
<value enum='M' description='LIST_STATUS_REQUEST'/>
<value enum='N' description='LIST_STATUS'/>
<value enum='P' description='ALLOCATION_INSTRUCTION_ACK'/>
<value enum='Q' description='DONT_KNOW_TRADE'/>
<value enum='R' description='QUOTE_REQUEST'/>
<value enum='S' description='QUOTE'/>
<value enum='T' description='SETTLEMENT_INSTRUCTIONS'/>
<value enum='V' description='MARKET_DATA_REQUEST'/>
<value enum='W' description='MARKET_DATA_SNAPSHOT_FULL_REFRESH'/>
<value enum='X' description='MARKET_DATA_INCREMENTAL_REFRESH'/>
<value enum='Y' description='MARKET_DATA_REQUEST_REJECT'/>
<value enum='Z' description='QUOTE_CANCEL'/>
<value enum='a' description='QUOTE_STATUS_REQUEST'/>
<value enum='b' description='MASS_QUOTE_ACKNOWLEDGEMENT'/>
<value enum='c' description='SECURITY_DEFINITION_REQUEST'/>
<value enum='d' description='SECURITY_DEFINITION'/>
<value enum='e' description='SECURITY_STATUS_REQUEST'/>
<value enum='f' description='SECURITY_STATUS'/>
<value enum='g' description='TRADING_SESSION_STATUS_REQUEST'/>
<value enum='h' description='TRADING_SESSION_STATUS'/>
<value enum='i' description='MASS_QUOTE'/>
<value enum='j' description='BUSINESS_MESSAGE_REJECT'/>
<value enum='k' description='BID_REQUEST'/>
<value enum='l' description='BID_RESPONSE'/>
<value enum='m' description='LIST_STRIKE_PRICE'/>
<value enum='n' description='XML_MESSAGE'/>
<value enum='o' description='REGISTRATION_INSTRUCTIONS'/>
<value enum='p' description='REGISTRATION_INSTRUCTIONS_RESPONSE'/>
<value enum='q' description='ORDER_MASS_CANCEL_REQUEST'/>
<value enum='r' description='ORDER_MASS_CANCEL_REPORT'/>
<value enum='s' description='NEW_ORDER_CROSS'/>
<value enum='t' description='CROSS_ORDER_CANCEL_REPLACE_REQUEST'/>
<value enum='u' description='CROSS_ORDER_CANCEL_REQUEST'/>
<value enum='v' description='SECURITY_TYPE_REQUEST'/>
<value enum='w' description='SECURITY_TYPES'/>
<value enum='x' description='SECURITY_LIST_REQUEST'/>
<value enum='y' description='SECURITY_LIST'/>
<value enum='z' description='DERIVATIVE_SECURITY_LIST_REQUEST'/>
<value enum='AA' description='DERIVATIVE_SECURITY_LIST'/>
<value enum='AB' description='NEW_ORDER_MULTILEG'/>
<value enum='AC' description='MULTILEG_ORDER_CANCEL_REPLACE'/>
<value enum='AD' description='TRADE_CAPTURE_REPORT_REQUEST'/>
<value enum='AE' description='TRADE_CAPTURE_REPORT'/>
<value enum='AF' description='ORDER_MASS_STATUS_REQUEST'/>
<value enum='AG' description='QUOTE_REQUEST_REJECT'/>
<value enum='AH' description='RFQ_REQUEST'/>
<value enum='AI' description='QUOTE_STATUS_REPORT'/>
<value enum='AJ' description='QUOTE_RESPONSE'/>
<value enum='AK' description='CONFIRMATION'/>
<value enum='AL' description='POSITION_MAINTENANCE_REQUEST'/>
<value enum='AM' description='POSITION_MAINTENANCE_REPORT'/>
<value enum='AN' description='REQUEST_FOR_POSITIONS'/>
<value enum='AO' description='REQUEST_FOR_POSITIONS_ACK'/>
<value enum='AP' description='POSITION_REPORT'/>
<value enum='AQ' description='TRADE_CAPTURE_REPORT_REQUEST_ACK'/>
<value enum='AR' description='TRADE_CAPTURE_REPORT_ACK'/>
<value enum='AS' description='ALLOCATION_REPORT'/>
<value enum='AT' description='ALLOCATION_REPORT_ACK'/>
<value enum='AU' description='CONFIRMATION_ACK'/>
<value enum='AV' description='SETTLEMENT_INSTRUCTION_REQUEST'/>
<value enum='AW' description='ASSIGNMENT_REPORT'/>
<value enum='AX' description='COLLATERAL_REQUEST'/>
<value enum='AY' description='COLLATERAL_ASSIGNMENT'/>
<value enum='AZ' description='COLLATERAL_RESPONSE'/>
<value enum='BA' description='COLLATERAL_REPORT'/>
<value enum='BB' description='COLLATERAL_INQUIRY'/>
<value enum='BC' description='NETWORK_STATUS_REQUEST'/>
<value enum='BD' description='NETWORK_STATUS_RESPONSE'/>
<value enum='BE' description='USER_REQUEST'/>
<value enum='BF' description='USER_RESPONSE'/>
<value enum='BG' description='COLLATERAL_INQUIRY_ACK'/>
<value enum='BH' description='CONFIRMATION_REQUEST'/>
<value enum='BI' description='TRADING_SESSION_LIST_REQUEST'/>
<value enum='BJ' description='TRADING_SESSION_LIST'/>
<value enum='BK' description='SECURITY_LIST_UPDATE_REPORT'/>
<value enum='BL' description='ADJUSTED_POSITION_REPORT'/>
<value enum='BM' description='ALLOCATION_INSTRUCTION_ALERT'/>
<value enum='BN' description='EXECUTION_ACKNOWLEDGEMENT'/>
<value enum='BO' description='CONTRARY_INTENTION_REPORT'/>
<value enum='BP' description='SECURITY_DEFINITION_UPDATE_REPORT'/>
</field>
<field name='NewSeqNo' number='36' type='SEQNUM'/>
<field name='PossDupFlag' number='43' type='BOOLEAN'/>
<field name='RefSeqNum' number='45' type='SEQNUM'/>
<field name='SenderCompID' number='49' type='STRING'/>
<field name='SenderSubID' number='50' type='STRING'/>
<field name='SendingTime' number='52' type='UTCTIMESTAMP'/>
<field name='TargetCompID' number='56' type='STRING'/>
<field name='TargetSubID' number='57' type='STRING'/>
<field name='Text' number='58' type='STRING'/>
<field name='Signature' number='89' type='DATA'/>
<field name='SecureDataLen' number='90' type='LENGTH'/>
<field name='SecureData' number='91' type='DATA'/>
<field name='SignatureLength' number='93' type='LENGTH'/>
<field name='RawDataLength' number='95' type='LENGTH'/>
<field name='RawData' number='96' type='DATA'/>
<field name='PossResend' number='97' type='BOOLEAN'/>
<field name='EncryptMethod' number='98' type='INT'>
<value description='NONE_OTHER' enum='0'/>
<value description='PKCS' enum='1'/>
<value description='DES' enum='2'/>
<value description='PKCS_DES' enum='3'/>
<value description='PGP_DES' enum='4'/>
<value description='PGP_DES_MD5' enum='5'/>
<value description='PEM_DES_MD5' enum='6'/>
</field>
<field name='HeartBtInt' number='108' type='INT'/>
<field name='TestReqID' number='112' type='STRING'/>
<field name='OnBehalfOfCompID' number='115' type='STRING'/>
<field name='OnBehalfOfSubID' number='116' type='STRING'/>
<field name='OrigSendingTime' number='122' type='UTCTIMESTAMP'/>
<field name='GapFillFlag' number='123' type='BOOLEAN'/>
<field name='DeliverToCompID' number='128' type='STRING'/>
<field name='DeliverToSubID' number='129' type='STRING'/>
<field name='ResetSeqNumFlag' number='141' type='BOOLEAN'/>
<field name='SenderLocationID' number='142' type='STRING'/>
<field name='TargetLocationID' number='143' type='STRING'/>
<field name='OnBehalfOfLocationID' number='144' type='STRING'/>
<field name='DeliverToLocationID' number='145' type='STRING'/>
<field name='XmlDataLen' number='212' type='LENGTH'/>
<field name='XmlData' number='213' type='DATA'/>
<field number='347' name='MessageEncoding' type='STRING'>
<value enum='ISO-2022-JP' description='ISO_2022_JP'/>
<value enum='EUC-JP' description='EUC_JP'/>
<value enum='SHIFT_JIS' description='SHIFT_JIS'/>
<value enum='UTF-8' description='UTF_8'/>
</field>
<field name='EncodedTextLen' number='354' type='LENGTH'/>
<field name='EncodedText' number='355' type='DATA'/>
<field name='LastMsgSeqNumProcessed' number='369' type='SEQNUM'/>
<field name='RefTagID' number='371' type='INT'/>
<field name='RefMsgType' number='372' type='STRING'/>
<field name='SessionRejectReason' number='373' type='INT'>
<value description='INVALID_TAG_NUMBER' enum='0'/>
<value description='REQUIRED_TAG_MISSING' enum='1'/>
<value description='SENDINGTIME_ACCURACY_PROBLEM' enum='10'/>
<value description='INVALID_MSGTYPE' enum='11'/>
<value description='XML_VALIDATION_ERROR' enum='12'/>
<value description='TAG_APPEARS_MORE_THAN_ONCE' enum='13'/>
<value description='TAG_SPECIFIED_OUT_OF_REQUIRED_ORDER' enum='14'/>
<value description='REPEATING_GROUP_FIELDS_OUT_OF_ORDER' enum='15'/>
<value description='INCORRECT_NUMINGROUP_COUNT_FOR_REPEATING_GROUP' enum='16'/>
<value description='NON_DATA_VALUE_INCLUDES_FIELD_DELIMITER' enum='17'/>
<value description='TAG_NOT_DEFINED_FOR_THIS_MESSAGE_TYPE' enum='2'/>
<value description='UNDEFINED_TAG' enum='3'/>
<value description='TAG_SPECIFIED_WITHOUT_A_VALUE' enum='4'/>
<value description='VALUE_IS_INCORRECT' enum='5'/>
<value description='INCORRECT_DATA_FORMAT_FOR_VALUE' enum='6'/>
<value description='DECRYPTION_PROBLEM' enum='7'/>
<value description='SIGNATURE_PROBLEM' enum='8'/>
<value description='COMPID_PROBLEM' enum='9'/>
<value description='OTHER' enum='99'/>
</field>
<field name='MaxMessageSize' number='383' type='LENGTH'/>
<field name='NoMsgTypes' number='384' type='NUMINGROUP'/>
<field name='MsgDirection' number='385' type='CHAR'>
<value description='RECEIVE' enum='R'/>
<value description='SEND' enum='S'/>
</field>
<field name='TestMessageIndicator' number='464' type='BOOLEAN'/>
<field name='Username' number='553' type='STRING'/>
<field name='Password' number='554' type='STRING'/>
<field name='NoHops' number='627' type='NUMINGROUP'/>
<field name='HopCompID' number='628' type='STRING'/>
<field name='HopSendingTime' number='629' type='UTCTIMESTAMP'/>
<field name='HopRefID' number='630' type='SEQNUM'/>
<field name='NextExpectedMsgSeqNum' number='789' type='SEQNUM'/>
<field name='ApplVerID' number='1128' type='STRING'>
<value description='FIX27' enum='0'/>
<value description='FIX30' enum='1'/>
<value description='FIX40' enum='2'/>
<value description='FIX41' enum='3'/>
<value description='FIX42' enum='4'/>
<value description='FIX43' enum='5'/>
<value description='FIX44' enum='6'/>
<value description='FIX50' enum='7'/>
<value description='FIX50SP1' enum='8'/>
<value description='FIX50SP2' enum='9'/>
</field>
<field name='CstmApplVerID' number='1129' type='STRING'/>
<field name='RefApplVerID' number='1130' type='STRING'/>
<field name='RefCstmApplVerID' number='1131' type='STRING'/>
<field name='DefaultApplVerID' number='1137' type='STRING'/>
</fields>
</fix>
+1
View File
@@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Platform>x64</Platform>
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
+58
View File
@@ -0,0 +1,58 @@
using System;
using System.Linq;
using CommandLine;
using bts.fix;
namespace bts
{
[Verb("fix", HelpText = "Fix command")]
public class FIXCommandOptions
{
[Option('f', "config", Required = true)]
public string config_file { get; set; }
[Option('i', "initiator", Default = false, Required = false)]
public bool initiator{ get; set; }
[Option('w', "http", Required = false)]
public string http{ get; set; }
[Option('o', "order_session", Default = false, Required = false)]
public bool order_session{ get; set; }
[Option('d', "dropcopy_only", Default = false, Required = false)]
public bool dropcopy_only { get; set; }
}
public class FIXCommand
{
public static int Run(FIXCommandOptions opt)
{
if (opt.order_session)
{
Console.WriteLine("Starting FIX ORDERS Acceptor using " + opt.config_file);
if(!string.IsNullOrEmpty(opt.http))
Console.WriteLine(" Http server " + opt.http);
return FixInit.start_acceptor(opt.config_file, true, (string.IsNullOrEmpty(opt.http) ? null : opt.http));
}
else if (opt.dropcopy_only)
{
Console.WriteLine("Starting FIX DROP Acceptor using " + opt.config_file);
if (!string.IsNullOrEmpty(opt.http))
Console.WriteLine(" Http server " + opt.http);
return FixInit.start_acceptor(opt.config_file, false, (string.IsNullOrEmpty(opt.http) ? null : opt.http));
}
else if (opt.initiator)
{
Console.WriteLine("Initiator not supported yet");
return -1;
}
string[] args = Parser.Default.FormatCommandLine(opt).Split(' ');
var res = Parser.Default.ParseArguments<FIXCommandOptions>(args);
var help = CommandLine.Text.HelpText.AutoBuild(res, h => h, r => r).ToString();
Console.WriteLine(help);
return -1;
}
}
}
@@ -19,8 +19,6 @@ namespace bts {
public bool admin { get; set; }
[Option(nameof(latency))]
public bool latency { get; set; }
[Option("md")]
public bool market_data { get; set; }
}
public class ServiceTest {
@@ -37,24 +35,9 @@ namespace bts {
if (o.latency) {
latency_test();
}
if (o.market_data) {
market_data();
}
return 0;
}
private static void market_data() {
using (var ctx = new ServiceContext()) {
var md = ctx.locate<MarketDataService>();
md.subscribe_securities().Table().Subscribe(update => {
Console.WriteLine($"got {update.state.Count} securities");
});
while(true) {
Thread.Sleep(1000);
}
}
}
static string try_get(string[] args, int index) {
if (args.Length < index) {
return args[index];
+4 -1
View File
@@ -44,7 +44,8 @@ namespace sparkcmd {
SettingsManagerOptions,
TestCommandOptions,
OrderStressOptions,
MBOCommandOptions
MBOCommandOptions,
FIXCommandOptions
>(BTS.remove_config_arg(args))
.MapResult<
ConfigcheckOptions,
@@ -55,6 +56,7 @@ namespace sparkcmd {
TestCommandOptions,
OrderStressOptions,
MBOCommandOptions,
FIXCommandOptions,
int>(
Configcheck.Run,
ScriptClientCommand.Run,
@@ -64,6 +66,7 @@ namespace sparkcmd {
TestCommand.Run,
OrderStress.Run,
MBOCommand.Run,
FIXCommand.Run,
errors => 1);
}
}
+2
View File
@@ -17,7 +17,9 @@
<ProjectReference Include="../spark_api/spark_api.csproj" />
<!--<ProjectReference Include="..\spark\Spark.csproj" />-->
<ProjectReference Include="..\spark_core\spark_core.csproj" />
<ProjectReference Include="..\spark_fix\spark_fix.csproj" />
<ProjectReference Include="..\spark_test\spark_test.csproj" />
<ProjectReference Include="../spark_fix/spark_fix.csproj" />
<!--<Proto3 Include="**/*.proto" />-->
</ItemGroup>
+41
View File
@@ -0,0 +1,41 @@
#http://www.quickfixengine.org/quickfix/doc/html/configuration.html
#https://www.onixs.biz/fix-dictionary.html
[DEFAULT]
ConnectionType=acceptor
SocketAcceptPort=5001
SocketReuseAddress=Y
StartTime=00:00:00
EndTime=00:00:00
UseDataDictionary=Y
ResetOnLogon=Y
ResetOnLogout=Y
ResetOnDisconnect=Y
HeartBtInt=30
LogonTimeout=30
FileLogPath=data_files/fix/log/
FileStorePath=data_files/fix/store/
SSLEnable=N
# SSLEnable=Y
# # It is recommended to install the certificate and refer to it by name instead of using filename + password
# SSLCertificate=QuickFixn-TestServer.pfx
# SSLCertificatePassword=QuickFixn-TestServer
# # For production refer to certificate by name instead: SSLCertificate=CN=QuickFixn-TestServer
# SSLCACertificate=QuickFixn-TestCA.cer
# SSLCheckCertificateRevocation=N
[SESSION]
BeginString=FIX.4.4
SenderCompID=SPARKFIX
TargetCompID=CLIENT1
DataDictionary=data_files/fix/spec/fix/FIX44.xml
[SESSION]
BeginString=FIX.4.4
SenderCompID=SPARKFIX
TargetCompID=CLIENT2
DataDictionary=data_files/fix/spec/fix/FIX44.xml
+828
View File
@@ -0,0 +1,828 @@
<fix major="4" minor="0">
<header>
<field name="BeginString" required="Y"/>
<field name="BodyLength" required="Y"/>
<field name="MsgType" required="Y"/>
<field name="SenderCompID" required="Y"/>
<field name="TargetCompID" required="Y"/>
<field name="OnBehalfOfCompID" required="N"/>
<field name="DeliverToCompID" required="N"/>
<field name="SecureDataLen" required="N"/>
<field name="SecureData" required="N"/>
<field name="MsgSeqNum" required="Y"/>
<field name="SenderSubID" required="N"/>
<field name="TargetSubID" required="N"/>
<field name="OnBehalfOfSubID" required="N"/>
<field name="DeliverToSubID" required="N"/>
<field name="PossDupFlag" required="N"/>
<field name="PossResend" required="N"/>
<field name="SendingTime" required="Y"/>
<field name="OrigSendingTime" required="N"/>
</header>
<trailer>
<field name="SignatureLength" required="N"/>
<field name="Signature" required="N"/>
<field name="CheckSum" required="Y"/>
</trailer>
<messages>
<message name="Heartbeat" msgtype="0" msgcat="admin">
<field name="TestReqID" required="N"/>
</message>
<message name="Logon" msgtype="A" msgcat="admin">
<field name="EncryptMethod" required="Y"/>
<field name="HeartBtInt" required="Y"/>
<field name="RawDataLength" required="N"/>
<field name="RawData" required="N"/>
</message>
<message name="TestRequest" msgtype="1" msgcat="admin">
<field name="TestReqID" required="Y"/>
</message>
<message name="ResendRequest" msgtype="2" msgcat="admin">
<field name="BeginSeqNo" required="Y"/>
<field name="EndSeqNo" required="Y"/>
</message>
<message name="Reject" msgtype="3" msgcat="admin">
<field name="RefSeqNum" required="Y"/>
<field name="Text" required="N"/>
</message>
<message name="SequenceReset" msgtype="4" msgcat="admin">
<field name="GapFillFlag" required="N"/>
<field name="NewSeqNo" required="Y"/>
</message>
<message name="Logout" msgtype="5" msgcat="admin">
<field name="Text" required="N"/>
</message>
<message name="Advertisement" msgtype="7" msgcat="app">
<field name="AdvId" required="Y"/>
<field name="AdvTransType" required="Y"/>
<field name="AdvRefID" required="N"/>
<field name="Symbol" required="Y"/>
<field name="SymbolSfx" required="N"/>
<field name="SecurityID" required="N"/>
<field name="IDSource" required="N"/>
<field name="Issuer" required="N"/>
<field name="SecurityDesc" required="N"/>
<field name="AdvSide" required="Y"/>
<field name="Shares" required="Y"/>
<field name="Price" required="N"/>
<field name="Currency" required="N"/>
<field name="TransactTime" required="N"/>
<field name="Text" required="N"/>
</message>
<message name="IndicationofInterest" msgtype="6" msgcat="app">
<field name="IOIid" required="Y"/>
<field name="IOITransType" required="Y"/>
<field name="IOIRefID" required="N"/>
<field name="Symbol" required="Y"/>
<field name="SymbolSfx" required="N"/>
<field name="SecurityID" required="N"/>
<field name="IDSource" required="N"/>
<field name="Issuer" required="N"/>
<field name="SecurityDesc" required="N"/>
<field name="Side" required="Y"/>
<field name="IOIShares" required="Y"/>
<field name="Price" required="N"/>
<field name="Currency" required="N"/>
<field name="ValidUntilTime" required="N"/>
<field name="IOIQltyInd" required="N"/>
<field name="IOIOthSvc" required="N"/>
<field name="IOINaturalFlag" required="N"/>
<field name="IOIQualifier" required="N"/>
<field name="Text" required="N"/>
</message>
<message name="News" msgtype="B" msgcat="app">
<field name="OrigTime" required="N"/>
<field name="Urgency" required="N"/>
<field name="RelatdSym" required="N" repeating="Y"/>
<group name="LinesOfText" required="Y">
<field name="Text" required="Y"/>
</group>
<field name="RawDataLength" required="N"/>
<field name="RawData" required="N"/>
</message>
<message name="Email" msgtype="C" msgcat="app">
<field name="EmailType" required="Y"/>
<field name="OrigTime" required="N"/>
<field name="RelatdSym" required="N" repeating="Y"/>
<field name="OrderID" required="N"/>
<field name="ClOrdID" required="N"/>
<group name="LinesOfText" required="Y">
<field name="Text" required="Y"/>
</group>
<field name="RawDataLength" required="N"/>
<field name="RawData" required="N"/>
</message>
<message name="QuoteRequest" msgtype="R" msgcat="app">
<field name="QuoteReqID" required="Y"/>
<field name="Symbol" required="Y"/>
<field name="SymbolSfx" required="N"/>
<field name="SecurityID" required="N"/>
<field name="IDSource" required="N"/>
<field name="Issuer" required="N"/>
<field name="SecurityDesc" required="N"/>
<field name="PrevClosePx" required="N"/>
<field name="Side" required="N"/>
<field name="OrderQty" required="N"/>
</message>
<message name="Quote" msgtype="S" msgcat="app">
<field name="QuoteReqID" required="N"/>
<field name="QuoteID" required="Y"/>
<field name="Symbol" required="Y"/>
<field name="SymbolSfx" required="N"/>
<field name="SecurityID" required="N"/>
<field name="IDSource" required="N"/>
<field name="Issuer" required="N"/>
<field name="SecurityDesc" required="N"/>
<field name="BidPx" required="Y"/>
<field name="OfferPx" required="N"/>
<field name="BidSize" required="N"/>
<field name="OfferSize" required="N"/>
<field name="ValidUntilTime" required="N"/>
</message>
<message name="NewOrderSingle" msgtype="D" msgcat="app">
<field name="ClOrdID" required="Y"/>
<field name="ClientID" required="N"/>
<field name="ExecBroker" required="N"/>
<field name="Account" required="N"/>
<field name="SettlmntTyp" required="N"/>
<field name="FutSettDate" required="N"/>
<field name="HandlInst" required="Y"/>
<field name="ExecInst" required="N"/>
<field name="MinQty" required="N"/>
<field name="MaxFloor" required="N"/>
<field name="ExDestination" required="N"/>
<field name="ProcessCode" required="N"/>
<field name="Symbol" required="Y"/>
<field name="SymbolSfx" required="N"/>
<field name="SecurityID" required="N"/>
<field name="IDSource" required="N"/>
<field name="Issuer" required="N"/>
<field name="SecurityDesc" required="N"/>
<field name="PrevClosePx" required="N"/>
<field name="Side" required="Y"/>
<field name="LocateReqd" required="N"/>
<field name="OrderQty" required="Y"/>
<field name="OrdType" required="Y"/>
<field name="Price" required="N"/>
<field name="StopPx" required="N"/>
<field name="Currency" required="N"/>
<field name="IOIid" required="N"/>
<field name="QuoteID" required="N"/>
<field name="TimeInForce" required="N"/>
<field name="ExpireTime" required="N"/>
<field name="Commission" required="N"/>
<field name="CommType" required="N"/>
<field name="Rule80A" required="N"/>
<field name="ForexReq" required="N"/>
<field name="SettlCurrency" required="N"/>
<field name="Text" required="N"/>
</message>
<message name="ExecutionReport" msgtype="8" msgcat="app">
<field name="OrderID" required="Y"/>
<field name="ClOrdID" required="N"/>
<field name="ClientID" required="N"/>
<field name="ExecBroker" required="N"/>
<field name="ListID" required="N"/>
<field name="ExecID" required="Y"/>
<field name="ExecTransType" required="Y"/>
<field name="ExecRefID" required="N"/>
<field name="OrdStatus" required="Y"/>
<field name="OrdRejReason" required="N"/>
<field name="Account" required="N"/>
<field name="SettlmntTyp" required="N"/>
<field name="FutSettDate" required="N"/>
<field name="Symbol" required="Y"/>
<field name="SymbolSfx" required="N"/>
<field name="SecurityID" required="N"/>
<field name="IDSource" required="N"/>
<field name="Issuer" required="N"/>
<field name="SecurityDesc" required="N"/>
<field name="Side" required="Y"/>
<field name="OrderQty" required="Y"/>
<field name="OrdType" required="N"/>
<field name="Price" required="N"/>
<field name="StopPx" required="N"/>
<field name="Currency" required="N"/>
<field name="TimeInForce" required="N"/>
<field name="ExpireTime" required="N"/>
<field name="ExecInst" required="N"/>
<field name="Rule80A" required="N"/>
<field name="LastShares" required="Y"/>
<field name="LastPx" required="Y"/>
<field name="LastMkt" required="N"/>
<field name="LastCapacity" required="N"/>
<field name="CumQty" required="Y"/>
<field name="AvgPx" required="Y"/>
<field name="TradeDate" required="N"/>
<field name="TransactTime" required="N"/>
<field name="ReportToExch" required="N"/>
<field name="Commission" required="N"/>
<field name="CommType" required="N"/>
<group name="NoMiscFees" required="N">
<field name="MiscFeeAmt" required="N"/>
<field name="MiscFeeCurr" required="N"/>
<field name="MiscFeeType" required="N"/>
</group>
<field name="NetMoney" required="N"/>
<field name="SettlCurrAmt" required="N"/>
<field name="SettlCurrency" required="N"/>
<field name="Text" required="N"/>
</message>
<message name="DontKnowTrade" msgtype="Q" msgcat="app">
<field name="OrderID" required="N"/>
<field name="ExecID" required="N"/>
<field name="DKReason" required="Y"/>
<field name="Symbol" required="Y"/>
<field name="Side" required="Y"/>
<field name="OrderQty" required="Y"/>
<field name="LastShares" required="Y"/>
<field name="LastPx" required="Y"/>
<field name="Text" required="N"/>
</message>
<message name="OrderCancelReplaceRequest" msgtype="G" msgcat="app">
<field name="OrderID" required="N"/>
<field name="ClientID" required="N"/>
<field name="ExecBroker" required="N"/>
<field name="OrigClOrdID" required="Y"/>
<field name="ClOrdID" required="Y"/>
<field name="ListID" required="N"/>
<field name="Account" required="N"/>
<field name="SettlmntTyp" required="N"/>
<field name="FutSettDate" required="N"/>
<field name="HandlInst" required="Y"/>
<field name="ExecInst" required="N"/>
<field name="MinQty" required="N"/>
<field name="MaxFloor" required="N"/>
<field name="ExDestination" required="N"/>
<field name="Symbol" required="Y"/>
<field name="SymbolSfx" required="N"/>
<field name="SecurityID" required="N"/>
<field name="IDSource" required="N"/>
<field name="Issuer" required="N"/>
<field name="SecurityDesc" required="N"/>
<field name="Side" required="Y"/>
<field name="OrderQty" required="Y"/>
<field name="OrdType" required="Y"/>
<field name="Price" required="N"/>
<field name="StopPx" required="N"/>
<field name="Currency" required="N"/>
<field name="TimeInForce" required="N"/>
<field name="ExpireTime" required="N"/>
<field name="Commission" required="N"/>
<field name="CommType" required="N"/>
<field name="Rule80A" required="N"/>
<field name="ForexReq" required="N"/>
<field name="SettlCurrency" required="N"/>
<field name="Text" required="N"/>
</message>
<message name="OrderCancelRequest" msgtype="F" msgcat="app">
<field name="OrigClOrdID" required="Y"/>
<field name="OrderID" required="N"/>
<field name="ClOrdID" required="Y"/>
<field name="ListID" required="N"/>
<field name="CxlType" required="Y"/>
<field name="ClientID" required="N"/>
<field name="ExecBroker" required="N"/>
<field name="Symbol" required="Y"/>
<field name="SymbolSfx" required="N"/>
<field name="SecurityID" required="N"/>
<field name="IDSource" required="N"/>
<field name="Issuer" required="N"/>
<field name="SecurityDesc" required="N"/>
<field name="Side" required="Y"/>
<field name="OrderQty" required="Y"/>
<field name="Text" required="N"/>
</message>
<message name="OrderCancelReject" msgtype="9" msgcat="app">
<field name="OrderID" required="Y"/>
<field name="ClOrdID" required="Y"/>
<field name="ClientID" required="N"/>
<field name="ExecBroker" required="N"/>
<field name="ListID" required="N"/>
<field name="CxlRejReason" required="N"/>
<field name="Text" required="N"/>
</message>
<message name="OrderStatusRequest" msgtype="H" msgcat="app">
<field name="OrderID" required="N"/>
<field name="ClOrdID" required="Y"/>
<field name="ClientID" required="N"/>
<field name="ExecBroker" required="N"/>
<field name="Symbol" required="Y"/>
<field name="SymbolSfx" required="N"/>
<field name="Issuer" required="N"/>
<field name="SecurityDesc" required="N"/>
<field name="Side" required="Y"/>
</message>
<message name="Allocation" msgtype="J" msgcat="app">
<field name="AllocID" required="Y"/>
<field name="AllocTransType" required="Y"/>
<field name="RefAllocID" required="N"/>
<group name="NoOrders" required="Y">
<field name="ClOrdID" required="Y"/>
<field name="OrderID" required="N"/>
<field name="ListID" required="N"/>
<field name="WaveNo" required="N"/>
</group>
<group name="NoExecs" required="N">
<field name="ExecID" required="N"/>
<field name="LastShares" required="N"/>
<field name="LastPx" required="N"/>
<field name="LastMkt" required="N"/>
</group>
<field name="Side" required="Y"/>
<field name="Symbol" required="Y"/>
<field name="SymbolSfx" required="N"/>
<field name="SecurityID" required="N"/>
<field name="IDSource" required="N"/>
<field name="Issuer" required="N"/>
<field name="SecurityDesc" required="N"/>
<field name="Shares" required="Y"/>
<field name="AvgPx" required="Y"/>
<field name="Currency" required="N"/>
<field name="AvgPrxPrecision" required="N"/>
<field name="TradeDate" required="Y"/>
<field name="TransactTime" required="N"/>
<field name="SettlmntTyp" required="N"/>
<field name="FutSettDate" required="N"/>
<field name="NetMoney" required="N"/>
<group name="NoMiscFees" required="N">
<field name="MiscFeeAmt" required="N"/>
<field name="MiscFeeCurr" required="N"/>
<field name="MiscFeeType" required="N"/>
</group>
<field name="SettlCurrAmt" required="N"/>
<field name="SettlCurrency" required="N"/>
<field name="OpenClose" required="N"/>
<field name="Text" required="N"/>
<group name="NoAllocs" required="Y">
<field name="AllocAccount" required="Y"/>
<field name="AllocShares" required="Y"/>
<field name="ProcessCode" required="N"/>
<field name="ExecBroker" required="N"/>
<field name="ClientID" required="N"/>
<field name="Commission" required="N"/>
<field name="CommType" required="N"/>
<group name="NoDlvyInst" required="N">
<field name="BrokerOfCredit" required="N"/>
<field name="DlvyInst" required="N"/>
</group>
</group>
</message>
<message name="AllocationACK" msgtype="P" msgcat="app">
<field name="ClientID" required="N"/>
<field name="ExecBroker" required="N"/>
<field name="AllocID" required="Y"/>
<field name="TradeDate" required="Y"/>
<field name="TransactTime" required="N"/>
<field name="AllocStatus" required="Y"/>
<field name="AllocRejCode" required="N"/>
<field name="Text" required="N"/>
</message>
<message name="NewOrderList" msgtype="E" msgcat="app">
<field name="ListID" required="Y"/>
<field name="WaveNo" required="N"/>
<field name="ListSeqNo" required="Y"/>
<field name="ListNoOrds" required="Y"/>
<field name="ListExecInst" required="N"/>
<field name="ClOrdID" required="Y"/>
<field name="ClientID" required="N"/>
<field name="ExecBroker" required="N"/>
<field name="Account" required="N"/>
<field name="SettlmntTyp" required="N"/>
<field name="FutSettDate" required="N"/>
<field name="HandlInst" required="Y"/>
<field name="ExecInst" required="N"/>
<field name="MinQty" required="N"/>
<field name="MaxFloor" required="N"/>
<field name="ExDestination" required="N"/>
<field name="ProcessCode" required="N"/>
<field name="Symbol" required="Y"/>
<field name="SymbolSfx" required="N"/>
<field name="SecurityID" required="N"/>
<field name="IDSource" required="N"/>
<field name="Issuer" required="N"/>
<field name="SecurityDesc" required="N"/>
<field name="PrevClosePx" required="N"/>
<field name="Side" required="Y"/>
<field name="LocateReqd" required="N"/>
<field name="OrderQty" required="Y"/>
<field name="OrdType" required="Y"/>
<field name="Price" required="N"/>
<field name="StopPx" required="N"/>
<field name="Currency" required="N"/>
<field name="TimeInForce" required="N"/>
<field name="ExpireTime" required="N"/>
<field name="Commission" required="N"/>
<field name="CommType" required="N"/>
<field name="Rule80A" required="N"/>
<field name="ForexReq" required="N"/>
<field name="SettlCurrency" required="N"/>
<field name="Text" required="N"/>
</message>
<message name="ListStatus" msgtype="N" msgcat="app">
<field name="ListID" required="Y"/>
<field name="WaveNo" required="N"/>
<field name="NoRpts" required="Y"/>
<field name="RptSeq" required="Y"/>
<group name="NoOrders" required="Y">
<field name="ClOrdID" required="Y"/>
<field name="CumQty" required="Y"/>
<field name="CxlQty" required="Y"/>
<field name="AvgPx" required="Y"/>
</group>
</message>
<message name="ListExecute" msgtype="L" msgcat="app">
<field name="ListID" required="Y"/>
<field name="WaveNo" required="N"/>
<field name="Text" required="N"/>
</message>
<message name="ListCancelRequest" msgtype="K" msgcat="app">
<field name="ListID" required="Y"/>
<field name="WaveNo" required="N"/>
<field name="Text" required="N"/>
</message>
<message name="ListStatusRequest" msgtype="M" msgcat="app">
<field name="ListID" required="Y"/>
<field name="WaveNo" required="N"/>
<field name="Text" required="N"/>
</message>
</messages>
<fields>
<field number="1" name="Account" type="STRING"/>
<field number="2" name="AdvId" type="INT"/>
<field number="3" name="AdvRefID" type="INT"/>
<field number="4" name="AdvSide" type="STRING">
<value enum="B" description="BUY"/>
<value enum="S" description="SELL"/>
<value enum="X" description="CROSS"/>
<value enum="T" description="TRADE"/>
</field>
<field number="5" name="AdvTransType" type="STRING">
<value enum="N" description="NEW"/>
<value enum="C" description="CANCEL"/>
<value enum="R" description="REPLACE"/>
</field>
<field number="6" name="AvgPx" type="FLOAT"/>
<field number="7" name="BeginSeqNo" type="INT"/>
<field number="8" name="BeginString" type="STRING"/>
<field number="9" name="BodyLength" type="INT"/>
<field number="10" name="CheckSum" type="STRING"/>
<field number="11" name="ClOrdID" type="STRING"/>
<field number="12" name="Commission" type="FLOAT"/>
<field number="13" name="CommType" type="STRING">
<value enum="1" description="PER_SHARE"/>
<value enum="2" description="PERCENTAGE"/>
<value enum="3" description="ABSOLUTE"/>
</field>
<field number="14" name="CumQty" type="INT"/>
<field number="15" name="Currency" type="STRING"/>
<field number="16" name="EndSeqNo" type="INT"/>
<field number="17" name="ExecID" type="INT"/>
<field number="18" name="ExecInst" type="MULTIPLEVALUESTRING">
<value enum="1" description="NOT_HELD"/>
<value enum="2" description="WORK"/>
<value enum="3" description="GO_ALONG"/>
<value enum="4" description="OVER_THE_DAY"/>
<value enum="5" description="HELD"/>
<value enum="6" description="PARTICIPATE_DONT_INITIATE"/>
<value enum="7" description="STRICT_SCALE"/>
<value enum="8" description="TRY_TO_SCALE"/>
<value enum="9" description="STAY_ON_BIDSIDE"/>
<value enum="0" description="STAY_ON_OFFERSIDE"/>
<value enum="A" description="NO_CROSS"/>
<value enum="B" description="OK_TO_CROSS"/>
<value enum="C" description="CALL_FIRST"/>
<value enum="D" description="PERCENT_OF_VOLUME"/>
<value enum="E" description="DO_NOT_INCREASE_DNI"/>
<value enum="F" description="DO_NOT_REDUCE_DNR"/>
<value enum="G" description="ALL_OR_NONE_AON"/>
<value enum="I" description="INSTITUTIONS_ONLY"/>
<value enum="L" description="LAST_PEG"/>
<value enum="M" description="MIDPRICE_PEG"/>
<value enum="N" description="NONNEGOTIABLE"/>
<value enum="O" description="OPENING_PEG"/>
<value enum="P" description="MARKET_PEG"/>
<value enum="R" description="PRIMARY_PEG"/>
<value enum="S" description="SUSPEND"/>
</field>
<field number="19" name="ExecRefID" type="INT"/>
<field number="20" name="ExecTransType" type="STRING">
<value enum="0" description="NEW"/>
<value enum="1" description="CANCEL"/>
<value enum="2" description="CORRECT"/>
<value enum="3" description="STATUS"/>
</field>
<field number="21" name="HandlInst" type="STRING">
<value enum="1" description="AUTOMATED_EXECUTION_ORDER_PRIVATE_NO_BROKER_INTERVENTION"/>
<value enum="2" description="AUTOMATED_EXECUTION_ORDER_PUBLIC_BROKER_INTERVENTION_OK"/>
<value enum="3" description="MANUAL_ORDER_BEST_EXECUTION"/>
</field>
<field number="22" name="IDSource" type="STRING">
<value enum="1" description="CUSIP"/>
<value enum="2" description="SEDOL"/>
<value enum="3" description="QUIK"/>
<value enum="4" description="ISIN_NUMBER"/>
<value enum="5" description="RIC_CODE"/>
</field>
<field number="23" name="IOIid" type="INT"/>
<field number="24" name="IOIOthSvc" type="STRING"/>
<field number="25" name="IOIQltyInd" type="STRING">
<value enum="L" description="LOW"/>
<value enum="M" description="MEDIUM"/>
<value enum="H" description="HIGH"/>
</field>
<field number="26" name="IOIRefID" type="INT"/>
<field number="27" name="IOIShares" type="STRING"/>
<field number="28" name="IOITransType" type="STRING">
<value enum="N" description="NEW"/>
<value enum="C" description="CANCEL"/>
<value enum="R" description="REPLACE"/>
</field>
<field number="29" name="LastCapacity" type="STRING">
<value enum="1" description="AGENT"/>
<value enum="2" description="CROSS_AS_AGENT"/>
<value enum="3" description="CROSS_AS_PRINCIPAL"/>
<value enum="4" description="PRINCIPAL"/>
</field>
<field number="30" name="LastMkt" type="STRING"/>
<field number="31" name="LastPx" type="FLOAT"/>
<field number="32" name="LastShares" type="INT"/>
<field number="33" name="LinesOfText" type="INT"/>
<field number="34" name="MsgSeqNum" type="INT"/>
<field number="35" name="MsgType" type="STRING"/>
<field number="36" name="NewSeqNo" type="INT"/>
<field number="37" name="OrderID" type="STRING"/>
<field number="38" name="OrderQty" type="INT"/>
<field number="39" name="OrdStatus" type="STRING">
<value enum="0" description="NEW"/>
<value enum="1" description="PARTIALLY_FILLED"/>
<value enum="2" description="FILLED"/>
<value enum="3" description="DONE_FOR_DAY"/>
<value enum="4" description="CANCELED"/>
<value enum="5" description="REPLACED"/>
<value enum="6" description="PENDING_CANCELREPLACE"/>
<value enum="7" description="STOPPED"/>
<value enum="8" description="REJECTED"/>
<value enum="9" description="SUSPENDED"/>
<value enum="A" description="PENDING_NEW"/>
<value enum="B" description="CALCULATED"/>
<value enum="C" description="EXPIRED"/>
</field>
<field number="40" name="OrdType" type="STRING">
<value enum="1" description="MARKET"/>
<value enum="2" description="LIMIT"/>
<value enum="3" description="STOP"/>
<value enum="4" description="STOP_LIMIT"/>
<value enum="5" description="MARKET_ON_CLOSE"/>
<value enum="6" description="WITH_OR_WITHOUT"/>
<value enum="7" description="LIMIT_OR_BETTER"/>
<value enum="8" description="LIMIT_WITH_OR_WITHOUT"/>
<value enum="9" description="ON_BASIS"/>
<value enum="A" description="ON_CLOSE"/>
<value enum="B" description="LIMIT_ON_CLOSE"/>
<value enum="C" description="FOREX"/>
<value enum="D" description="PREVIOUSLY_QUOTED"/>
<value enum="E" description="PREVIOUSLY_INDICATED"/>
<value enum="P" description="PEGGED"/>
</field>
<field number="41" name="OrigClOrdID" type="STRING"/>
<field number="42" name="OrigTime" type="TIME"/>
<field number="43" name="PossDupFlag" type="STRING">
<value enum="Y" description="POSSIBLE_DUPLICATE"/>
<value enum="N" description="ORIGINAL_TRANSMISSION"/>
</field>
<field number="44" name="Price" type="FLOAT"/>
<field number="45" name="RefSeqNum" type="INT"/>
<field number="46" name="RelatdSym" type="STRING"/>
<field number="47" name="Rule80A" type="STRING">
<value enum="A" description="AGENCY_SINGLE_ORDER"/>
<value enum="D" description="PROGRAM_ORDER_INDEX_ARB_FOR_MEMBER_FIRMORG"/>
<value enum="C" description="PROGRAM_ORDER_NONINDEX_ARB_FOR_MEMBER_FIRMORG"/>
<value enum="J" description="PROGRAM_ORDER_INDEX_ARB_FOR_INDIVIDUAL_CUSTOMER"/>
<value enum="K" description="PROGRAM_ORDER_NONINDEX_ARB_FOR_INDIVIDUAL_CUSTOMER"/>
<value enum="U" description="PROGRAM_ORDER_INDEX_ARB_FOR_OTHER_AGENCY"/>
<value enum="Y" description="PROGRAM_ORDER_NONINDEX_ARB_FOR_OTHER_AGENCY"/>
<value enum="M" description="PROGRAM_ORDER_INDEX_ARB_FOR_OTHER_MEMBER"/>
<value enum="N" description="PROGRAM_ORDER_NONINDEX_ARB_FOR_OTHER_MEMBER"/>
<value enum="W" description="ALL_OTHER_ORDERS_AS_AGENT_FOR_OTHER_MEMBER"/>
</field>
<field number="48" name="SecurityID" type="STRING"/>
<field number="49" name="SenderCompID" type="STRING"/>
<field number="50" name="SenderSubID" type="STRING"/>
<field number="52" name="SendingTime" type="TIME"/>
<field number="53" name="Shares" type="INT"/>
<field number="54" name="Side" type="STRING">
<value enum="1" description="BUY"/>
<value enum="2" description="SELL"/>
<value enum="3" description="BUY_MINUS"/>
<value enum="4" description="SELL_PLUS"/>
<value enum="5" description="SELL_SHORT"/>
<value enum="6" description="SELL_SHORT_EXEMPT"/>
</field>
<field number="55" name="Symbol" type="STRING"/>
<field number="56" name="TargetCompID" type="STRING"/>
<field number="57" name="TargetSubID" type="STRING"/>
<field number="58" name="Text" type="STRING"/>
<field number="59" name="TimeInForce" type="STRING">
<value enum="0" description="DAY"/>
<value enum="1" description="GOOD_TILL_CANCEL"/>
<value enum="2" description="AT_THE_OPENING"/>
<value enum="3" description="IMMEDIATE_OR_CANCEL"/>
<value enum="4" description="FILL_OR_KILL"/>
<value enum="5" description="GOOD_TILL_CROSSING"/>
<value enum="6" description="GOOD_TILL_DATE"/>
</field>
<field number="60" name="TransactTime" type="TIME"/>
<field number="61" name="Urgency" type="STRING">
<value enum="0" description="NORMAL"/>
<value enum="1" description="FLASH"/>
<value enum="2" description="BACKGROUND"/>
</field>
<field number="62" name="ValidUntilTime" type="TIME"/>
<field number="63" name="SettlmntTyp" type="STRING">
<value enum="0" description="REGULAR"/>
<value enum="1" description="CASH"/>
<value enum="2" description="NEXT_DAY"/>
<value enum="3" description="TPLUS2"/>
<value enum="4" description="TPLUS3"/>
<value enum="5" description="TPLUS4"/>
<value enum="6" description="FUTURE"/>
<value enum="7" description="WHEN_ISSUED"/>
<value enum="8" description="SELLERS_OPTION"/>
<value enum="9" description="TPLUS5"/>
</field>
<field number="64" name="FutSettDate" type="DATE"/>
<field number="65" name="SymbolSfx" type="STRING"/>
<field number="66" name="ListID" type="STRING"/>
<field number="67" name="ListSeqNo" type="INT"/>
<field number="68" name="ListNoOrds" type="INT"/>
<field number="69" name="ListExecInst" type="STRING"/>
<field number="70" name="AllocID" type="INT"/>
<field number="71" name="AllocTransType" type="STRING">
<value enum="0" description="NEW"/>
<value enum="1" description="REPLACE"/>
<value enum="2" description="CANCEL"/>
</field>
<field number="72" name="RefAllocID" type="INT"/>
<field number="73" name="NoOrders" type="INT"/>
<field number="74" name="AvgPrxPrecision" type="INT"/>
<field number="75" name="TradeDate" type="DATE"/>
<field number="76" name="ExecBroker" type="STRING"/>
<field number="77" name="OpenClose" type="STRING"/>
<field number="78" name="NoAllocs" type="INT"/>
<field number="79" name="AllocAccount" type="STRING"/>
<field number="80" name="AllocShares" type="INT"/>
<field number="81" name="ProcessCode" type="STRING">
<value enum="0" description="REGULAR"/>
<value enum="1" description="SOFT_DOLLAR"/>
<value enum="2" description="STEPIN"/>
<value enum="3" description="STEPOUT"/>
<value enum="4" description="SOFTDOLLAR_STEPIN"/>
<value enum="5" description="SOFTDOLLAR_STEPOUT"/>
<value enum="6" description="PLAN_SPONSOR"/>
</field>
<field number="82" name="NoRpts" type="INT"/>
<field number="83" name="RptSeq" type="INT"/>
<field number="84" name="CxlQty" type="INT"/>
<field number="85" name="NoDlvyInst" type="INT"/>
<field number="86" name="DlvyInst" type="STRING"/>
<field number="87" name="AllocStatus" type="INT">
<value enum="0" description="ACCEPTED"/>
<value enum="1" description="REJECTED"/>
<value enum="2" description="PARTIAL_ACCEPT"/>
<value enum="3" description="RECEIVED"/>
</field>
<field number="88" name="AllocRejCode" type="INT">
<value enum="0" description="UNKNOWN_ACCOUNT"/>
<value enum="1" description="INCORRECT_QUANTITY"/>
<value enum="2" description="INCORRECT_AVERAGE_PRICE"/>
<value enum="3" description="UNKNOWN_EXECUTING_BROKER_MNEMONIC"/>
<value enum="4" description="COMMISSION_DIFFERENCE"/>
<value enum="5" description="UNKNOWN_ORDERID"/>
<value enum="6" description="UNKNOWN_LISTID"/>
<value enum="7" description="OTHER"/>
</field>
<field number="89" name="Signature" type="DATA"/>
<field number="90" name="SecureDataLen" type="INT"/>
<field number="91" name="SecureData" type="DATA"/>
<field number="92" name="BrokerOfCredit" type="STRING"/>
<field number="93" name="SignatureLength" type="INT"/>
<field number="94" name="EmailType" type="STRING">
<value enum="0" description="NEW"/>
<value enum="1" description="REPLY"/>
<value enum="2" description="ADMIN_REPLY"/>
</field>
<field number="95" name="RawDataLength" type="INT"/>
<field number="96" name="RawData" type="DATA"/>
<field number="97" name="PossResend" type="STRING"/>
<field number="98" name="EncryptMethod" type="INT">
<value enum="0" description="NONE_OTHER"/>
<value enum="1" description="PKCS"/>
<value enum="2" description="DES"/>
<value enum="3" description="PKCSDES"/>
<value enum="4" description="PGPDES"/>
<value enum="5" description="PGPDESMD5"/>
<value enum="6" description="PEMDESMD5"/>
</field>
<field number="99" name="StopPx" type="FLOAT"/>
<field number="100" name="ExDestination" type="STRING">
<value enum="0" description="NONE"/>
<value enum="4" description="POSIT"/>
</field>
<field number="102" name="CxlRejReason" type="INT">
<value enum="0" description="TOO_LATE_TO_CANCEL"/>
<value enum="1" description="UNKNOWN_ORDER"/>
</field>
<field number="103" name="OrdRejReason" type="INT">
<value enum="0" description="BROKER_OPTION"/>
<value enum="1" description="UNKNOWN_SYMBOL"/>
<value enum="2" description="EXCHANGE_CLOSED"/>
<value enum="3" description="ORDER_EXCEEDS_LIMIT"/>
<value enum="4" description="TOO_LATE_TO_ENTER"/>
</field>
<field number="104" name="IOIQualifier" type="STRING">
<value enum="X" description="CROSSING_OPPORTUNITY"/>
<value enum="O" description="AT_THE_OPEN"/>
<value enum="M" description="MORE_BEHIND"/>
<value enum="P" description="TAKING_A_POSITION"/>
<value enum="V" description="VERSUS"/>
<value enum="Q" description="CURRENT_QUOTE"/>
<value enum="C" description="AT_THE_CLOSE"/>
<value enum="S" description="PORTFOLIO_SHOWN"/>
<value enum="I" description="IN_TOUCH_WITH"/>
<value enum="W" description="INDICATION_WORKING_AWAY"/>
<value enum="A" description="ALL_OR_NONE"/>
<value enum="L" description="LIMIT"/>
<value enum="T" description="THROUGH_THE_DAY"/>
</field>
<field number="105" name="WaveNo" type="STRING"/>
<field number="106" name="Issuer" type="STRING"/>
<field number="107" name="SecurityDesc" type="STRING"/>
<field number="108" name="HeartBtInt" type="INT"/>
<field number="109" name="ClientID" type="STRING"/>
<field number="110" name="MinQty" type="INT"/>
<field number="111" name="MaxFloor" type="INT"/>
<field number="112" name="TestReqID" type="STRING"/>
<field number="113" name="ReportToExch" type="STRING">
<value enum="Y" description="YES"/>
<value enum="N" description="NO"/>
</field>
<field number="114" name="LocateReqd" type="STRING">
<value enum="Y" description="YES"/>
<value enum="N" description="NO"/>
</field>
<field number="115" name="OnBehalfOfCompID" type="STRING"/>
<field number="116" name="OnBehalfOfSubID" type="STRING"/>
<field number="117" name="QuoteID" type="STRING"/>
<field number="118" name="NetMoney" type="FLOAT"/>
<field number="119" name="SettlCurrAmt" type="FLOAT"/>
<field number="120" name="SettlCurrency" type="STRING"/>
<field number="121" name="ForexReq" type="STRING">
<value enum="Y" description="YES"/>
<value enum="N" description="NO"/>
</field>
<field number="122" name="OrigSendingTime" type="TIME"/>
<field number="123" name="GapFillFlag" type="STRING">
<value enum="Y" description="GAP_FILL_MESSAGE_MSGSEQNUM_FIELD_VALID"/>
<value enum="N" description="SEQUENCE_RESET_IGNORE_MSGSEQNUM"/>
</field>
<field number="124" name="NoExecs" type="INT"/>
<field number="125" name="CxlType" type="STRING">
<value enum="P" description="PARTIAL_CANCEL"/>
<value enum="F" description="FULL_REMAINING_QUANTITY"/>
</field>
<field number="126" name="ExpireTime" type="TIME"/>
<field number="127" name="DKReason" type="STRING">
<value enum="A" description="UNKNOWN_SYMBOL"/>
<value enum="B" description="WRONG_SIDE"/>
<value enum="C" description="QUANTITY_EXCEEDS_ORDER"/>
<value enum="D" description="NO_MATCHING_ORDER"/>
<value enum="E" description="PRICE_EXCEEDS_LIMIT"/>
<value enum="Z" description="OTHER" />
</field>
<field number="128" name="DeliverToCompID" type="STRING"/>
<field number="129" name="DeliverToSubID" type="STRING"/>
<field number="130" name="IOINaturalFlag" type="STRING">
<value enum="Y" description="NATURAL"/>
<value enum="N" description="NOT_NATURAL"/>
</field>
<field number="131" name="QuoteReqID" type="STRING"/>
<field number="132" name="BidPx" type="FLOAT"/>
<field number="133" name="OfferPx" type="FLOAT"/>
<field number="134" name="BidSize" type="INT"/>
<field number="135" name="OfferSize" type="INT"/>
<field number="136" name="NoMiscFees" type="INT"/>
<field number="137" name="MiscFeeAmt" type="FLOAT"/>
<field number="138" name="MiscFeeCurr" type="STRING"/>
<field number="139" name="MiscFeeType" type="STRING">
<value enum="1" description="REGULATORY"/>
<value enum="2" description="TAX"/>
<value enum="3" description="LOCAL_COMMISSION"/>
<value enum="4" description="EXCHANGE_FEES"/>
<value enum="5" description="STAMP"/>
<value enum="6" description="LEVY"/>
<value enum="7" description="OTHER"/>
</field>
<field number="140" name="PrevClosePx" type="FLOAT"/>
</fields>
</fix>
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,313 @@
<?xml version='1.0' encoding='UTF-8'?>
<fix type='FIXT' major='1' minor='1' servicepack='0'>
<header>
<field name='BeginString' required='Y'/>
<field name='BodyLength' required='Y'/>
<field name='MsgType' required='Y'/>
<field name='SenderCompID' required='Y'/>
<field name='TargetCompID' required='Y'/>
<field name='OnBehalfOfCompID' required='N'/>
<field name='DeliverToCompID' required='N'/>
<field name='SecureDataLen' required='N'/>
<field name='SecureData' required='N'/>
<field name='MsgSeqNum' required='Y'/>
<field name='SenderSubID' required='N'/>
<field name='SenderLocationID' required='N'/>
<field name='TargetSubID' required='N'/>
<field name='TargetLocationID' required='N'/>
<field name='OnBehalfOfSubID' required='N'/>
<field name='OnBehalfOfLocationID' required='N'/>
<field name='DeliverToSubID' required='N'/>
<field name='DeliverToLocationID' required='N'/>
<field name='PossDupFlag' required='N'/>
<field name='PossResend' required='N'/>
<field name='SendingTime' required='Y'/>
<field name='OrigSendingTime' required='N'/>
<field name='XmlDataLen' required='N'/>
<field name='XmlData' required='N'/>
<field name='MessageEncoding' required='N'/>
<field name='LastMsgSeqNumProcessed' required='N'/>
<component name='HopGrp' required='N'/>
<field name='ApplVerID' required='N'/>
<field name='CstmApplVerID' required='N'/>
</header>
<trailer>
<field name='SignatureLength' required='N'/>
<field name='Signature' required='N'/>
<field name='CheckSum' required='Y'/>
</trailer>
<messages>
<message msgcat='admin' msgtype='0' name='Heartbeat'>
<field name='TestReqID' required='N'/>
</message>
<message msgcat='admin' msgtype='1' name='TestRequest'>
<field name='TestReqID' required='Y'/>
</message>
<message msgcat='admin' msgtype='2' name='ResendRequest'>
<field name='BeginSeqNo' required='Y'/>
<field name='EndSeqNo' required='Y'/>
</message>
<message msgcat='admin' msgtype='3' name='Reject'>
<field name='RefSeqNum' required='Y'/>
<field name='RefTagID' required='N'/>
<field name='RefMsgType' required='N'/>
<field name='SessionRejectReason' required='N'/>
<field name='Text' required='N'/>
<field name='EncodedTextLen' required='N'/>
<field name='EncodedText' required='N'/>
</message>
<message msgcat='admin' msgtype='4' name='SequenceReset'>
<field name='GapFillFlag' required='N'/>
<field name='NewSeqNo' required='Y'/>
</message>
<message msgcat='admin' msgtype='5' name='Logout'>
<field name='Text' required='N'/>
<field name='EncodedTextLen' required='N'/>
<field name='EncodedText' required='N'/>
</message>
<message msgcat='admin' msgtype='A' name='Logon'>
<field name='EncryptMethod' required='Y'/>
<field name='HeartBtInt' required='Y'/>
<field name='RawDataLength' required='N'/>
<field name='RawData' required='N'/>
<field name='ResetSeqNumFlag' required='N'/>
<field name='NextExpectedMsgSeqNum' required='N'/>
<field name='MaxMessageSize' required='N'/>
<field name='TestMessageIndicator' required='N'/>
<field name='Username' required='N'/>
<field name='Password' required='N'/>
<field name='DefaultApplVerID' required='Y'/>
<component name='MsgTypeGrp' required='N'/>
</message>
</messages>
<components>
<component name='HopGrp'>
<group name='NoHops' required='N'>
<field name='HopCompID' required='N'/>
<field name='HopSendingTime' required='N'/>
<field name='HopRefID' required='N'/>
</group>
</component>
<component name='MsgTypeGrp'>
<group name='NoMsgTypes' required='N'>
<field name='RefMsgType' required='N'/>
<field name='MsgDirection' required='N'/>
<field name='RefApplVerID' required='N'/>
<field name='RefCstmApplVerID' required='N'/>
</group>
</component>
</components>
<fields>
<field name='BeginSeqNo' number='7' type='SEQNUM'/>
<field name='BeginString' number='8' type='STRING'/>
<field name='BodyLength' number='9' type='LENGTH'/>
<field name='CheckSum' number='10' type='STRING'/>
<field name='EndSeqNo' number='16' type='SEQNUM'/>
<field name='MsgSeqNum' number='34' type='SEQNUM'/>
<field number='35' name='MsgType' type='STRING'>
<value enum='0' description='HEARTBEAT'/>
<value enum='1' description='TEST_REQUEST'/>
<value enum='2' description='RESEND_REQUEST'/>
<value enum='3' description='REJECT'/>
<value enum='4' description='SEQUENCE_RESET'/>
<value enum='5' description='LOGOUT'/>
<value enum='6' description='INDICATION_OF_INTEREST'/>
<value enum='7' description='ADVERTISEMENT'/>
<value enum='8' description='EXECUTION_REPORT'/>
<value enum='9' description='ORDER_CANCEL_REJECT'/>
<value enum='A' description='LOGON'/>
<value enum='B' description='NEWS'/>
<value enum='C' description='EMAIL'/>
<value enum='D' description='ORDER_SINGLE'/>
<value enum='E' description='ORDER_LIST'/>
<value enum='F' description='ORDER_CANCEL_REQUEST'/>
<value enum='G' description='ORDER_CANCEL_REPLACE_REQUEST'/>
<value enum='H' description='ORDER_STATUS_REQUEST'/>
<value enum='J' description='ALLOCATION_INSTRUCTION'/>
<value enum='K' description='LIST_CANCEL_REQUEST'/>
<value enum='L' description='LIST_EXECUTE'/>
<value enum='M' description='LIST_STATUS_REQUEST'/>
<value enum='N' description='LIST_STATUS'/>
<value enum='P' description='ALLOCATION_INSTRUCTION_ACK'/>
<value enum='Q' description='DONT_KNOW_TRADE'/>
<value enum='R' description='QUOTE_REQUEST'/>
<value enum='S' description='QUOTE'/>
<value enum='T' description='SETTLEMENT_INSTRUCTIONS'/>
<value enum='V' description='MARKET_DATA_REQUEST'/>
<value enum='W' description='MARKET_DATA_SNAPSHOT_FULL_REFRESH'/>
<value enum='X' description='MARKET_DATA_INCREMENTAL_REFRESH'/>
<value enum='Y' description='MARKET_DATA_REQUEST_REJECT'/>
<value enum='Z' description='QUOTE_CANCEL'/>
<value enum='a' description='QUOTE_STATUS_REQUEST'/>
<value enum='b' description='MASS_QUOTE_ACKNOWLEDGEMENT'/>
<value enum='c' description='SECURITY_DEFINITION_REQUEST'/>
<value enum='d' description='SECURITY_DEFINITION'/>
<value enum='e' description='SECURITY_STATUS_REQUEST'/>
<value enum='f' description='SECURITY_STATUS'/>
<value enum='g' description='TRADING_SESSION_STATUS_REQUEST'/>
<value enum='h' description='TRADING_SESSION_STATUS'/>
<value enum='i' description='MASS_QUOTE'/>
<value enum='j' description='BUSINESS_MESSAGE_REJECT'/>
<value enum='k' description='BID_REQUEST'/>
<value enum='l' description='BID_RESPONSE'/>
<value enum='m' description='LIST_STRIKE_PRICE'/>
<value enum='n' description='XML_MESSAGE'/>
<value enum='o' description='REGISTRATION_INSTRUCTIONS'/>
<value enum='p' description='REGISTRATION_INSTRUCTIONS_RESPONSE'/>
<value enum='q' description='ORDER_MASS_CANCEL_REQUEST'/>
<value enum='r' description='ORDER_MASS_CANCEL_REPORT'/>
<value enum='s' description='NEW_ORDER_CROSS'/>
<value enum='t' description='CROSS_ORDER_CANCEL_REPLACE_REQUEST'/>
<value enum='u' description='CROSS_ORDER_CANCEL_REQUEST'/>
<value enum='v' description='SECURITY_TYPE_REQUEST'/>
<value enum='w' description='SECURITY_TYPES'/>
<value enum='x' description='SECURITY_LIST_REQUEST'/>
<value enum='y' description='SECURITY_LIST'/>
<value enum='z' description='DERIVATIVE_SECURITY_LIST_REQUEST'/>
<value enum='AA' description='DERIVATIVE_SECURITY_LIST'/>
<value enum='AB' description='NEW_ORDER_MULTILEG'/>
<value enum='AC' description='MULTILEG_ORDER_CANCEL_REPLACE'/>
<value enum='AD' description='TRADE_CAPTURE_REPORT_REQUEST'/>
<value enum='AE' description='TRADE_CAPTURE_REPORT'/>
<value enum='AF' description='ORDER_MASS_STATUS_REQUEST'/>
<value enum='AG' description='QUOTE_REQUEST_REJECT'/>
<value enum='AH' description='RFQ_REQUEST'/>
<value enum='AI' description='QUOTE_STATUS_REPORT'/>
<value enum='AJ' description='QUOTE_RESPONSE'/>
<value enum='AK' description='CONFIRMATION'/>
<value enum='AL' description='POSITION_MAINTENANCE_REQUEST'/>
<value enum='AM' description='POSITION_MAINTENANCE_REPORT'/>
<value enum='AN' description='REQUEST_FOR_POSITIONS'/>
<value enum='AO' description='REQUEST_FOR_POSITIONS_ACK'/>
<value enum='AP' description='POSITION_REPORT'/>
<value enum='AQ' description='TRADE_CAPTURE_REPORT_REQUEST_ACK'/>
<value enum='AR' description='TRADE_CAPTURE_REPORT_ACK'/>
<value enum='AS' description='ALLOCATION_REPORT'/>
<value enum='AT' description='ALLOCATION_REPORT_ACK'/>
<value enum='AU' description='CONFIRMATION_ACK'/>
<value enum='AV' description='SETTLEMENT_INSTRUCTION_REQUEST'/>
<value enum='AW' description='ASSIGNMENT_REPORT'/>
<value enum='AX' description='COLLATERAL_REQUEST'/>
<value enum='AY' description='COLLATERAL_ASSIGNMENT'/>
<value enum='AZ' description='COLLATERAL_RESPONSE'/>
<value enum='BA' description='COLLATERAL_REPORT'/>
<value enum='BB' description='COLLATERAL_INQUIRY'/>
<value enum='BC' description='NETWORK_STATUS_REQUEST'/>
<value enum='BD' description='NETWORK_STATUS_RESPONSE'/>
<value enum='BE' description='USER_REQUEST'/>
<value enum='BF' description='USER_RESPONSE'/>
<value enum='BG' description='COLLATERAL_INQUIRY_ACK'/>
<value enum='BH' description='CONFIRMATION_REQUEST'/>
<value enum='BI' description='TRADING_SESSION_LIST_REQUEST'/>
<value enum='BJ' description='TRADING_SESSION_LIST'/>
<value enum='BK' description='SECURITY_LIST_UPDATE_REPORT'/>
<value enum='BL' description='ADJUSTED_POSITION_REPORT'/>
<value enum='BM' description='ALLOCATION_INSTRUCTION_ALERT'/>
<value enum='BN' description='EXECUTION_ACKNOWLEDGEMENT'/>
<value enum='BO' description='CONTRARY_INTENTION_REPORT'/>
<value enum='BP' description='SECURITY_DEFINITION_UPDATE_REPORT'/>
</field>
<field name='NewSeqNo' number='36' type='SEQNUM'/>
<field name='PossDupFlag' number='43' type='BOOLEAN'/>
<field name='RefSeqNum' number='45' type='SEQNUM'/>
<field name='SenderCompID' number='49' type='STRING'/>
<field name='SenderSubID' number='50' type='STRING'/>
<field name='SendingTime' number='52' type='UTCTIMESTAMP'/>
<field name='TargetCompID' number='56' type='STRING'/>
<field name='TargetSubID' number='57' type='STRING'/>
<field name='Text' number='58' type='STRING'/>
<field name='Signature' number='89' type='DATA'/>
<field name='SecureDataLen' number='90' type='LENGTH'/>
<field name='SecureData' number='91' type='DATA'/>
<field name='SignatureLength' number='93' type='LENGTH'/>
<field name='RawDataLength' number='95' type='LENGTH'/>
<field name='RawData' number='96' type='DATA'/>
<field name='PossResend' number='97' type='BOOLEAN'/>
<field name='EncryptMethod' number='98' type='INT'>
<value description='NONE_OTHER' enum='0'/>
<value description='PKCS' enum='1'/>
<value description='DES' enum='2'/>
<value description='PKCS_DES' enum='3'/>
<value description='PGP_DES' enum='4'/>
<value description='PGP_DES_MD5' enum='5'/>
<value description='PEM_DES_MD5' enum='6'/>
</field>
<field name='HeartBtInt' number='108' type='INT'/>
<field name='TestReqID' number='112' type='STRING'/>
<field name='OnBehalfOfCompID' number='115' type='STRING'/>
<field name='OnBehalfOfSubID' number='116' type='STRING'/>
<field name='OrigSendingTime' number='122' type='UTCTIMESTAMP'/>
<field name='GapFillFlag' number='123' type='BOOLEAN'/>
<field name='DeliverToCompID' number='128' type='STRING'/>
<field name='DeliverToSubID' number='129' type='STRING'/>
<field name='ResetSeqNumFlag' number='141' type='BOOLEAN'/>
<field name='SenderLocationID' number='142' type='STRING'/>
<field name='TargetLocationID' number='143' type='STRING'/>
<field name='OnBehalfOfLocationID' number='144' type='STRING'/>
<field name='DeliverToLocationID' number='145' type='STRING'/>
<field name='XmlDataLen' number='212' type='LENGTH'/>
<field name='XmlData' number='213' type='DATA'/>
<field number='347' name='MessageEncoding' type='STRING'>
<value enum='ISO-2022-JP' description='ISO_2022_JP'/>
<value enum='EUC-JP' description='EUC_JP'/>
<value enum='SHIFT_JIS' description='SHIFT_JIS'/>
<value enum='UTF-8' description='UTF_8'/>
</field>
<field name='EncodedTextLen' number='354' type='LENGTH'/>
<field name='EncodedText' number='355' type='DATA'/>
<field name='LastMsgSeqNumProcessed' number='369' type='SEQNUM'/>
<field name='RefTagID' number='371' type='INT'/>
<field name='RefMsgType' number='372' type='STRING'/>
<field name='SessionRejectReason' number='373' type='INT'>
<value description='INVALID_TAG_NUMBER' enum='0'/>
<value description='REQUIRED_TAG_MISSING' enum='1'/>
<value description='SENDINGTIME_ACCURACY_PROBLEM' enum='10'/>
<value description='INVALID_MSGTYPE' enum='11'/>
<value description='XML_VALIDATION_ERROR' enum='12'/>
<value description='TAG_APPEARS_MORE_THAN_ONCE' enum='13'/>
<value description='TAG_SPECIFIED_OUT_OF_REQUIRED_ORDER' enum='14'/>
<value description='REPEATING_GROUP_FIELDS_OUT_OF_ORDER' enum='15'/>
<value description='INCORRECT_NUMINGROUP_COUNT_FOR_REPEATING_GROUP' enum='16'/>
<value description='NON_DATA_VALUE_INCLUDES_FIELD_DELIMITER' enum='17'/>
<value description='TAG_NOT_DEFINED_FOR_THIS_MESSAGE_TYPE' enum='2'/>
<value description='UNDEFINED_TAG' enum='3'/>
<value description='TAG_SPECIFIED_WITHOUT_A_VALUE' enum='4'/>
<value description='VALUE_IS_INCORRECT' enum='5'/>
<value description='INCORRECT_DATA_FORMAT_FOR_VALUE' enum='6'/>
<value description='DECRYPTION_PROBLEM' enum='7'/>
<value description='SIGNATURE_PROBLEM' enum='8'/>
<value description='COMPID_PROBLEM' enum='9'/>
<value description='OTHER' enum='99'/>
</field>
<field name='MaxMessageSize' number='383' type='LENGTH'/>
<field name='NoMsgTypes' number='384' type='NUMINGROUP'/>
<field name='MsgDirection' number='385' type='CHAR'>
<value description='RECEIVE' enum='R'/>
<value description='SEND' enum='S'/>
</field>
<field name='TestMessageIndicator' number='464' type='BOOLEAN'/>
<field name='Username' number='553' type='STRING'/>
<field name='Password' number='554' type='STRING'/>
<field name='NoHops' number='627' type='NUMINGROUP'/>
<field name='HopCompID' number='628' type='STRING'/>
<field name='HopSendingTime' number='629' type='UTCTIMESTAMP'/>
<field name='HopRefID' number='630' type='SEQNUM'/>
<field name='NextExpectedMsgSeqNum' number='789' type='SEQNUM'/>
<field name='ApplVerID' number='1128' type='STRING'>
<value description='FIX27' enum='0'/>
<value description='FIX30' enum='1'/>
<value description='FIX40' enum='2'/>
<value description='FIX41' enum='3'/>
<value description='FIX42' enum='4'/>
<value description='FIX43' enum='5'/>
<value description='FIX44' enum='6'/>
<value description='FIX50' enum='7'/>
<value description='FIX50SP1' enum='8'/>
<value description='FIX50SP2' enum='9'/>
</field>
<field name='CstmApplVerID' number='1129' type='STRING'/>
<field name='RefApplVerID' number='1130' type='STRING'/>
<field name='RefCstmApplVerID' number='1131' type='STRING'/>
<field name='DefaultApplVerID' number='1137' type='STRING'/>
</fields>
</fix>
+1 -1
View File
@@ -1 +1 @@
set(sources api/apicore.proto;api/apigateway.proto;api/apioptions.proto;api/core/ApiClientInterop.cpp;api/core/ApiServerInterop.cpp;api/public/ApiServer.cpp;api/public/ClientChannel.cpp;api/public/QuickbusClientChannel.cpp;api/public/ServerChannel.cpp;api/public/ServiceContext.cpp;api/service_helpers/AdminServiceUtils.cpp;api/service_helpers/AlgoServiceUtils.cpp;api/service_helpers/PositionUtilities.cpp;api/services/AdminService.proto;api/services/AlgoDefinitionService.proto;api/services/AlgoService.proto;api/services/ApiUnitTestService.proto;api/services/AuthService.proto;api/services/BasePositionService.proto;api/services/ErrorReportService.proto;api/services/HelloService.proto;api/services/MBOService.proto;api/services/MarginService.proto;api/services/MarketDataAuxiliaryService.proto;api/services/MarketDataRelay.proto;api/services/MarketDataService.proto;api/services/MoneyFileService.proto;api/services/OrderService.proto;api/services/OutOfProcessURLListener.proto;api/services/PersistenceService.proto;api/services/PositionService.proto;api/services/ShellDiagnosticService.proto;api/services/ShellLatencyService.proto;api/services/SyntheticSecurityService.proto;api/test/ApiTests.cpp;api/test/HelloServiceServer.cpp;config/ConfigCheck.cpp;config/ConfigDownloader.cpp;config/ConfigErrorCollector.cpp;config/ConfigLog.cpp;config/ConfigPropertyEvaluator.cpp;config/ConfigValueQueue.cpp;config/ConfigurationException.cpp;config/ConfigurationState.cpp;config/PreprocessInputStream.cpp;config/config.cpp;config/defaults/MarketData.conf;config/defaults/Ports.conf;config/defaults/Symbols.conf;config/defaults/cme_reference_data.conf;config/defaults/edge.conf;config/defaults/jetfix.conf;config/defaults/keycode.conf;config/defaults/logging.conf;config/defaults/orderman_cfg.conf;config/defaults/orders_fills_cleanup.conf;config/defaults/position_cfg.conf;config/defaults/span.conf;config/defaults/spreader.conf;config/defaults/testkeys.conf;config/defaults/threads.conf;config/defaults/toggles.conf;config/extensions/extensions.proto;config/invalid/invalid.proto;config/protos/ExchangeSimCfg.proto;config/protos/MarketData.proto;config/protos/Ports.proto;config/protos/Symbols.proto;config/protos/UI.proto;config/protos/cme_reference_data.proto;config/protos/jetfix.proto;config/protos/keycode.proto;config/protos/logging.proto;config/protos/mercury_cfg.proto;config/protos/orderman_cfg.proto;config/protos/orders_fills_cleanup.proto;config/protos/perflog_cfg.proto;config/protos/position_cfg.proto;config/protos/quickbus_cfg.proto;config/protos/span.proto;config/protos/spreader.proto;config/protos/subprocess.proto;config/protos/system.proto;config/protos/testkeys.proto;config/protos/threads.proto;config/protos/toggles.proto;config/tests/HTTPServer.cpp;config/tests/config_ref_tests.cpp;config/tests/config_tests.cpp;config/text_format/text_format.cpp;domain_model/Security.cpp;domain_model/Security.proto;domain_model/SecurityTests.cpp;domain_model/sod.cpp;domain_model/tests/domain_tests.cpp;expression/BooleanGrammar.cpp;expression/ExpressionEvaluator.cpp;expression/ParserExceptions.cpp;expression/Value.cpp;expression/tests/expression_parser_tests.cpp;jetfix/codec/FIXArray.cpp;jetfix/common/OutFIX.cpp;jetfix/connection/AsyncReader.cpp;jetfix/connection/IConnection.cpp;jetfix/connection/SocketConnection.cpp;jetfix/gateway/CoreGateway.cpp;jetfix/gateway/JetFIXGateway.cpp;jetfix/gateway/Session.cpp;jetfix/store/FIXFileStore.cpp;jetfix/store/session_name.cpp;jetfix/tests/async_reader_tests.cpp;jetfix/tests/decoding_tests.cpp;jetfix/tests/fix_encoding_stream_tests.cpp;jetfix/tests/fix_fragment_tests.cpp;jetfix/tests/jetfix_performance_tests.cpp;jetfix/tests/sample_fix.cpp;jetfix/tests/store_tests.cpp;logging/LoggerHub.cpp;logging/Sink.cpp;logging/logging.cpp;logging/tests/logging_tests.cpp;md/Diag/MDPeriodicDumper.cpp;md/Diag/ShmDumper.cpp;md/MBOProcessor.cpp;md/MBOServiceServer.cpp;md/MDClient.cpp;md/MDConsumer.cpp;md/MDConsumerHandle.cpp;md/MDConsumerInterop.cpp;md/MDProducer.cpp;md/MDProducerHandle.cpp;md/MemorySegmentUtils.cpp;md/PlatformLoader.cpp;md/PriceSize.cpp;md/Product.cpp;md/SecurityCache.cpp;md/SecurityDB.cpp;md/SecurityIDRecorder.cpp;md/SecurityMapper.cpp;md/SecurityOracle.cpp;md/SettlementRecorder.cpp;md/Shm/FixedSecurity.cpp;md/SyntheticSecurityService.cpp;md/cme/MDP3Utils.cpp;md/common.cpp;md/ice/ICEUtils.cpp;md/protos/co2.proto;md/relay/QueryServer.cpp;md/relay/RelayClient.cpp;md/relay/RelayRecorder.cpp;md/service/MarketDataServiceServer.cpp;md/test/Co2ManagedTestHelper.cpp;md/test/Co2TestInstrument.cpp;md/test/mbo_tests.cpp;md/test/md2_tests.cpp;md/test/md_test_utils.cpp;md/test/synthetic_book_merge_tests.cpp;md/vendor/OnixsUtils.cpp;mercury/actors/IPollableActor.cpp;mercury/broker/Broker.cpp;mercury/broker/BrokerProxy.cpp;mercury/broker/ILocalBroker.cpp;mercury/broker/IRemoteBroker.cpp;mercury/common/mercury_common.cpp;mercury/events/TimerEvent.cpp;mercury/executor/Executor.cpp;mercury/topics/Topic.cpp;metrics/metrics.cpp;metricsLine truncated
set(sources api/apicore.proto;api/apigateway.proto;api/apioptions.proto;api/core/ApiClientInterop.cpp;api/core/ApiServerInterop.cpp;api/public/ApiServer.cpp;api/public/ClientChannel.cpp;api/public/QuickbusClientChannel.cpp;api/public/ServerChannel.cpp;api/public/ServiceContext.cpp;api/service_helpers/AdminServiceUtils.cpp;api/service_helpers/AlgoServiceUtils.cpp;api/service_helpers/PositionUtilities.cpp;api/services/AdminService.proto;api/services/AlgoDefinitionService.proto;api/services/AlgoService.proto;api/services/ApiUnitTestService.proto;api/services/AuthService.proto;api/services/BasePositionService.proto;api/services/ErrorReportService.proto;api/services/HelloService.proto;api/services/MBOService.proto;api/services/MarginService.proto;api/services/MarketDataAuxiliaryService.proto;api/services/MarketDataRelay.proto;api/services/MoneyFileService.proto;api/services/OrderService.proto;api/services/OutOfProcessURLListener.proto;api/services/PersistenceService.proto;api/services/PositionService.proto;api/services/ShellDiagnosticService.proto;api/services/ShellLatencyService.proto;api/services/SyntheticSecurityService.proto;api/test/ApiTests.cpp;api/test/HelloServiceServer.cpp;config/ConfigCheck.cpp;config/ConfigDownloader.cpp;config/ConfigErrorCollector.cpp;config/ConfigLog.cpp;config/ConfigPropertyEvaluator.cpp;config/ConfigValueQueue.cpp;config/ConfigurationException.cpp;config/ConfigurationState.cpp;config/PreprocessInputStream.cpp;config/config.cpp;config/defaults/MarketData.conf;config/defaults/Ports.conf;config/defaults/Symbols.conf;config/defaults/cme_reference_data.conf;config/defaults/edge.conf;config/defaults/jetfix.conf;config/defaults/keycode.conf;config/defaults/logging.conf;config/defaults/orderman_cfg.conf;config/defaults/orders_fills_cleanup.conf;config/defaults/position_cfg.conf;config/defaults/span.conf;config/defaults/spreader.conf;config/defaults/testkeys.conf;config/defaults/threads.conf;config/defaults/toggles.conf;config/extensions/extensions.proto;config/invalid/invalid.proto;config/protos/ExchangeSimCfg.proto;config/protos/MarketData.proto;config/protos/Ports.proto;config/protos/Symbols.proto;config/protos/UI.proto;config/protos/cme_reference_data.proto;config/protos/jetfix.proto;config/protos/keycode.proto;config/protos/logging.proto;config/protos/mercury_cfg.proto;config/protos/orderman_cfg.proto;config/protos/orders_fills_cleanup.proto;config/protos/perflog_cfg.proto;config/protos/position_cfg.proto;config/protos/quickbus_cfg.proto;config/protos/span.proto;config/protos/spreader.proto;config/protos/system.proto;config/protos/testkeys.proto;config/protos/threads.proto;config/protos/toggles.proto;config/tests/HTTPServer.cpp;config/tests/config_ref_tests.cpp;config/tests/config_tests.cpp;config/text_format/text_format.cpp;domain_model/Security.cpp;domain_model/Security.proto;domain_model/SecurityTests.cpp;domain_model/sod.cpp;domain_model/tests/domain_tests.cpp;expression/BooleanGrammar.cpp;expression/ExpressionEvaluator.cpp;expression/ParserExceptions.cpp;expression/Value.cpp;expression/tests/expression_parser_tests.cpp;jetfix/codec/FIXArray.cpp;jetfix/common/OutFIX.cpp;jetfix/connection/AsyncReader.cpp;jetfix/connection/IConnection.cpp;jetfix/connection/SocketConnection.cpp;jetfix/gateway/CoreGateway.cpp;jetfix/gateway/JetFIXGateway.cpp;jetfix/gateway/Session.cpp;jetfix/store/FIXFileStore.cpp;jetfix/store/session_name.cpp;jetfix/tests/async_reader_tests.cpp;jetfix/tests/decoding_tests.cpp;jetfix/tests/fix_encoding_stream_tests.cpp;jetfix/tests/fix_fragment_tests.cpp;jetfix/tests/jetfix_performance_tests.cpp;jetfix/tests/sample_fix.cpp;jetfix/tests/store_tests.cpp;logging/LoggerHub.cpp;logging/Sink.cpp;logging/logging.cpp;logging/tests/logging_tests.cpp;md/Diag/MDPeriodicDumper.cpp;md/Diag/ShmDumper.cpp;md/MBOProcessor.cpp;md/MBOServiceServer.cpp;md/MDClient.cpp;md/MDConsumer.cpp;md/MDConsumerHandle.cpp;md/MDConsumerInterop.cpp;md/MDProducer.cpp;md/MDProducerHandle.cpp;md/MemorySegmentUtils.cpp;md/PlatformLoader.cpp;md/PriceSize.cpp;md/SecurityCache.cpp;md/SecurityDB.cpp;md/SecurityIDRecorder.cpp;md/SecurityMapper.cpp;md/SecurityOracle.cpp;md/SettlementRecorder.cpp;md/Shm/FixedSecurity.cpp;md/SyntheticSecurityService.cpp;md/cme/MDP3Utils.cpp;md/common.cpp;md/ice/ICEUtils.cpp;md/protos/co2.proto;md/relay/QueryServer.cpp;md/relay/RelayClient.cpp;md/relay/RelayRecorder.cpp;md/test/Co2ManagedTestHelper.cpp;md/test/Co2TestInstrument.cpp;md/test/mbo_tests.cpp;md/test/md2_tests.cpp;md/test/md_test_utils.cpp;md/test/synthetic_book_merge_tests.cpp;md/vendor/OnixsUtils.cpp;mercury/actors/IPollableActor.cpp;mercury/broker/Broker.cpp;mercury/broker/BrokerProxy.cpp;mercury/broker/ILocalBroker.cpp;mercury/broker/IRemoteBroker.cpp;mercury/common/mercury_common.cpp;mercury/events/TimerEvent.cpp;mercury/executor/Executor.cpp;mercury/topics/Topic.cpp;metrics/metrics.cpp;metrics/system_metrics.cpp;orderman/actors/AsyncFactory.cpp;orderman/actors/ExecutionGateway.cpp;orderman/actors/FillStore.cpp;orLine truncated
+1 -1
View File
@@ -1 +1 @@
set(sources api/apicore.proto;api/apigateway.proto;api/apioptions.proto;api/core/ApiClientInterop.cpp;api/core/ApiServerInterop.cpp;api/public/ApiServer.cpp;api/public/ClientChannel.cpp;api/public/QuickbusClientChannel.cpp;api/public/ServerChannel.cpp;api/public/ServiceContext.cpp;api/service_helpers/AdminServiceUtils.cpp;api/service_helpers/AlgoServiceUtils.cpp;api/service_helpers/PositionUtilities.cpp;api/services/AdminService.proto;api/services/AlgoDefinitionService.proto;api/services/AlgoService.proto;api/services/ApiUnitTestService.proto;api/services/AuthService.proto;api/services/BasePositionService.proto;api/services/ErrorReportService.proto;api/services/HelloService.proto;api/services/MBOService.proto;api/services/MarginService.proto;api/services/MarketDataAuxiliaryService.proto;api/services/MarketDataRelay.proto;api/services/MarketDataService.proto;api/services/MoneyFileService.proto;api/services/OrderService.proto;api/services/OutOfProcessURLListener.proto;api/services/PersistenceService.proto;api/services/PositionService.proto;api/services/ShellDiagnosticService.proto;api/services/ShellLatencyService.proto;api/services/SyntheticSecurityService.proto;api/test/ApiTests.cpp;api/test/HelloServiceServer.cpp;config/ConfigCheck.cpp;config/ConfigDownloader.cpp;config/ConfigErrorCollector.cpp;config/ConfigLog.cpp;config/ConfigPropertyEvaluator.cpp;config/ConfigValueQueue.cpp;config/ConfigurationException.cpp;config/ConfigurationState.cpp;config/PreprocessInputStream.cpp;config/config.cpp;config/defaults/MarketData.conf;config/defaults/Ports.conf;config/defaults/Symbols.conf;config/defaults/cme_reference_data.conf;config/defaults/edge.conf;config/defaults/jetfix.conf;config/defaults/keycode.conf;config/defaults/logging.conf;config/defaults/orderman_cfg.conf;config/defaults/orders_fills_cleanup.conf;config/defaults/position_cfg.conf;config/defaults/span.conf;config/defaults/spreader.conf;config/defaults/testkeys.conf;config/defaults/threads.conf;config/defaults/toggles.conf;config/extensions/extensions.proto;config/invalid/invalid.proto;config/protos/ExchangeSimCfg.proto;config/protos/MarketData.proto;config/protos/Ports.proto;config/protos/Symbols.proto;config/protos/UI.proto;config/protos/cme_reference_data.proto;config/protos/jetfix.proto;config/protos/keycode.proto;config/protos/logging.proto;config/protos/mercury_cfg.proto;config/protos/orderman_cfg.proto;config/protos/orders_fills_cleanup.proto;config/protos/perflog_cfg.proto;config/protos/position_cfg.proto;config/protos/quickbus_cfg.proto;config/protos/span.proto;config/protos/spreader.proto;config/protos/subprocess.proto;config/protos/system.proto;config/protos/testkeys.proto;config/protos/threads.proto;config/protos/toggles.proto;config/tests/HTTPServer.cpp;config/tests/config_ref_tests.cpp;config/tests/config_tests.cpp;config/text_format/text_format.cpp;domain_model/Security.cpp;domain_model/Security.proto;domain_model/SecurityTests.cpp;domain_model/sod.cpp;domain_model/tests/domain_tests.cpp;expression/BooleanGrammar.cpp;expression/ExpressionEvaluator.cpp;expression/ParserExceptions.cpp;expression/Value.cpp;expression/tests/expression_parser_tests.cpp;logging/LoggerHub.cpp;logging/Sink.cpp;logging/logging.cpp;logging/tests/logging_tests.cpp;md/Diag/MDPeriodicDumper.cpp;md/Diag/ShmDumper.cpp;md/MBOProcessor.cpp;md/MBOServiceServer.cpp;md/MDClient.cpp;md/MDConsumer.cpp;md/MDConsumerHandle.cpp;md/MDConsumerInterop.cpp;md/MDProducer.cpp;md/MDProducerHandle.cpp;md/MemorySegmentUtils.cpp;md/PlatformLoader.cpp;md/PriceSize.cpp;md/Product.cpp;md/SecurityCache.cpp;md/SecurityDB.cpp;md/SecurityIDRecorder.cpp;md/SecurityMapper.cpp;md/SecurityOracle.cpp;md/SettlementRecorder.cpp;md/Shm/FixedSecurity.cpp;md/SyntheticSecurityService.cpp;md/cme/MDP3Utils.cpp;md/common.cpp;md/ice/ICEUtils.cpp;md/protos/co2.proto;md/relay/QueryServer.cpp;md/relay/RelayClient.cpp;md/relay/RelayRecorder.cpp;md/service/MarketDataServiceServer.cpp;md/test/Co2ManagedTestHelper.cpp;md/test/Co2TestInstrument.cpp;md/test/mbo_tests.cpp;md/test/md2_tests.cpp;md/test/md_test_utils.cpp;md/test/synthetic_book_merge_tests.cpp;md/vendor/OnixsUtils.cpp;os/os.cpp;os/tests/os_tests.cpp;quickbus/core/LocalNode.cpp;quickbus/core/Quickbus.cpp;quickbus/core/SubscriptionID.cpp;quickbus/core/TableID.cpp;quickbus/message_model/Update.cpp;quickbus/message_model/merge_updates.cpp;quickbus/network/QBConnection.cpp;quickbus/network/QBConnectionManager.cpp;quickbus/network/endpoint_description.cpp;quickbus/network/quickbus_msgs.proto;quickbus/pubsub/TablePublisher.cpp;quickbus/pubsub/TableSubscriber.cpp;quickbus/pubsub/tests/qb_pubsub_tests.cpp;quickbus/routing/INode.cpp;quickbus/routing/NodeID.cpp;quickbus/routing/Router.cpp;quickbus/rpc/RPCClient.cpp;quickbus/rpc/RPCServer.cpp;quickbus/rpc/RPCSessionID.cpp;quickbus/rpc/rpc_utils.cpp;quickbus/rpc/tests/qb_rpc_tests.cpp;quickbus/tests/quickbus_tests.cpp;sparkproto/SparkProtos.proto;testing/catch_test_runner.cpp;utils/AuthSessionManager.cpp;utils/AuthToken.cLine truncated
set(sources api/apicore.proto;api/apigateway.proto;api/apioptions.proto;api/core/ApiClientInterop.cpp;api/core/ApiServerInterop.cpp;api/public/ApiServer.cpp;api/public/ClientChannel.cpp;api/public/QuickbusClientChannel.cpp;api/public/ServerChannel.cpp;api/public/ServiceContext.cpp;api/service_helpers/AdminServiceUtils.cpp;api/service_helpers/AlgoServiceUtils.cpp;api/service_helpers/PositionUtilities.cpp;api/services/AdminService.proto;api/services/AlgoDefinitionService.proto;api/services/AlgoService.proto;api/services/ApiUnitTestService.proto;api/services/AuthService.proto;api/services/BasePositionService.proto;api/services/ErrorReportService.proto;api/services/HelloService.proto;api/services/MBOService.proto;api/services/MarginService.proto;api/services/MarketDataAuxiliaryService.proto;api/services/MarketDataRelay.proto;api/services/MoneyFileService.proto;api/services/OrderService.proto;api/services/OutOfProcessURLListener.proto;api/services/PersistenceService.proto;api/services/PositionService.proto;api/services/ShellDiagnosticService.proto;api/services/ShellLatencyService.proto;api/services/SyntheticSecurityService.proto;api/test/ApiTests.cpp;api/test/HelloServiceServer.cpp;config/ConfigCheck.cpp;config/ConfigDownloader.cpp;config/ConfigErrorCollector.cpp;config/ConfigLog.cpp;config/ConfigPropertyEvaluator.cpp;config/ConfigValueQueue.cpp;config/ConfigurationException.cpp;config/ConfigurationState.cpp;config/PreprocessInputStream.cpp;config/config.cpp;config/defaults/MarketData.conf;config/defaults/Ports.conf;config/defaults/Symbols.conf;config/defaults/cme_reference_data.conf;config/defaults/edge.conf;config/defaults/jetfix.conf;config/defaults/keycode.conf;config/defaults/logging.conf;config/defaults/orderman_cfg.conf;config/defaults/orders_fills_cleanup.conf;config/defaults/position_cfg.conf;config/defaults/span.conf;config/defaults/spreader.conf;config/defaults/testkeys.conf;config/defaults/threads.conf;config/defaults/toggles.conf;config/extensions/extensions.proto;config/invalid/invalid.proto;config/protos/ExchangeSimCfg.proto;config/protos/MarketData.proto;config/protos/Ports.proto;config/protos/Symbols.proto;config/protos/UI.proto;config/protos/cme_reference_data.proto;config/protos/jetfix.proto;config/protos/keycode.proto;config/protos/logging.proto;config/protos/mercury_cfg.proto;config/protos/orderman_cfg.proto;config/protos/orders_fills_cleanup.proto;config/protos/perflog_cfg.proto;config/protos/position_cfg.proto;config/protos/quickbus_cfg.proto;config/protos/span.proto;config/protos/spreader.proto;config/protos/subprocess.proto;config/protos/system.proto;config/protos/testkeys.proto;config/protos/threads.proto;config/protos/toggles.proto;config/tests/HTTPServer.cpp;config/tests/config_ref_tests.cpp;config/tests/config_tests.cpp;config/text_format/text_format.cpp;domain_model/Security.cpp;domain_model/Security.proto;domain_model/SecurityTests.cpp;domain_model/sod.cpp;domain_model/tests/domain_tests.cpp;expression/BooleanGrammar.cpp;expression/ExpressionEvaluator.cpp;expression/ParserExceptions.cpp;expression/Value.cpp;expression/tests/expression_parser_tests.cpp;logging/LoggerHub.cpp;logging/Sink.cpp;logging/logging.cpp;logging/tests/logging_tests.cpp;md/Diag/MDPeriodicDumper.cpp;md/Diag/ShmDumper.cpp;md/MBOProcessor.cpp;md/MBOServiceServer.cpp;md/MDClient.cpp;md/MDConsumer.cpp;md/MDConsumerHandle.cpp;md/MDConsumerInterop.cpp;md/MDProducer.cpp;md/MDProducerHandle.cpp;md/MemorySegmentUtils.cpp;md/PlatformLoader.cpp;md/PriceSize.cpp;md/SecurityCache.cpp;md/SecurityDB.cpp;md/SecurityIDRecorder.cpp;md/SecurityMapper.cpp;md/SecurityOracle.cpp;md/SettlementRecorder.cpp;md/Shm/FixedSecurity.cpp;md/SyntheticSecurityService.cpp;md/cme/MDP3Utils.cpp;md/common.cpp;md/ice/ICEUtils.cpp;md/protos/co2.proto;md/relay/QueryServer.cpp;md/relay/RelayClient.cpp;md/relay/RelayRecorder.cpp;md/test/Co2ManagedTestHelper.cpp;md/test/Co2TestInstrument.cpp;md/test/mbo_tests.cpp;md/test/md2_tests.cpp;md/test/md_test_utils.cpp;md/test/synthetic_book_merge_tests.cpp;md/vendor/OnixsUtils.cpp;os/os.cpp;os/tests/os_tests.cpp;quickbus/core/LocalNode.cpp;quickbus/core/Quickbus.cpp;quickbus/core/SubscriptionID.cpp;quickbus/core/TableID.cpp;quickbus/message_model/Update.cpp;quickbus/message_model/merge_updates.cpp;quickbus/network/QBConnection.cpp;quickbus/network/QBConnectionManager.cpp;quickbus/network/endpoint_description.cpp;quickbus/network/quickbus_msgs.proto;quickbus/pubsub/TablePublisher.cpp;quickbus/pubsub/TableSubscriber.cpp;quickbus/pubsub/tests/qb_pubsub_tests.cpp;quickbus/routing/INode.cpp;quickbus/routing/NodeID.cpp;quickbus/routing/Router.cpp;quickbus/rpc/RPCClient.cpp;quickbus/rpc/RPCServer.cpp;quickbus/rpc/RPCSessionID.cpp;quickbus/rpc/rpc_utils.cpp;quickbus/rpc/tests/qb_rpc_tests.cpp;quickbus/tests/quickbus_tests.cpp;sparkproto/SparkProtos.proto;testing/catch_test_runner.cpp;utils/AuthSessionManager.cpp;utils/AuthToken.cpp;utils/Dispatcher.cpp;utils/GrowableSPSCQueue.cpp;utils/HTTPStream.cpp;utils/PBUtils.cpp;Line truncated
+1 -1
View File
@@ -142,4 +142,4 @@ if (WIN32)
include(${CMAKE_SOURCE_DIR}/tools/vs_filters.cmake)
endif()
@@ -1,46 +0,0 @@
syntax="proto3";
package bts.api;
option csharp_namespace="bts.api";
option cc_enable_arenas=true;
import "lib/api/apioptions.proto";
import "lib/api/apicore.proto";
import "lib/domain_model/Security.proto";
import "lib/md/protos/co2.proto";
message ProductList {
repeated bts.api.Product products = 1;
}
// Should this cary int prices?
message PriceEntry {
double price = 1;
uint32 direct = 10;
uint32 implied = 11;
}
message BookEntry {
uint32 key = 1 [(bts.api.key)=true];
repeated PriceEntry bid = 10;
repeated PriceEntry ask = 20;
}
message TickerEntry {
uint32 key = 1 [(bts.api.key)=true];
int64 time = 2;
double price = 3;
uint32 size = 4;
uint32 total_volume = 5;
bts.co2.AggressorSide aggressor_side = 6;
bool from_spread = 7;
bool gap = 10;
}
service MarketDataService {
rpc get_products(bts.api.VoidMessage) returns (ProductList);
// stream all securities
rpc securities (bts.api.VoidMessage) returns (stream bts.api.Security);
rpc book (bts.api.Product) returns (stream BookEntry);
rpc trades(bts.api.VoidMessage) returns (stream TickerEntry);
// subscribe_misc(Product)
}
+8
View File
@@ -0,0 +1,8 @@
Fix {
value {
enable_acceptor: true
allow_orders: true
fix_config_file: 'spark_fix.cfg'
}
}
+9
View File
@@ -0,0 +1,9 @@
syntax='proto2';
package bts.config;
message Fix {
optional bool enable_acceptor = 5 [default = false];
optional bool allow_orders = 10 [default = false];
optional string fix_config_file = 20;
}
-1
View File
@@ -49,7 +49,6 @@ enum class MessageTypes : uint32_t
TestRequest = '1',
TradingSessionStatus = 'h',
TradingSessionStatusRequest = 'g',
MDIncrementalUpdate = 'X',
ICETraderLogin = ('U' << 16) + ('C' << 8) + 'G',
ICETraderLoginResponse = ('U' << 16) + ('C' << 8) + 'I',
ICETraderLogout = ('U' << 16) + ('C' << 8) + 'H',
+8 -9
View File
@@ -18,8 +18,8 @@
#include <fmt/format.h>
#include <fstream>
#include <regex>
#include <thread>
#include <regex>
namespace bts {
namespace jetfix {
@@ -114,17 +114,16 @@ std::string store_path(std::string base_path,
return result.string();
}
static std::regex store_line_rx("\\d\\d\\d\\d\\d\\d\\d\\d-"
"\\d\\d:\\d\\d:\\d\\d\\."
"\\d\\d\\d . 8=FIX\\.4\\.2.*");
bool is_valid_store_line(std::string const &line) {
return std::regex_match(line, store_line_rx);
bool is_valid_store_line(std::string const&line) {
std::regex rx("\\d\\d\\d\\d\\d\\d\\d\\d-"
"\\d\\d:\\d\\d:\\d\\d\\."
"\\d\\d\\d . 8=FIX\\.4\\.2.*");
return std::regex_match(line, rx);
}
std::map<uint32_t, InMsgBuffer>
load_replay(config::JetFIX::Connection const &cfg, std::string const &path,
uint32_t) {
uint32_t ) {
std::map<uint32_t, InMsgBuffer> result;
if (boost::filesystem::exists(path)) {
@@ -138,7 +137,7 @@ load_replay(config::JetFIX::Connection const &cfg, std::string const &path,
if (!f.eof()) {
if (!is_valid_store_line(line_buffer))
continue;
if (line_buffer[22] == '<') {
auto ts =
datetime::parse_FIX_timestamp(line_buffer.substr(0, 21));
+1
View File
@@ -46,6 +46,7 @@ constexpr log::Subsystem DataFlow {Latency.ordinal+1 };
constexpr log::Subsystem Plugin {DataFlow.ordinal+1 };
constexpr log::Subsystem Sdk {Plugin.ordinal+1 };
constexpr log::Subsystem Http {Sdk.ordinal+1 };
constexpr log::Subsystem Fix {Http.ordinal+1 };
struct LoggerHandle {
LoggerHandle(LoggerHandle const&) = delete;
+110
View File
@@ -0,0 +1,110 @@
#pragma once
#ifndef _WIN32
#include "lib/domain_model/Security.h"
#include "lib/md/MDConsumerHandle.h"
#include "lib/md/MDClient.h"
#include "lib/md/ExchangeOrderKey.h"
#include "lib/utils/LockBox.h"
#include <tuple>
#include <vector>
#include <unordered_map>
#include <optional>
#include <functional>
namespace bts {
namespace md {
security_key default_key(const MDConsumerHandle& h)
{
auto&& key = h.key();
return key;
}
std::string desc_key(const MDConsumerHandle& h)
{
auto&& sec = h.get_normalized_security();
auto&& desc = securities::descriptor(sec);
return desc;
}
template<auto Key_Func>
class HandleIndex
{
MDClient& _client;
int _sub;
std::optional<MDConsumer> _consumer;
public:
typedef decltype( Key_Func(std::declval<MDConsumerHandle>()) ) KeyType;
utils::LockBox<std::unordered_map<KeyType,MDConsumerHandle>> handle_index;
utils::LockBox<std::unordered_map<KeyType,SecurityPtr>> security_index;
HandleIndex(md::MDClient& client) :
_client(client),
_sub(0),
_consumer(std::nullopt),
handle_index(),
security_index()
{
_sub = _client.on_consumer().subscribe([=](const MDConsumer& c) { on_consumer(c); });
on_consumer( _client.current_consumer() );
}
virtual ~HandleIndex()
{
_client.on_consumer().unsubscribe(_sub);
}
private:
void on_consumer(const MDConsumer& c)
{
MDConsumer temp(c);
if (temp.all_heartbeats_ok())
{
auto existing = _consumer ? _consumer->id() : 0;
LOG(md,Info, "Updating HandleIndex MDConsumer. Old {} new {}", existing, temp.id());
// clear the index
handle_index.lock([](auto& index) { index.clear(); });
security_index.lock([](auto& index) { index.clear(); });
// Swap to new consumer
if (_consumer)
{
_consumer->swap(temp);
}
else
{
_consumer = temp;
}
// Subscribe to on_security
auto id = _consumer->id();
_consumer->on_security([this,id](const SecurityPtr& sec, MDConsumerHandle handle)
{
if (_consumer->id() == id)
{
handle_index.lock([this, handle](auto& index)
{
auto key = Key_Func(handle);
index[ key ] = handle;
});
security_index.lock([this, handle, &sec](auto& index)
{
auto key = Key_Func(handle);
index[ key ] = sec;
});
}
});
}
}
};
typedef HandleIndex<default_key> KeyHandleIndex;
typedef HandleIndex<desc_key> DescHandleIndex;
}}
#endif
+10 -57
View File
@@ -8,6 +8,8 @@
#include "MDClient.h"
#include "ExchangeOrderKey.h"
#include "MBOProcessor.h"
#include "MDClient.h"
#include "HandleIndex.h"
#include "lib/utils/LockBox.h"
@@ -21,55 +23,6 @@ using namespace bts::api::orderman;
namespace bts {
namespace md {
//
// Simple class to handle MD recovery and maintain an index of SecurityKey=>MDConsumerHandle
class HandleIndex {
MDClient& _client;
int _sub;
std::optional<MDConsumer> _consumer;
public:
utils::LockBox<std::unordered_map<SecurityKey,MDConsumerHandle>> index;
HandleIndex(md::MDClient& client):
_client(client),
_sub(0),
_consumer(std::nullopt),
index() {
_sub = _client.on_consumer().subscribe([=](const MDConsumer& c) { on_consumer(c); });
on_consumer(_client.current_consumer());
}
~HandleIndex() { _client.on_consumer().unsubscribe(_sub); }
private:
void on_consumer(const MDConsumer& c) {
MDConsumer temp(c);
if (temp.all_heartbeats_ok()) {
auto existing = _consumer ? _consumer->id() : 0;
LOG(md,Info, "Updateing MBOService MDConsumer. Old {} new {}", existing, temp.id());
// clear the index
index.lock([](auto& index) { index.clear(); });
// Swap to new consumer
if (_consumer) {
_consumer->swap(temp);
}
else { _consumer = temp; }
// Subscribe to on_security
auto id = _consumer->id();
_consumer->on_security([this,id](const SecurityPtr&, MDConsumerHandle handle) {
if (_consumer->id() == id) {
index.lock([handle](auto& index) {
index[SecurityKey(handle.key())] = handle;
});
}
});
}
}
};
class ActiveOrder {
SecurityKey _security;
SparkOrderKey _id;
@@ -111,7 +64,7 @@ struct MBOServiceImpl {
MBOServiceImpl(
api::ServiceContext& ctx,
utils::Dispatcher& d,
md::MDClient& c,
MDClient& c,
MBOServiceBase::PiqPublisher&& pub
):
dispatcher(d),
@@ -124,10 +77,10 @@ struct MBOServiceImpl {
{}
utils::Dispatcher& dispatcher;
md::MDClient& client;
MDClient& client;
OrderService orders;
HandleIndex handle_index;
KeyHandleIndex handle_index;
MBOServiceBase::PiqPublisher publish;
utils::DispatcherTimer timer;
@@ -162,10 +115,10 @@ std::optional<uint32_t> search_orders(const ExchangeOrderKey oid, const std::vec
return std::nullopt;
}
bool update_position(const HandleIndex& handles, ActiveOrder& order) {
const auto& index = handles.index;
bool update_position(const KeyHandleIndex& handles, ActiveOrder& order) {
const auto& index = handles.handle_index;
auto handle = index.lock([id=order.security_id()](const auto& index) {
auto iter = index.find(id);
auto iter = index.find(id.value());
return iter != index.end() ? iter->second : MDConsumerHandle {};
});
@@ -300,8 +253,8 @@ MBOServiceServer::~MBOServiceServer() { }
void MBOServiceServer::get_orders_for_security(const MBOSecurityQuery& request, const api::Response<PositionData>& reply) {
PositionData response;
response.set_security_id(request.security_id());
auto handle = _me->handle_index.index.lock([id=request.security_id()](const auto& index) {
auto iter = index.find(SecurityKey(id));
auto handle = _me->handle_index.handle_index.lock([id=request.security_id()](const auto& index) {
auto iter = index.find(id);
return iter != index.end() ? iter->second : MDConsumerHandle {};
});
-37
View File
@@ -1,37 +0,0 @@
#ifndef _WIN32
#include "Product.h"
#include <boost/tokenizer.hpp>
#include <vector>
namespace bts {
namespace api {
std::string product_to_string(const api::Product& p) {
std::string buffer = p.symbol();
buffer += ":";
buffer += SecurityType_Name(p.type());
buffer += ":";
buffer += Venue_Name(p.exchange());
return buffer;
}
std::optional<api::Product> string_to_product(const std::string& s) {
boost::tokenizer<boost::char_separator<char>> tok { s };
std::vector<std::string> parts;
for (const auto& t : tok) {
parts.push_back(t);
}
if (parts.size() != 3) return std::nullopt;
SecurityType type = SecurityType::SECURITYTYPE_UNSET;
if (!SecurityType_Parse(parts[1], &type)) return std::nullopt;
Venue v = Venue::VENUE_UNSET;
if (!Venue_Parse(parts[2], &v)) return std::nullopt;
Product p;
p.set_symbol(parts[0]);
p.set_type(type);
p.set_exchange(v);
return {p};
}
}}//ns
#endif
-13
View File
@@ -1,13 +0,0 @@
#pragma once
#include "lib/domain_model/Security.pb.h"
#include "lib/utils/optional.h"
#include <string>
namespace bts {
namespace api {
std::string product_to_string(const api::Product&);
std::optional<api::Product> string_to_product(const std::string&);
} }
@@ -1,116 +0,0 @@
#ifndef _WIN32
#include "MarketDataServiceServer.h"
#include "lib/metrics/metrics.h"
#include "lib/md/UserSymbol.h"
#include "lib/md/get_symbols.h"
#include "lib/md/Product.h"
#include "lib/utils/AuthToken.h"
#include <atomic>
#include <set>
namespace bts {
namespace md {
struct MarketDataServiceImpl {
MarketDataServiceImpl(api::MarketDataServiceBase::SecuritiesStatefulPublisher);
utils::Dispatcher& dispatcher;
api::MarketDataServiceBase::SecuritiesStatefulPublisher security_publisher;
std::atomic<uint32_t> sec_outstanding;
void add_security(const SecurityPtr& sec) {
++sec_outstanding;
dispatcher.post([this,sec]() {
security_publisher.add_or_update(*sec);
auto flush = (--sec_outstanding) == 0;
if (flush) {
security_publisher.flush();
}
});
}
};
MarketDataServiceImpl::MarketDataServiceImpl(
api::MarketDataServiceBase::SecuritiesStatefulPublisher security_pub) :
dispatcher(utils::Dispatcher::get_named("MDService")),
security_publisher(security_pub),
sec_outstanding(0)
{
}
MarketDataService::MarketDataService(
MDClient& md,
api::ServiceContext ctx,
metrics::MetricsContainer&) :
api::AuthenticatedMarketDataServiceBase(ctx)
{
_me = std::make_shared<MarketDataServiceImpl>(make_securities_stateful_publisher());
md.current_consumer().on_security([me=_me](const SecurityPtr& sec, MDConsumerHandle) {
me->add_security(sec);
});
}
// This method duplicates MarketDataRelayServer::request_products()
void MarketDataService::get_products(
const api::AuthToken&,
const ::bts::api::VoidMessage&,
const api::Response<::bts::api::ProductList>& reply) {
api::ProductList list;
std::set<md::UserSymbol> syms;
md::get_system_md_symbols(syms);
for(const auto& i : syms) {
auto prod = list.add_products();
prod->set_exchange(i.exchange());
prod->set_type(i.type());
prod->set_symbol(i.symbol());
}
reply(list);
}
api::StreamAccessResponse authorized(bool is_authorized) {
api::StreamAccessResponse r;
r.set_authorized(is_authorized);
return r;
}
void MarketDataService::allow_securities(
const bts::api::AuthToken&,
const std::string& qualifier,
const api::Response<bts::api::StreamAccessResponse>& reply) {
// Non-empty qualifier is invalid and rejected
reply(authorized(qualifier.empty()));
}
void MarketDataService::allow_book(
const bts::api::AuthToken& token,
const std::string& qualifier,
const api::Response<bts::api::StreamAccessResponse>& reply) {
api::user::TokenPayload payload;
if (api::auth::decode_token(token, &payload)) {
auto product = api::string_to_product(qualifier);
if (product) {
// todo: start streaming
reply(authorized(true));
}
}
reply(authorized(false));
}
void MarketDataService::allow_trades(
const bts::api::AuthToken& token,
const std::string& qualifier,
const api::Response<bts::api::StreamAccessResponse>& reply) {
api::user::TokenPayload payload;
if (api::auth::decode_token(token, &payload)) {
auto product = api::string_to_product(qualifier);
if (product) {
// todo: start streaming
reply(authorized(true));
}
}
reply(authorized(false));
}
}} //namespace
#endif
@@ -1,43 +0,0 @@
#pragma once
#include "lib/utils/Dispatcher.h"
#include "lib/api/public/ServiceContext.h"
#include "lib/api/services/MarketDataService.server.pb.h"
#include "lib/md/MDClient.h"
#include <memory>
namespace bts {
namespace metrics { class MetricsContainer; }
namespace md {
struct MarketDataServiceImpl;
class MarketDataService : public api::AuthenticatedMarketDataServiceBase {
std::shared_ptr<MarketDataServiceImpl> _me;
public:
MarketDataService(
MDClient& md,
api::ServiceContext ctx,
metrics::MetricsContainer& stats);
void get_products(
const api::AuthToken&,
const ::bts::api::VoidMessage&,
const api::Response<::bts::api::ProductList>&) override;
void allow_securities(
const bts::api::AuthToken&,
const std::string& qualifier,
const api::Response<bts::api::StreamAccessResponse>& reply) override;
void allow_book(
const bts::api::AuthToken& token,
const std::string& qualifier,
const api::Response<bts::api::StreamAccessResponse>& reply) override;
void allow_trades(
const bts::api::AuthToken& token,
const std::string& qualifier,
const api::Response<bts::api::StreamAccessResponse>& reply) override;
};
}} //namespace
+12 -75
View File
@@ -31,9 +31,9 @@ class MDSource : public mercury::Actor, public mercury::IPollableActor {
public:
MDSource(md::MDConsumer &consumer, metrics::MetricsContainer &stats,
trace::PerfLog &log)
: _handles(), _pending_handles(), _status_subs(), _md_consumer(consumer),
: _handles(), _status_subs(), _md_consumer(consumer),
_book_update(), _ticker_update(), _status_update(),
_perf_log(log), _stats(stats), _loop_timer(), _counter(0) {
_perf_log(log), _stats(stats), _loop_timer() {
_trades_buffer.Reserve(1000);
auto cme_channels = md::get_configured_cme_channels();
@@ -169,47 +169,6 @@ class MDSource : public mercury::Actor, public mercury::IPollableActor {
// Publish stats
auto stop = utils::TimeStamp::now();
_loop_timer->observe((start - stop).nanoseconds());
_counter += 1;
if (_counter % (2<<20) == 0) {
// Invoke periodic work every 2M calls on on_poll
// This is approximately 20-30 seconds
do_periodic_work();
}
}
void do_periodic_work() {
if (!_pending_handles.empty()) {
for (auto iter = _pending_handles.begin(); iter != _pending_handles.end(); ++iter) {
if (iter->handle->is_initialized()) {
auto handle = *(iter->handle);
LOG(OrderMan, Info, "Found md for {}. Pending handle removed.", handle.key());
switch(iter->type) {
case MDRequestType::BOOK:
_handles.push_back({utils::TimeStamp(), handle,
get_external_event_channel(handle.get_usersymbol()),
std::make_unique<std::string>(securities::descriptor(
handle.get_normalized_security()))});
break;
case MDRequestType::STATUS:
for (auto& h : _status_subs) {
// no need to reset status
if (h.handle.key() == handle.key()) break;
}
_status_subs.push_back(
StatusRecord{ handle, co2::TRADINGSTATUS_UNKNOWN });
case MDRequestType::TICKER:
// We aren't currently monitoring for pending ticker requests
break;
}
}
}
_pending_handles.erase(
std::remove_if(_pending_handles.begin(),
_pending_handles.end(),
[](const auto& h) { return h.handle->is_initialized(); }),
_pending_handles.end());
}
}
void on_book_sub(SecurityKey sk,
@@ -225,23 +184,14 @@ class MDSource : public mercury::Actor, public mercury::IPollableActor {
LOG(OrderMan, Warn,
"Starting to publish book updates for security key: {}", k);
auto handle = _md_consumer.get_handle(k);
auto mhandle = _md_consumer.get_managed_handle(k);
if (mhandle->is_initialized()) {
auto handle = *mhandle;
_handles.push_back({utils::TimeStamp(), handle,
get_external_event_channel(handle.get_usersymbol()),
std::make_unique<std::string>(securities::descriptor(
handle.get_normalized_security()))});
if (handle.is_synthetic())
synthetic_count_metric.increment();
}
else {
// A pending handle is a handle for security we are reasonbly sure exists
// but we haven't yet found live market data for.
LOG(OrderMan, Warn, "No market data for {}. Pending handle added.", k);
_pending_handles.push_back({ mhandle, MDRequestType::BOOK });
}
_handles.push_back({utils::TimeStamp(), handle,
get_external_event_channel(handle.get_usersymbol()),
std::make_unique<std::string>(securities::descriptor(
handle.get_normalized_security()))});
if (handle.is_synthetic())
synthetic_count_metric.increment();
}
const char *get_external_event_channel(const md::UserSymbol &user_symbol) {
@@ -255,7 +205,7 @@ class MDSource : public mercury::Actor, public mercury::IPollableActor {
metrics::CounterMetric<int> &channel_count_metric) {
auto user_symbol = _md_consumer.get_handle(sk.value()).get_usersymbol();
for (auto &ch : _channels) {
for (auto &ch : _channels)
if (ch.user_symbol == user_symbol) {
auto it =
std::find_if(ch.securities.begin(), ch.securities.end(),
@@ -272,7 +222,6 @@ class MDSource : public mercury::Actor, public mercury::IPollableActor {
}
return;
}
}
// this is a channel we are not subscribed to
channel_count_metric.increment();
@@ -301,14 +250,8 @@ class MDSource : public mercury::Actor, public mercury::IPollableActor {
return;
}
}
auto handle = _md_consumer.get_managed_handle(k);
if (handle->is_initialized()) {
_status_subs.push_back(StatusRecord{ *handle, co2::TRADINGSTATUS_UNKNOWN });
}
else {
LOG(OrderMan, Warn, "No market data for {}. Pending handle added.", k);
_pending_handles.push_back({ handle, MDRequestType::STATUS });
}
auto handle = _md_consumer.get_handle(k);
_status_subs.push_back(StatusRecord{ handle, co2::TRADINGSTATUS_UNKNOWN });
}
struct HandleRecord {
@@ -318,11 +261,6 @@ class MDSource : public mercury::Actor, public mercury::IPollableActor {
std::unique_ptr<std::string> symbol;
};
boost::container::small_vector<HandleRecord, 100> _handles;
struct PendingRecord {
std::shared_ptr<md::MDConsumerHandle> handle;
MDRequestType type;
};
boost::container::small_vector<PendingRecord, 4> _pending_handles;
struct ChannelRecord {
int64_t cursor;
@@ -347,7 +285,6 @@ class MDSource : public mercury::Actor, public mercury::IPollableActor {
metrics::MetricsContainer &_stats;
std::shared_ptr<metrics::HistogramMetric<30>> _loop_timer;
std::map<md::UserSymbol, std::string> _symbol_to_channel;
uint64_t _counter;
};
} // namespace orderman
} // namespace bts
@@ -6,7 +6,7 @@ namespace bts {
namespace orderman {
class ChildTemplate;
struct LegData;
class LegData;
class PyramidAlgo : public IAlgoOrder {
public:
@@ -6,7 +6,7 @@ namespace bts {
namespace orderman {
class ChildTemplate;
struct LegData;
class LegData;
class TASAlgo : public IAlgoOrder {
public:
+7 -7
View File
@@ -5,6 +5,7 @@ from bluetradingsystems/linux_docker
# This lets us query an image to see when it was built
ARG SDK_VERSION=0
ARG SDK_BUILD_DATE=0
ARG USERNAME=bts
# configure build_examples
env SDK_ROOT=/sdk \
@@ -12,14 +13,13 @@ env SDK_ROOT=/sdk \
SDK_BUILD_DATE=$SDK_BUILD_DATE
# add user bts
RUN groupadd --gid 1000 bts && \
useradd -s /bin/bash --uid 1000 --gid 1000 -m bts && \
RUN groupadd --gid 1000 $USERNAME && \
useradd -s /bin/bash --uid 1000 --gid 1000 -m $USERNAME && \
mkdir -p /sparkbin/plugins && \
mkdir /sparkdata && \
mkdir /sdk && \
ln -s /sparkbin/ /sdk/lib && \
echo bts ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/bts && \
chmod 0440 /etc/sudoers.d/bts && \
ln -s /sparkbin/ sdk/lib && \
echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME && \
chmod 0440 /etc/sudoers.d/$USERNAME && \
chown -R bts.bts /sparkbin/plugins && \
chown -R bts.bts /sparkdata
@@ -28,6 +28,6 @@ COPY include/ /sdk/include/
COPY lib/ /sparkbin/
COPY externals /sdk/externals/
COPY spark.conf /sparkdata/conf/
COPY --chown=bts futures.coconut /sparkdata/data/replay/futures.coconut
COPY --chown=$USERNAME futures.coconut /sparkdata/data/replay/futures.coconut
@@ -2,7 +2,7 @@
"name": "Spark sdk container",
"image": "spark_sdk",
"runArgs": [
"--shm-size", "2048m",
"--shm-size", "1024m",
"--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined",
"-u", "bts"
],
@@ -1,20 +0,0 @@
{
"name": "Spark sdk container",
"image": "spark_sdk",
"runArgs": [
"--shm-size", "2048m",
"--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined",
"-u", "bts"
],
"settings": {
"terminal.integrated.shell.linux": "/bin/bash",
"C_Cpp.default.cppStandard": "c++20"
},
// use 9000 to avoid conflict with typical bts dev setup
"appPort": [9000,9001],
"postCreateCommand": "",
"extensions": [
"ms-vscode.cpptools"
]
}
Loaded 100 of 134 files, more files were not shown because too many files have changed in this diff. Show more