Compare commits
1000
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ebaf8ff51f | ||
|
|
b3369db7cc | ||
|
|
279abcfefd | ||
|
|
872e2465a6 | ||
|
|
89fb79c556 | ||
|
|
c92e9df77b | ||
|
|
81aaa853d5 | ||
|
|
4f308faba2 | ||
|
|
0b924033c2 | ||
|
|
3606c707e4 | ||
|
|
5998107e6a | ||
|
|
297982433b | ||
|
|
15ac9d945b | ||
|
|
a0f1d11692 | ||
|
|
e7890a459c | ||
|
|
f7fb5ed400 | ||
|
|
75e98d353f | ||
|
|
01ab0dd3e5 | ||
|
|
fbdf56b4dc | ||
|
|
b698b64879 | ||
|
|
5fc6ff4c00 | ||
|
|
6951272633 | ||
|
|
548611b44f | ||
|
|
322da04723 | ||
|
|
3544eac815 | ||
|
|
7fef7d88ce | ||
|
|
7531cf5eb4 | ||
|
|
5826a083c0 | ||
|
|
ec0d5d22f1 | ||
|
|
d433368795 | ||
|
|
dc4453e510 | ||
|
|
1b1583abda | ||
|
|
9d2f2888bb | ||
|
|
26816f0048 | ||
|
|
e97e6b93c7 | ||
|
|
0d8252e131 | ||
|
|
801b9622f8 | ||
|
|
a5df3f2da2 | ||
|
|
f03a413855 | ||
|
|
f3a692bda2 | ||
|
|
6c3bdbdc34 | ||
|
|
d4749dd381 | ||
|
|
a008f4d0fd | ||
|
|
0ee9521454 | ||
|
|
62cef7c2f7 | ||
|
|
1b39f4e47c | ||
|
|
3212b2fcee | ||
|
|
1576541bd1 | ||
|
|
62e97364fb | ||
|
|
93b954ce46 | ||
|
|
c9da022c58 | ||
|
|
68a822c342 | ||
|
|
0772a13b09 | ||
|
|
5ee2cfb5f6 | ||
|
|
c53f6ad906 | ||
|
|
e8d4fa1200 | ||
|
|
1058c8a80e | ||
|
|
7ecb106880 | ||
|
|
b0c1d93c50 | ||
|
|
8d47584ee8 | ||
|
|
0c5a039226 | ||
|
|
7b95174171 | ||
|
|
31e913fb1b | ||
|
|
2677144bfa | ||
|
|
20f6c76050 | ||
|
|
6b30c42c0d | ||
|
|
4a41f9b166 | ||
|
|
f4bb2aaada | ||
|
|
36b43024ac | ||
|
|
2f62d29f66 | ||
|
|
828f867a80 | ||
|
|
c9663cf7ab | ||
|
|
b85de51d0c | ||
|
|
dc8e65923d | ||
|
|
1469373b9c | ||
|
|
820e937336 | ||
|
|
8b73878782 | ||
|
|
b15106dac4 | ||
|
|
100316b791 | ||
|
|
3c98425226 | ||
|
|
1aa9c46367 | ||
|
|
5211cab351 | ||
|
|
e89a4cce53 | ||
|
|
cb56b90737 | ||
|
|
761a89f052 | ||
|
|
cab6b56606 | ||
|
|
8a743a91a5 | ||
|
|
5dec5dc392 | ||
|
|
27aa4fca26 | ||
|
|
84a2e50bf7 | ||
|
|
297eb5b25b | ||
|
|
d9d0e1f4ef | ||
|
|
6ec0cc8bbe | ||
|
|
795b77ea3f | ||
|
|
91c97d32bb | ||
|
|
e0c50703d7 | ||
|
|
dab1e76766 | ||
|
|
b8c927df27 | ||
|
|
2684d25f09 | ||
|
|
7c95a77ae2 | ||
|
|
31b115d13b | ||
|
|
d681a6924b | ||
|
|
d0cce84d2e | ||
|
|
532591c34f | ||
|
|
562b9419bd | ||
|
|
7f187224c1 | ||
|
|
79b2121f5e | ||
|
|
0bd477594c | ||
|
|
149cd90fb4 | ||
|
|
f74e719a9f | ||
|
|
8b68beae96 | ||
|
|
9cc0b471f2 | ||
|
|
3e035197d0 | ||
|
|
c9d8a640b6 | ||
|
|
1d97e620fd | ||
|
|
f6299ab5c3 | ||
|
|
eaff4774e0 | ||
|
|
bed52db98a | ||
|
|
bd3ef33607 | ||
|
|
25a594895e | ||
|
|
4d468c8026 | ||
|
|
68ed90487b | ||
|
|
ddc2c67fea | ||
|
|
77459e9c64 | ||
|
|
db64f2f45b | ||
|
|
3f7ea71de7 | ||
|
|
d334418655 | ||
|
|
d1844afeae | ||
|
|
b6dc2bd4d4 | ||
|
|
58906eb3b6 | ||
|
|
50e61604ba | ||
|
|
6bd23f106f | ||
|
|
dfd8348724 | ||
|
|
963a4207e2 | ||
|
|
d2e9352e48 | ||
|
|
da42e95754 | ||
|
|
a878a55ac1 | ||
|
|
4305d560aa | ||
|
|
055f0015e7 | ||
|
|
a39d91ceb3 | ||
|
|
ddc50e1fba | ||
|
|
ffb571d1cf | ||
|
|
2a36c05d75 | ||
|
|
a3730eb203 | ||
|
|
d033275694 | ||
|
|
4e58342677 | ||
|
|
5eeb5a534c | ||
|
|
016ddf9b69 | ||
|
|
0cc5817932 | ||
|
|
032836dea4 | ||
|
|
f20c53bced | ||
|
|
a06461eb5e | ||
|
|
34e7d6a617 | ||
|
|
276e9ad0ef | ||
|
|
5968ac10d2 | ||
|
|
31e44d8c10 | ||
|
|
9bf7666c30 | ||
|
|
8fdab4a510 | ||
|
|
385adaa1b0 | ||
|
|
f9506bc9ad | ||
|
|
b9fd0e2e28 | ||
|
|
6b5b517d70 | ||
|
|
80850146c1 | ||
|
|
0680dddab4 | ||
|
|
70aa62c0cf | ||
|
|
06165b3842 | ||
|
|
f21902d60d | ||
|
|
a27f383b62 | ||
|
|
35d4fcc513 | ||
|
|
8a96b00f64 | ||
|
|
2d06fd3d92 | ||
|
|
76050e0722 | ||
|
|
a3f0c2fbf6 | ||
|
|
1ccc4c3746 | ||
|
|
e5d85db888 | ||
|
|
e47b1c3048 | ||
|
|
039791a296 | ||
|
|
e6884b6654 | ||
|
|
8cbae28dd8 | ||
|
|
010a1fecb1 | ||
|
|
ec1d925dbe | ||
|
|
96bec55ee7 | ||
|
|
424bb36fc7 | ||
|
|
c24700195f | ||
|
|
f7184b0949 | ||
|
|
633ebf38a2 | ||
|
|
1eb8352b6b | ||
|
|
33c201b395 | ||
|
|
999973c349 | ||
|
|
4663ae9e4d | ||
|
|
34fc6af137 | ||
|
|
6cc25a7337 | ||
|
|
0c9a9fcb5e | ||
|
|
48b62f1cab | ||
|
|
5a0ceafa66 | ||
|
|
d31969606e | ||
|
|
6c6fb74506 | ||
|
|
a69ed30e70 | ||
|
|
a654f302a2 | ||
|
|
9ca3285888 | ||
|
|
d7d170f228 | ||
|
|
df4c3b9376 | ||
|
|
cf977befd1 | ||
|
|
1d538b4cb0 | ||
|
|
f21c9f96d1 | ||
|
|
16a71a9f63 | ||
|
|
b42febdf60 | ||
|
|
71915de4b0 | ||
|
|
facb3249d0 | ||
|
|
f323efc61a | ||
|
|
be5f54326e | ||
|
|
a8689aee06 | ||
|
|
85b2d257a7 | ||
|
|
f49ca9f7bd | ||
|
|
65cf042639 | ||
|
|
6aae7831bc | ||
|
|
297233eae6 | ||
|
|
57526a5df5 | ||
|
|
69dcbdd348 | ||
|
|
0114dd0276 | ||
|
|
7d26ff641e | ||
|
|
a8ffe3a6ec | ||
|
|
bda135c435 | ||
|
|
ffd35aebac | ||
|
|
c9b2ac290c | ||
|
|
b92fed4f47 | ||
|
|
6d7290db63 | ||
|
|
0d0cf11157 | ||
|
|
0fa97aeb56 | ||
|
|
d1422ddc58 | ||
|
|
340d65a47c | ||
|
|
51ffa7e7f7 | ||
|
|
2a89c3721b | ||
|
|
0156bbfc46 | ||
|
|
f89fb76cb2 | ||
|
|
16adb9ee18 | ||
|
|
fd6eedda87 | ||
|
|
1ef2b2f55d | ||
|
|
e2cd1ec2f3 | ||
|
|
ffd1835218 | ||
|
|
110a5f74de | ||
|
|
6d20c782ca | ||
|
|
fa88ee6f68 | ||
|
|
22ef965840 | ||
|
|
09a19b702c | ||
|
|
c90915fb1c | ||
|
|
18af3dce74 | ||
|
|
154a637ee1 | ||
|
|
88c42ee6bd | ||
|
|
8b583fcbec | ||
|
|
48dfded132 | ||
|
|
baaa3c4f98 | ||
|
|
838550d78a | ||
|
|
0fc2a55378 | ||
|
|
38b466d305 | ||
|
|
0052c88804 | ||
|
|
6d183e0db9 | ||
|
|
ccbf1e1323 | ||
|
|
c3e43beada | ||
|
|
bf8323e79b | ||
|
|
ab44da6a96 | ||
|
|
dbad27e97d | ||
|
|
10656f7071 | ||
|
|
ed00025a01 | ||
|
|
7d076437a5 | ||
|
|
b7ee9aa208 | ||
|
|
601b989e75 | ||
|
|
02c8714cfd | ||
|
|
e25514b75e | ||
|
|
0f05a45d0d | ||
|
|
399e4bf654 | ||
|
|
5908b4478e | ||
|
|
8107b058b0 | ||
|
|
7d3efdb220 | ||
|
|
e335c54f20 | ||
|
|
5b748feb5c | ||
|
|
a1b9bad321 | ||
|
|
e6ef795de7 | ||
|
|
aa88a0906d | ||
|
|
4b75aa6080 | ||
|
|
e6ab7d825a | ||
|
|
7b5155f599 | ||
|
|
c78e6e8315 | ||
|
|
44571a5af5 | ||
|
|
7b833087e5 | ||
|
|
12f1e026d0 | ||
|
|
762ce06f7c | ||
|
|
657973c2d4 | ||
|
|
c509669de9 | ||
|
|
d79378aa28 | ||
|
|
5799d5ed1e | ||
|
|
05a7f9fa72 | ||
|
|
fef0143ee9 | ||
|
|
ece8a12f4a | ||
|
|
6758c94adf | ||
|
|
8930f59cd6 | ||
|
|
967f789114 | ||
|
|
d1210b06cc | ||
|
|
caeda6c12a | ||
|
|
b6bf02045e | ||
|
|
156561c976 | ||
|
|
6a433b8cef | ||
|
|
1d9f0de409 | ||
|
|
66b06d7190 | ||
|
|
9c160f5e41 | ||
|
|
19f4bfb6ab | ||
|
|
a06dc98b98 | ||
|
|
95b6382a3a | ||
|
|
419e8550c1 | ||
|
|
e29c6a1a22 | ||
|
|
daceee2af9 | ||
|
|
ba61d5de76 | ||
|
|
4594282f2a | ||
|
|
58ca003c94 | ||
|
|
70c0d422c8 | ||
|
|
a04871f15f | ||
|
|
f9b67c7ee4 | ||
|
|
69fdec2866 | ||
|
|
9052051872 | ||
|
|
ab5b4e17ad | ||
|
|
ffbdd81a9e | ||
|
|
269b08e119 | ||
|
|
7eb8f32ff7 | ||
|
|
66f58e1d4b | ||
|
|
62274f5129 | ||
|
|
b5b5101faf | ||
|
|
bb232d8f1e | ||
|
|
3bb473f62d | ||
|
|
4295165427 | ||
|
|
10fbf30ac4 | ||
|
|
bb0aedeb0d | ||
|
|
e01c7f5372 | ||
|
|
d6cb22bdf8 | ||
|
|
9a1199a058 | ||
|
|
adcb5502b0 | ||
|
|
62f1911f35 | ||
|
|
d75c8af729 | ||
|
|
1b3f5bc8a6 | ||
|
|
da95ece9fc | ||
|
|
d6ff13dd00 | ||
|
|
1124829aad | ||
|
|
f9d98787a0 | ||
|
|
deca2bedb5 | ||
|
|
1b767f6e5e | ||
|
|
fe647044f8 | ||
|
|
5f52d81194 | ||
|
|
792a4bcace | ||
|
|
f012f4d70b | ||
|
|
aaca502500 | ||
|
|
de64bd843c | ||
|
|
af7897f9f3 | ||
|
|
0defcce179 | ||
|
|
b69035acf7 | ||
|
|
8e33343f9c | ||
|
|
5f718750a3 | ||
|
|
935227cfa2 | ||
|
|
940705a066 | ||
|
|
d2bfcf7603 | ||
|
|
ae4e6c2221 | ||
|
|
2a85289c6a | ||
|
|
0047890f9d | ||
|
|
dab3b3cd80 | ||
|
|
593533736b | ||
|
|
eb29368b80 | ||
|
|
b93203e4b6 | ||
|
|
f87c04a835 | ||
|
|
a63657e0d5 | ||
|
|
b702d8dc9e | ||
|
|
b0e5a4929f | ||
|
|
7d2695e602 | ||
|
|
79a8a29bac | ||
|
|
6aaed0e76e | ||
|
|
8072eece66 | ||
|
|
043d826442 | ||
|
|
3bf9fa08e5 | ||
|
|
79a7b8504e | ||
|
|
ffd2dd22c2 | ||
|
|
469e4636e3 | ||
|
|
15b45b7494 | ||
|
|
edf9fd268f | ||
|
|
9f1bae7d6f | ||
|
|
52a35a56de | ||
|
|
59338635f1 | ||
|
|
0f3c0c2f24 | ||
|
|
fa76cad459 | ||
|
|
b98d51cc55 | ||
|
|
1c10149a2c | ||
|
|
2ab063d5cd | ||
|
|
030cf8a938 | ||
|
|
2b8815c90d | ||
|
|
a7ee3b28ff | ||
|
|
06af24666b | ||
|
|
d7a98a8a95 | ||
|
|
f0a144e786 | ||
|
|
c45f131dc0 | ||
|
|
b5a227f7aa | ||
|
|
b4f2de327a | ||
|
|
6bc5b35295 | ||
|
|
562bb0423a | ||
|
|
122a2c6f53 | ||
|
|
dbf6bc1bf8 | ||
|
|
569bcee7e7 | ||
|
|
8e471af048 | ||
|
|
f7c8ceb88d | ||
|
|
48fca3a9cc | ||
|
|
adce1a40a8 | ||
|
|
6f88e7585b | ||
|
|
7b0fd23b5b | ||
|
|
e433de5241 | ||
|
|
8e1e96d9f8 | ||
|
|
ff9c9e2d64 | ||
|
|
70a1f0305e | ||
|
|
6bb7348b54 | ||
|
|
1cfba93216 | ||
|
|
ba33d9a657 | ||
|
|
5b2a6215a7 | ||
|
|
9edb5625c1 | ||
|
|
a31ad90be4 | ||
|
|
bddebfc25b | ||
|
|
f184ec5ecf | ||
|
|
b0a1d4f448 | ||
|
|
5bcb75b15c | ||
|
|
24ce565051 | ||
|
|
23d4e7f78d | ||
|
|
d3aa696afb | ||
|
|
e33028669d | ||
|
|
81700b03c8 | ||
|
|
8e2092c3e2 | ||
|
|
775ff3e2db | ||
|
|
69dcfdb2bd | ||
|
|
51584e5e0f | ||
|
|
9f48b648b7 | ||
|
|
f0376843db | ||
|
|
cb46e853ee | ||
|
|
9e2ad000d4 | ||
|
|
cb52c14db1 | ||
|
|
2b53a051d3 | ||
|
|
768853bbe5 | ||
|
|
cc40c523f9 | ||
|
|
c7fd8deabe | ||
|
|
6a896586ce | ||
|
|
c4f4a8ff4e | ||
|
|
1cc594d3a4 | ||
|
|
6725762fa1 | ||
|
|
2dd2b4e9b8 | ||
|
|
6c78a949bb | ||
|
|
ce0beafac3 | ||
|
|
b2f27e0a58 | ||
|
|
a9152ff365 | ||
|
|
9ea581367b | ||
|
|
b761e24dbc | ||
|
|
ca8a148108 | ||
|
|
53586d19df | ||
|
|
095e4bc325 | ||
|
|
5b8a5af7cd | ||
|
|
6a8f2a4868 | ||
|
|
b7c9d282ea | ||
|
|
8cc61628e3 | ||
|
|
6f91d1a890 | ||
|
|
548328dc41 | ||
|
|
12c864368d | ||
|
|
dd60692b28 | ||
|
|
9fc4b369bf | ||
|
|
d12200e977 | ||
|
|
38941d9bd9 | ||
|
|
f59f6a54ce | ||
|
|
727898fc9c | ||
|
|
f7b5eeb04c | ||
|
|
908f924e28 | ||
|
|
0ff2fbc4ff | ||
|
|
82535c915a | ||
|
|
038137d002 | ||
|
|
031dd3779d | ||
|
|
5c552f4e50 | ||
|
|
64d43be34a | ||
|
|
d544511993 | ||
|
|
5c2617d065 | ||
|
|
27dfc14085 | ||
|
|
8f43c2e172 | ||
|
|
e030518d60 | ||
|
|
f794537868 | ||
|
|
7a4cb105d8 | ||
|
|
06e4e34625 | ||
|
|
78be61c9ba | ||
|
|
d80045d7c0 | ||
|
|
725a3dd76b | ||
|
|
81e8acb459 | ||
|
|
9cc5a38213 | ||
|
|
dd28d5375c | ||
|
|
46c37059b2 | ||
|
|
b0bfcc861a | ||
|
|
1e353c2a21 | ||
|
|
e283d05d81 | ||
|
|
aaf90c5293 | ||
|
|
4f5f73101d | ||
|
|
e1a5c1e6cd | ||
|
|
e179f7e5a4 | ||
|
|
2ee0f0be2c | ||
|
|
5bdaab0581 | ||
|
|
707b5cf016 | ||
|
|
f415cddf0b | ||
|
|
8c36b498a4 | ||
|
|
dba3747d98 | ||
|
|
c03263ef0b | ||
|
|
94baf15d01 | ||
|
|
c36541cee0 | ||
|
|
14aad6ece8 | ||
|
|
088185d5ce | ||
|
|
08478a2663 | ||
|
|
9fd88f2a86 | ||
|
|
83b8f14aa0 | ||
|
|
aba09e769b | ||
|
|
8de1fa00aa | ||
|
|
d1960850e8 | ||
|
|
b1714cbd83 | ||
|
|
ed3a1a735e | ||
|
|
b6d1eb9773 | ||
|
|
d39d7b8f47 | ||
|
|
fb4ffaeeb9 | ||
|
|
19e4079864 | ||
|
|
a38fb38f33 | ||
|
|
20df8a6597 | ||
|
|
f90ef6e12c | ||
|
|
b528e1c1ec | ||
|
|
97a2ff9adf | ||
|
|
d52ec704fb | ||
|
|
e2d065f6b3 | ||
|
|
6454ea16ae | ||
|
|
298f9261b4 | ||
|
|
09805de03e | ||
|
|
a0d3447a0d | ||
|
|
14be87e22d | ||
|
|
e61f514c0b | ||
|
|
5e84af4f8f | ||
|
|
5f75609d8d | ||
|
|
bd0e697ea3 | ||
|
|
67d62f0d8c | ||
|
|
1712069530 | ||
|
|
2b12e7fee1 | ||
|
|
0fb69c8beb | ||
|
|
6f68c0f6a1 | ||
|
|
a9df42deec | ||
|
|
258f4f394d | ||
|
|
d42ebd7ea5 | ||
|
|
d9bb667351 | ||
|
|
8ef97d012a | ||
|
|
76cc77485a | ||
|
|
6572c7344d | ||
|
|
25dfa9a0a2 | ||
|
|
50f6ce9fb4 | ||
|
|
cba1675da7 | ||
|
|
3720a7728f | ||
|
|
ce26c2acaf | ||
|
|
631964e8bd | ||
|
|
4ea32e06a9 | ||
|
|
3b25e181fa | ||
|
|
3bd4dce5cb | ||
|
|
880dac06b9 | ||
|
|
cb6e004931 | ||
|
|
c19aae91a6 | ||
|
|
2194ea027f | ||
|
|
ded84cfb1c | ||
|
|
0464b61de5 | ||
|
|
7cbfc4d7d7 | ||
|
|
af83516e38 | ||
|
|
8f4f0649a6 | ||
|
|
68834e2a6d | ||
|
|
3e7627ac24 | ||
|
|
3181501210 | ||
|
|
0cec54dd62 | ||
|
|
1766feebcb | ||
|
|
e2d10bc518 | ||
|
|
aacc5d8d27 | ||
|
|
0ddf145ef9 | ||
|
|
e7ee32b3df | ||
|
|
fc41203f28 | ||
|
|
13009a6d90 | ||
|
|
fa55a61ef3 | ||
|
|
e832252669 | ||
|
|
31980f7c14 | ||
|
|
d63ee80f94 | ||
|
|
ca69e11fff | ||
|
|
9d202906f0 | ||
|
|
968dd5a4d3 | ||
|
|
30cb1fd800 | ||
|
|
38eb122bbc | ||
|
|
1b043f77cb | ||
|
|
e2e31d310f | ||
|
|
6890a61b26 | ||
|
|
36828a979f | ||
|
|
57bf60e6df | ||
|
|
8e3a83d314 | ||
|
|
dc43d25c53 | ||
|
|
068e762f44 | ||
|
|
845fa99bd0 | ||
|
|
2b5403bbd5 | ||
|
|
c9ff3e1bb3 | ||
|
|
c60ada3c78 | ||
|
|
ed7790bc0c | ||
|
|
63434516f8 | ||
|
|
8d5715d510 | ||
|
|
e8b1786411 | ||
|
|
b2be4c58c4 | ||
|
|
380d263c5e | ||
|
|
9a13fb3626 | ||
|
|
924eb31d1d | ||
|
|
a8cd07e4d4 | ||
|
|
aa3dda2c57 | ||
|
|
4e78938827 | ||
|
|
02062ee07b | ||
|
|
ed10545d8a | ||
|
|
1335813031 | ||
|
|
cacf3933be | ||
|
|
f7b89b3d39 | ||
|
|
14cbd4a174 | ||
|
|
d86e7c4ad2 | ||
|
|
6e3e4e1385 | ||
|
|
0864925031 | ||
|
|
d122d5704b | ||
|
|
8a1a75098e | ||
|
|
7063035e7b | ||
|
|
0db69f1b1b | ||
|
|
efa07fe96e | ||
|
|
a36f9278d5 | ||
|
|
727f39b6a6 | ||
|
|
d0c978b71c | ||
|
|
6e9d164d32 | ||
|
|
50a96fc22a | ||
|
|
c6499976a9 | ||
|
|
4b8ca8d97e | ||
|
|
7e77e510fc | ||
|
|
bd24381986 | ||
|
|
5830eee68d | ||
|
|
f3928f58dd | ||
|
|
72d57b242e | ||
|
|
9a6e43e4a4 | ||
|
|
ffb443fcb2 | ||
|
|
f22e68f4bc | ||
|
|
09f08f0a57 | ||
|
|
53ca6aade8 | ||
|
|
b968ebe492 | ||
|
|
bbef942f86 | ||
|
|
7859b7923e | ||
|
|
8202b51cb9 | ||
|
|
ddd41ab317 | ||
|
|
d175a53ef8 | ||
|
|
904e238a78 | ||
|
|
0fb1425766 | ||
|
|
2104fd5ad8 | ||
|
|
26a58e82bf | ||
|
|
01e96c8241 | ||
|
|
ab931bb527 | ||
|
|
e756897f88 | ||
|
|
05ea25a86f | ||
|
|
a6ab49a911 | ||
|
|
33ee7ac114 | ||
|
|
61981a0ea1 | ||
|
|
204e9383fa | ||
|
|
d424032757 | ||
|
|
0fcdf3f4ff | ||
|
|
1b48739e1e | ||
|
|
8b96b1d835 | ||
|
|
3569500111 | ||
|
|
05cfcb5648 | ||
|
|
e425064730 | ||
|
|
4a50e7f86d | ||
|
|
15cbacd1d2 | ||
|
|
cdf4a63ae8 | ||
|
|
f35a674b9f | ||
|
|
03a4691bc0 | ||
|
|
a990eac146 | ||
|
|
27f06d0f9d | ||
|
|
7a05ae1714 | ||
|
|
72549a7bcb | ||
|
|
4f46aa5360 | ||
|
|
b07e985e8b | ||
|
|
0c072b018e | ||
|
|
d7456c0528 | ||
|
|
60c5159a4a | ||
|
|
7388472f6a | ||
|
|
c24c31d8d3 | ||
|
|
be006051b5 | ||
|
|
4590dbc056 | ||
|
|
b5e751e625 | ||
|
|
b5a8098d9e | ||
|
|
3d1de2849c | ||
|
|
887850a612 | ||
|
|
0d910d6f6e | ||
|
|
f1fe8226b5 | ||
|
|
d4cd9d5399 | ||
|
|
3a8d3e0104 | ||
|
|
a053609cc9 | ||
|
|
6b311883a5 | ||
|
|
c8e3258544 | ||
|
|
a24e814182 | ||
|
|
417413e8c0 | ||
|
|
1090422fa2 | ||
|
|
ff753b0550 | ||
|
|
74f2e2ac50 | ||
|
|
ffbed31b33 | ||
|
|
4992d2dab6 | ||
|
|
88dbfd4346 | ||
|
|
2c1cf5f2e0 | ||
|
|
3d6e6ea7db | ||
|
|
73d1f67dcd | ||
|
|
ebb427dc90 | ||
|
|
74bed6275a | ||
|
|
20f65a9196 | ||
|
|
69208bf347 | ||
|
|
7c9eac2803 | ||
|
|
2039be54df | ||
|
|
221f24827b | ||
|
|
5e0f1d450c | ||
|
|
ec4f88c68f | ||
|
|
cad611104b | ||
|
|
fe179d44f2 | ||
|
|
c4866253b8 | ||
|
|
932b185769 | ||
|
|
a3e4576165 | ||
|
|
0a1cf0198d | ||
|
|
6b97d55927 | ||
|
|
2780d6da0b | ||
|
|
2e831aa90e | ||
|
|
ad819dca68 | ||
|
|
14f2ae481a | ||
|
|
c222181730 | ||
|
|
d59f7a5bb1 | ||
|
|
0d4f97a023 | ||
|
|
6603e8ad86 | ||
|
|
632a86f670 | ||
|
|
cdbda8250f | ||
|
|
be6c2f8b35 | ||
|
|
ddaf029cc7 | ||
|
|
fae994c057 | ||
|
|
d72796394d | ||
|
|
a3dc6ebc2e | ||
|
|
8278a20b95 | ||
|
|
88401f0c27 | ||
|
|
16493a9919 | ||
|
|
5c9c75463c | ||
|
|
5f6742f1db | ||
|
|
ccb050c8b8 | ||
|
|
43fd07dcfa | ||
|
|
efcb4f471c | ||
|
|
d2f2e03e64 | ||
|
|
ea2aee5044 | ||
|
|
cfeba74900 | ||
|
|
cc3353e243 | ||
|
|
683b85c66b | ||
|
|
789710d841 | ||
|
|
9a76d9c857 | ||
|
|
231f596ad7 | ||
|
|
41bc4f7950 | ||
|
|
963bd15b35 | ||
|
|
3c7dbc0489 | ||
|
|
3046871cf4 | ||
|
|
dd9ca350af | ||
|
|
b292f50d99 | ||
|
|
910cf20473 | ||
|
|
5ac8a46a6c | ||
|
|
decdae424d | ||
|
|
4228dcab95 | ||
|
|
d99a2f5b88 | ||
|
|
b080d4a9c4 | ||
|
|
282e10cba3 | ||
|
|
dd67252173 | ||
|
|
540559de3e | ||
|
|
19871752ee | ||
|
|
4801a16977 | ||
|
|
7aaae817ac | ||
|
|
d6499464cf | ||
|
|
52d30249fe | ||
|
|
a14d449b33 | ||
|
|
14a86d7b29 | ||
|
|
19729a276d | ||
|
|
0f1135d5d6 | ||
|
|
146b5bdd8a | ||
|
|
1783feffe7 | ||
|
|
fa1b436fb3 | ||
|
|
1a9ff09f43 | ||
|
|
38964f4d10 | ||
|
|
637d7384b1 | ||
|
|
191518d8bc | ||
|
|
50768750d6 | ||
|
|
b3f8976922 | ||
|
|
dfe906ea64 | ||
|
|
450ef7dd56 | ||
|
|
89a4f9264a | ||
|
|
55ade15574 | ||
|
|
36b8b35e47 | ||
|
|
23bb872052 | ||
|
|
1af8247a69 | ||
|
|
de569e2564 | ||
|
|
fc24c768d8 | ||
|
|
7aee876d54 | ||
|
|
3e3e519403 | ||
|
|
3e40bf9fd3 | ||
|
|
315ca96d4f | ||
|
|
9d1c0d7f44 | ||
|
|
97b2f2df75 | ||
|
|
92a9127160 | ||
|
|
388d491a0a | ||
|
|
13b09ffc12 | ||
|
|
2ec7aa5f3f | ||
|
|
6148a08b62 | ||
|
|
e914ca9c15 | ||
|
|
17c2a91a0f | ||
|
|
09d75af8c3 | ||
|
|
83a2a01789 | ||
|
|
e1137c4e1d | ||
|
|
bf8df1d396 | ||
|
|
97e1277b6a | ||
|
|
c198965a49 | ||
|
|
a10a49cf4f | ||
|
|
cfec77bb96 | ||
|
|
03e2433201 | ||
|
|
d064af817c | ||
|
|
7b3c4b76bc | ||
|
|
5de431f279 | ||
|
|
7b63d951f0 | ||
|
|
018887980b | ||
|
|
8b4d649bd4 | ||
|
|
441d3c886b | ||
|
|
472e32f558 | ||
|
|
472c9252f9 | ||
|
|
98a9ad3ef2 | ||
|
|
7b237fedea | ||
|
|
7281aa8ff1 | ||
|
|
d915e2f064 | ||
|
|
beb5d855b1 | ||
|
|
120b86aaae | ||
|
|
44eeff98e7 | ||
|
|
dc420a097a | ||
|
|
69ee85dea9 | ||
|
|
c42bc45f24 | ||
|
|
37a8ae6677 | ||
|
|
a271abf3c4 | ||
|
|
76f582613b | ||
|
|
e15d7babbd | ||
|
|
469914c6c9 | ||
|
|
edba0e1cd7 | ||
|
|
ac1c5566ac | ||
|
|
4564e630db | ||
|
|
5c77fa2799 | ||
|
|
db234c7d06 | ||
|
|
1bb4ce91cf | ||
|
|
d1a3857119 | ||
|
|
6dd63156cc | ||
|
|
01f178fe3b | ||
|
|
53672e1875 | ||
|
|
e7a20252a0 | ||
|
|
497884fe00 | ||
|
|
f7aa2c5bec | ||
|
|
5c75507f42 | ||
|
|
ba1b459b0b | ||
|
|
bac7ea06f2 | ||
|
|
26c577f94b | ||
|
|
4fc59c2ca8 | ||
|
|
0a6cc0cdf1 | ||
|
|
e96d9112ef | ||
|
|
3a7fbe2ddf | ||
|
|
2bfc3148d1 | ||
|
|
72734bb15f | ||
|
|
1dd72abc9a | ||
|
|
6dfcb970b8 | ||
|
|
72aab5bbcb | ||
|
|
0afededebf | ||
|
|
8c8e4dd0e8 | ||
|
|
17769cbced | ||
|
|
5cb1220d05 | ||
|
|
37ba9f7b0d | ||
|
|
9a1bf1bbae | ||
|
|
a404bbf654 | ||
|
|
0b34457259 | ||
|
|
5939b983dd | ||
|
|
c0b0ffd646 | ||
|
|
21a48ba0ad | ||
|
|
9a21d03311 | ||
|
|
46d6ca9d2c | ||
|
|
6ef274d5d6 | ||
|
|
36d507b3ca | ||
|
|
54820107db | ||
|
|
38bf521132 | ||
|
|
4aa0d878a6 | ||
|
|
03bbf2f4a8 | ||
|
|
f2d284cadb | ||
|
|
9f1ac3ee80 | ||
|
|
6b81dcef7d | ||
|
|
1f0371e870 | ||
|
|
322f1164be | ||
|
|
c6cae3064d | ||
|
|
7c13474e31 | ||
|
|
72aa028bd6 | ||
|
|
f8d5b9bace | ||
|
|
e861e2916f | ||
|
|
23738b109d | ||
|
|
713e11d146 | ||
|
|
444e3154b3 | ||
|
|
270ee60df9 | ||
|
|
1ce041c5e5 | ||
|
|
50940bfd13 | ||
|
|
06c1f60598 | ||
|
|
37414d6c78 | ||
|
|
3057f8233d | ||
|
|
8cb4151f63 | ||
|
|
e000d34766 | ||
|
|
87a8665273 | ||
|
|
7a47b7a85a | ||
|
|
a60a792dfa | ||
|
|
a73a1cc4f5 | ||
|
|
32fbdf8a21 | ||
|
|
75c54bbe3e | ||
|
|
38575039b9 | ||
|
|
43a49b9399 | ||
|
|
618c41ce97 | ||
|
|
bd8c9c354b | ||
|
|
8f5d062a3b | ||
|
|
e1a3950051 | ||
|
|
7e816c1503 | ||
|
|
15d9afb2de | ||
|
|
b5468e5565 | ||
|
|
a4c3a61f13 | ||
|
|
7ce101f7f7 | ||
|
|
b61cab397d | ||
|
|
222e1a51dc | ||
|
|
9fa3464188 | ||
|
|
fee695d3d9 | ||
|
|
140f1d88ea | ||
|
|
c4eeaf2ec8 | ||
|
|
54dd30245f | ||
|
|
263ff63a37 | ||
|
|
f3d16502de | ||
|
|
4b7db298c4 | ||
|
|
65f41452fb | ||
|
|
d7a2ae4b09 | ||
|
|
61ac626542 | ||
|
|
8d7a2f342e | ||
|
|
0db037175f | ||
|
|
98aa463b4e | ||
|
|
0b40d3971d | ||
|
|
a21a769909 | ||
|
|
ca8e540453 | ||
|
|
134950747f | ||
|
|
5abc17adf3 | ||
|
|
f3cd3a402e | ||
|
|
c7217b8475 | ||
|
|
99c5129ea7 | ||
|
|
d025ee0c89 | ||
|
|
c24ddaa190 | ||
|
|
442aa156ac | ||
|
|
e906d41cc2 | ||
|
|
6e09d9e949 | ||
|
|
aea02e212a | ||
|
|
a94a66234a | ||
|
|
4cbbf6972a | ||
|
|
caa9671c96 | ||
|
|
20eb3ed39d | ||
|
|
772a898433 | ||
|
|
b5997d326e | ||
|
|
f8626f81cd | ||
|
|
bc208d2421 | ||
|
|
625ebcc762 | ||
|
|
0a163badf0 | ||
|
|
dea95455a0 | ||
|
|
f0f5988abf | ||
|
|
db5f16985c | ||
|
|
f0105867be | ||
|
|
2c0b314428 | ||
|
|
3cd74f33f1 | ||
|
|
a6ee36f4bc | ||
|
|
9cadf635fb | ||
|
|
43e043b044 | ||
|
|
6bac75d7ab | ||
|
|
7ceb170c5f | ||
|
|
47c7ee71b4 | ||
|
|
4f58452771 | ||
|
|
d5bf15cc36 | ||
|
|
9736541385 | ||
|
|
5591c8316d | ||
|
|
a44d3a2c26 | ||
|
|
dceb300324 | ||
|
|
84b9ca3096 | ||
|
|
17e9f1ea96 | ||
|
|
946ec36840 | ||
|
|
11425a898f | ||
|
|
d0029e7f88 | ||
|
|
bdbdda947f | ||
|
|
f88ab57fa0 | ||
|
|
36442a037e | ||
|
|
5969568dee | ||
|
|
96265ea187 | ||
|
|
9676b1fdca | ||
|
|
556132c2dd | ||
|
|
a22b7b7189 | ||
|
|
8e41a42ced | ||
|
|
e0f7bdfc13 | ||
|
|
ec0b96215f | ||
|
|
e27a8be526 | ||
|
|
70cd9f185e | ||
|
|
33eaf6f86d |
No files matched your search
+2
-2
@@ -32,5 +32,5 @@ trace_data/
|
||||
/src/lib/orderman/perf_analysis/last_pretty_log.csv
|
||||
/src/lib/orderman/perf_analysis/log.csv
|
||||
/doc/user/public/*
|
||||
.ionide/*
|
||||
src/web/ui/.ionide/symbolCache.db
|
||||
.ionide/*
|
||||
/.ignore
|
||||
@@ -1 +1 @@
|
||||
set(sources /home/ppinto/Dropbox/bts/spark/doc/user/build.sh;content/_index.md;content/bts_spark/Algos/_index.md;content/bts_spark/Glossary/index.md;content/bts_spark/Help/about_spark.png;content/bts_spark/Help/image39.png;content/bts_spark/Help/image58.png;content/bts_spark/Help/index.md;content/bts_spark/Launcher/image38.png;content/bts_spark/Launcher/image68.png;content/bts_spark/Launcher/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/Logging-In-to-the-System/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/index.md;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/image15.png;content/bts_spark/My-Windows/image16.png;content/bts_spark/My-Windows/image37.png;content/bts_spark/My-Windows/index.md;content/bts_spark/Settings/image51.png;content/bts_spark/Settings/image9.png;content/bts_spark/Settings/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/Spreader/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/index.md;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)
|
||||
@@ -3,6 +3,10 @@ title = "Glossary of Terms"
|
||||
weight = 9
|
||||
sort_by = "weight"
|
||||
insert_anchor_links = "right"
|
||||
|
||||
|
||||
[extra]
|
||||
page_description = "Definitions of common terms used in BTS Spark and this manual"
|
||||
+++
|
||||
|
||||
|
||||
|
||||
@@ -3,12 +3,12 @@ title = "Help"
|
||||
weight = 3
|
||||
sort_by = "weight"
|
||||
insert_anchor_links = "right"
|
||||
|
||||
[extra]
|
||||
page_description = "Report a problem or find the activity log from the Help module in BTS Spark"
|
||||
+++
|
||||
|
||||
|
||||
<div>
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/yGQfr_puT3w" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</div>
|
||||
{{ youtube(id="yGQfr_puT3w") }}
|
||||
|
||||
## Report a Problem
|
||||
If there is any issue at all, you can click here
|
||||
@@ -18,14 +18,14 @@ insert_anchor_links = "right"
|
||||
send, BTS will get an alert of everything you submitted and will be
|
||||
in contact with you shortly.
|
||||
|
||||

|
||||
{{ image(name="image58.png", alt="screenshot") }}
|
||||
|
||||
## About Spark
|
||||
Upon launching this, you will see an info window
|
||||
which will list what version you are running as well as who is
|
||||
currently logged in.
|
||||
|
||||

|
||||
{{ image(name="about_spark.png", alt="screenshot") }}
|
||||
|
||||
## Activity log
|
||||
This is an overall log viewer which will show
|
||||
@@ -34,4 +34,4 @@ insert_anchor_links = "right"
|
||||
messages in a text box in the right top corner.
|
||||
|
||||
|
||||

|
||||
{{ image(name="image39.png", alt="screenshot") }}
|
||||
@@ -1,15 +1,15 @@
|
||||
+++
|
||||
title = "Module Launcher"
|
||||
title = "Launcher"
|
||||
weight = 2
|
||||
sort_by = "weight"
|
||||
insert_anchor_links = "right"
|
||||
|
||||
[extra]
|
||||
page_description = "The basics of the BTS Spark launcher and user interface"
|
||||
+++
|
||||
|
||||
|
||||
|
||||
<div>
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/OxVqQBKFIDw" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</div>
|
||||
{{ youtube(id="OxVqQBKFIDw") }}
|
||||
|
||||
- The module launcher is the first item that will come up after
|
||||
logging in to Spark.
|
||||
@@ -18,7 +18,7 @@ insert_anchor_links = "right"
|
||||
each module
|
||||
- It appears like the following:
|
||||
|
||||

|
||||
{{ image(name="image38.png", alt="screenshot") }}
|
||||
|
||||
- If you right-click anywhere on the launcher you can modify
|
||||
various display settings including:
|
||||
@@ -29,7 +29,7 @@ insert_anchor_links = "right"
|
||||
- Ability to exit the front end, this can also be done by simply clicking the “X” on the top right of this window or by clicking on exit from this options window
|
||||
- These options are all displayed like the following:
|
||||
|
||||

|
||||
{{ image(name="image68.png", alt="screenshot") }}
|
||||
|
||||
## Spark User interface
|
||||
|
||||
|
||||
@@ -3,17 +3,21 @@ title = "Logging in to the system"
|
||||
weight = 1
|
||||
sort_by = "weight"
|
||||
insert_anchor_links = "right"
|
||||
|
||||
[extra]
|
||||
page_description = "How to log into BTS Spark"
|
||||
+++
|
||||
|
||||
|
||||
The shortcut icon will appear on your desktop like below:
|
||||
|
||||

|
||||
{{ image(name="image64.png", alt="BTS icon") }}
|
||||
|
||||
Simply double click or single click and hit enter to launch the
|
||||
login screen:
|
||||
|
||||

|
||||
{{ image(name="image3.png", alt="login screen") }}
|
||||
|
||||
|
||||
Choose your username from the drop down, choose your initial
|
||||
workspace, enter your password, and click Login
|
||||
@@ -3,22 +3,22 @@ title = "Market"
|
||||
weight = 4
|
||||
sort_by = "weight"
|
||||
insert_anchor_links = "right"
|
||||
+++
|
||||
|
||||
[extra]
|
||||
page_description = "The BTS Spark Market module contains the Market View and Time and Sales windows"
|
||||
+++
|
||||
|
||||
|
||||
- This is one of the main items on the module launcher
|
||||
- When hovering over it, it will show 2 different modules which can
|
||||
be launched from it, market view and then, time and sales
|
||||
- It appears like the below:
|
||||
|
||||

|
||||
|
||||
{{ image(name="image53.png", alt="screenshot") }}
|
||||
|
||||
## Market View
|
||||
|
||||
<div>
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/Y54S1uscT_g" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</div>
|
||||
{{ youtube(id="Y54S1uscT_g") }}
|
||||
|
||||
- This provides a grid of outright, spread, and synthetic products
|
||||
showing real-time market data all in one place
|
||||
@@ -29,7 +29,7 @@ insert_anchor_links = "right"
|
||||
- You choose which products you would like to view upon launching it,
|
||||
the security browser will appear as shown below:
|
||||
|
||||

|
||||
{{ image(name="image21.png", alt="security picker") }}
|
||||
|
||||
- Click on individual securities that you wish to view and click add,
|
||||
they will then show up in the selected securities window below. If
|
||||
@@ -45,13 +45,13 @@ insert_anchor_links = "right"
|
||||
- Below is an example of an outright, spread, all futures, and
|
||||
synthetic chosen:
|
||||
|
||||

|
||||
{{ image(name="image14.png", alt="screenshot") }}
|
||||
|
||||
- Clicking OK will bring up the Market View with the selected
|
||||
securities you have chosen, in this example, it appears like the
|
||||
following:
|
||||
|
||||

|
||||
{{ image(name="market_view.png", alt="screenshot") }}
|
||||
|
||||
- Once a market view is launched and you are viewing data, you can
|
||||
customize the view further by the following:
|
||||
@@ -61,19 +61,19 @@ insert_anchor_links = "right"
|
||||
- Filtering - by hovering over the column header, a filtering box
|
||||
will appear like below:
|
||||
|
||||

|
||||
{{ image(name="image66.png", alt="screenshot") }}
|
||||
|
||||
- All columns let you sort by that columns minimum and maximum
|
||||
information in a box that appears like the following:
|
||||
|
||||

|
||||
{{ image(name="image24.png", alt="screenshot") }}
|
||||
|
||||
- Specifically for the securities column, there is a search box that
|
||||
will appear by bringing up the filtering box, which enables users to
|
||||
type the security in which they are looking for. This appears like
|
||||
the following:
|
||||
|
||||

|
||||
{{ image(name="image11.png", alt="screenshot") }}
|
||||
|
||||
- Besides viewing the market data, you can do a lot within the market
|
||||
view by utilizing the icons to the left of the main window, these
|
||||
@@ -88,7 +88,7 @@ insert_anchor_links = "right"
|
||||
|
||||
- Change securities
|
||||
|
||||
- Click on the settings icon  which will launch the market view security selection. You can add or remove Securities you have already selected and are shown in the market view.
|
||||
- Click on the settings icon {{ image(name="change_securities.png", alt="screenshot") }} which will launch the market view security selection. You can add or remove Securities you have already selected and are shown in the market view.
|
||||
|
||||
- Launch an order ticket
|
||||
- This is done 1 of 3 ways:
|
||||
@@ -96,7 +96,7 @@ insert_anchor_links = "right"
|
||||
or Ask Qty which will bring up an order ticket pre-populated with
|
||||
either the Bid or Ask price and volume.
|
||||
- Highlighting a single security and clicking on the order ticket
|
||||
 icon
|
||||
{{ image(name="image23.png", alt="screenshot") }} icon
|
||||
on the left-hand browser window of the market view
|
||||
- Highlighting a single security and right clicking bringing up the
|
||||
menu options to launch an order ticket.
|
||||
@@ -121,7 +121,7 @@ insert_anchor_links = "right"
|
||||
|
||||
- This is done by either highlighting 1 or many securities and then
|
||||
clicking on the Fills icon
|
||||
 on
|
||||
{{ image(name="image20.png", alt="screenshot") }} on
|
||||
the left-hand side to bring up a fill window for the selected
|
||||
securities.
|
||||
|
||||
@@ -132,14 +132,14 @@ insert_anchor_links = "right"
|
||||
|
||||
- This is accomplished by highlighting 1 or many securities and then
|
||||
clicking on the time and sales icon
|
||||
 on
|
||||
{{ image(name="image49.png", alt="screenshot") }} on
|
||||
the left-hand side
|
||||
|
||||
- Launching the synthetic window to create a synthetic product
|
||||
|
||||
- This is accomplished by highlighting either 1 or 2 securities and
|
||||
clicking on the Synthetic icon
|
||||
 on
|
||||
{{ image(name="image34.png", alt="screenshot") }} on
|
||||
the lower left-hand side
|
||||
|
||||
- Please note - If only 1 security is chosen, a create synthetic
|
||||
@@ -148,9 +148,7 @@ insert_anchor_links = "right"
|
||||
|
||||
## Time and Sales
|
||||
|
||||
<div>
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/nEkSGacjt0s" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</div>
|
||||
{{ youtube(id="nEkSGacjt0s") }}
|
||||
|
||||
- Provides a display of real-time fills as they happen for 1 or many
|
||||
securities
|
||||
@@ -161,9 +159,9 @@ insert_anchor_links = "right"
|
||||
- On launching a security browser will appear, allowing you to choose
|
||||
the products you would like to view.
|
||||
|
||||

|
||||
{{ image(name="time_and_sales.png", alt="screenshot") }}
|
||||
|
||||
- From time and sales, you can launch the same items as the market
|
||||
view with the exception of a launching the synthetic window to
|
||||
create a synthetic product
|
||||
- From the settings icon  you can customize the time and sales modifying grid; the colors of the aggressor, status of trades coming in, as well as font sizes and which columns to see.
|
||||
- From the settings icon {{ image(name="settings_icon.png", alt="screenshot") }} you can customize the time and sales modifying grid; the colors of the aggressor, status of trades coming in, as well as font sizes and which columns to see.
|
||||
@@ -3,13 +3,13 @@ title = "My Windows"
|
||||
weight = 7
|
||||
sort_by = "weight"
|
||||
insert_anchor_links = "right"
|
||||
|
||||
[extra]
|
||||
page_description = "Name and load windows with the My Windows module in BTS Spark"
|
||||
+++
|
||||
|
||||
|
||||
|
||||
<div>
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/pjm1JJ9Q3jM" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</div>
|
||||
{{ youtube(id="pjm1JJ9Q3jM") }}
|
||||
|
||||
This is the housing of the windows that you have manually named and
|
||||
creates a place where you can quickly and easily launch windows
|
||||
@@ -20,18 +20,18 @@ click on any tab and the “Add to My Windows” menu will appear. If you
|
||||
click on Add to My Windows, it will give you the ability to type in a
|
||||
text box on the tab itself.
|
||||
|
||||

|
||||
{{ image(name="image16.png", alt="screenshot") }}
|
||||
|
||||
Once you have named the tab, click enter to get out of the editing view
|
||||
of the text box. Once that is done, it will display that name for that
|
||||
tab moving forward, which will be displayed within the My Windows
|
||||
section of the module launcher.
|
||||
|
||||

|
||||
{{ image(name="image15.png", alt="screenshot") }}
|
||||
|
||||
Right-clicking on a tab that has already had its default title modified
|
||||
will show the following which will allow you to rename the modified
|
||||
title or remove it from the My Windows, which will then restore the
|
||||
default standard title.
|
||||
|
||||

|
||||
{{ image(name="image37.png", alt="screenshot") }}
|
||||
@@ -3,12 +3,13 @@ title = "Settings"
|
||||
weight = 8
|
||||
sort_by = "weight"
|
||||
insert_anchor_links = "right"
|
||||
|
||||
|
||||
[extra]
|
||||
page_description = "The BTS Spark Settings module and workspaces management"
|
||||
+++
|
||||
|
||||
|
||||
<div>
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/yGQfr_puT3w" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</div>
|
||||
{{ youtube(id="yGQfr_puT3w") }}
|
||||
|
||||
## Workspaces
|
||||
|
||||
@@ -16,7 +17,7 @@ This is where your workspaces can be saved or switched
|
||||
to pre-saved ones that you have created. If you click on the
|
||||
Settings module, the Workspaces
|
||||
|
||||

|
||||
{{ image(name="image9.png", alt="screenshot") }}
|
||||
|
||||
Once the Workspace menu is launched you can save your current workspace
|
||||
by typing in a name in the text box and clicking save. This will save
|
||||
@@ -26,4 +27,4 @@ switching to it from the workspace launcher later on.
|
||||
You can also delete workspaces by clicking on the “X” to the right of
|
||||
the saved workspace from the workspace menu.
|
||||
|
||||

|
||||
{{ image(name="image51.png", alt="screenshot") }}
|
||||
@@ -3,47 +3,33 @@ title = "Spreader"
|
||||
weight = 6
|
||||
sort_by = "weight"
|
||||
insert_anchor_links = "right"
|
||||
[extra]
|
||||
page_description = "How to create and edit synthetic spreads in BTS Spark's spreader"
|
||||
+++
|
||||
|
||||
{{ youtube(id="RZU9Wj0cETo") }}
|
||||
{{ youtube(id="XEZpuPAgMC0") }}
|
||||
{{ youtube(id="EVFK2yNQFS4") }}
|
||||
{{ youtube(id="d5ywlHen6yo") }}
|
||||
{{ youtube(id="Mmw8PNJA0Dw") }}
|
||||
{{ youtube(id="QK-bBSH6Rc0") }}
|
||||
|
||||
<div>
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/XEZpuPAgMC0" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/EVFK2yNQFS4" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
|
||||
<div>
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/d5ywlHen6yo" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/Mmw8PNJA0Dw" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/QK-bBSH6Rc0" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
- Launching the spreader from the module launcher will bring up the
|
||||
- Launching the spreader from the launcher will bring up the
|
||||
synthetic management browser which appears like below:
|
||||
|
||||

|
||||
{{ image(name="image35.png", alt="screenshot") }}
|
||||
|
||||
- From this window, it will show any synthetics that you have already
|
||||
created as well as various other options of both managing the
|
||||
synthetics and other tasks all from the left-hand side pane within
|
||||
the window, including:
|
||||
|
||||
- Adding a new synthetic 
|
||||
- Removing a synthetic 
|
||||
- Changing a synthetic 
|
||||
- Cloning a synthetic 
|
||||
- Launching a ladder of a highlighted synthetic 
|
||||
- Launching an order book of selected synthetic 
|
||||
- Adding a new synthetic {{ image(name="image8.png", alt="screenshot") }}
|
||||
- Removing a synthetic {{ image(name="image13.png", alt="screenshot") }}
|
||||
- Changing a synthetic {{ image(name="image55.png", alt="screenshot") }}
|
||||
- Cloning a synthetic {{ image(name="image28.png", alt="screenshot") }}
|
||||
- Launching a ladder of a highlighted synthetic {{ image(name="image7.png", alt="screenshot") }}
|
||||
- Launching an order book of selected synthetic {{ image(name="image43.png", alt="screenshot") }}
|
||||
|
||||
|
||||
|
||||
@@ -63,7 +49,7 @@ insert_anchor_links = "right"
|
||||
- An empty synthetic browser will look like below without any legs
|
||||
chosen:
|
||||
|
||||

|
||||
{{ image(name="image31.png", alt="screenshot") }}
|
||||
|
||||
- Clicking on Add Leg on the top right of the window will launch the
|
||||
security browser, which will allow you to choose the first leg
|
||||
@@ -77,13 +63,13 @@ insert_anchor_links = "right"
|
||||
name your synthetic product. By default, it will auto-populate
|
||||
based on the symbols you have chosen:
|
||||
|
||||

|
||||
{{ image(name="image29.png", alt="screenshot") }}
|
||||
|
||||
- You can click into the text box to the right of the name and
|
||||
customize the name to be whatever you would like, we’ll call this
|
||||
ES\_CAL:
|
||||
|
||||

|
||||
{{ image(name="image19.png", alt="screenshot") }}
|
||||
|
||||
- Also included on this row are what ticks you would like this to be
|
||||
priced in as well as the format of the pricing
|
||||
@@ -92,7 +78,7 @@ insert_anchor_links = "right"
|
||||
as the option to add additional legs through the add leg box to the
|
||||
right of the symbols:
|
||||
|
||||

|
||||
{{ image(name="image18.png", alt="screenshot") }}
|
||||
|
||||
- The following rows are all part of the main parameters which can
|
||||
all be modified according to the traders style of designing the
|
||||
@@ -104,14 +90,14 @@ insert_anchor_links = "right"
|
||||
details of how that parameter functions. Below is an example of the
|
||||
throttle details displayed:
|
||||
|
||||

|
||||
{{ image(name="image56.png", alt="screenshot") }}
|
||||
|
||||
- Main parameters - these are the top 4 rows in the Create Synthetic
|
||||
window which all synthetics will be required to have set.
|
||||
Everything below these can be customized to a trader's needs, however, the top 4 are the main foundational aspects used for the calculation of
|
||||
the synthetic:
|
||||
|
||||

|
||||
{{ image(name="image10.png", alt="screenshot") }}
|
||||
|
||||
- Quantity - This is the number of contracts of the security you
|
||||
would like to be included in the calculation of the synthetic as
|
||||
@@ -139,7 +125,7 @@ insert_anchor_links = "right"
|
||||
displayed and click on such will display further details on how this
|
||||
parameter is used:
|
||||
|
||||

|
||||
{{ image(name="image72.png", alt="screenshot") }}
|
||||
|
||||
- Quote
|
||||
|
||||
@@ -148,20 +134,20 @@ insert_anchor_links = "right"
|
||||
by defining a region on either side of the working quote order,
|
||||
inside which quote updates will not be sent:
|
||||
|
||||

|
||||
{{ image(name="image6.png", alt="screenshot") }}
|
||||
|
||||
- Pre-Hedge
|
||||
|
||||
- Pay Less - If enabled by checking the checkbox, the spreader will
|
||||
attempt to pay less when the quantity at the level of the calculated
|
||||
hedge price is more than the threshold defined. The hedge order is
|
||||
hedge price is less than the threshold defined. The hedge order is
|
||||
paid less by the “Payless Ticks” as defined per leg.
|
||||
- Pay Up - If enabled by checking the checkbox, the spreader will pay
|
||||
up when the quantity at the level of the calculated hedge price is
|
||||
more than the threshold defined. The hedge order will pay up by the
|
||||
“Payup Ticks” as defined per leg.
|
||||
|
||||

|
||||
{{ image(name="image54.png", alt="screenshot") }}
|
||||
|
||||
- Post-Hedge
|
||||
|
||||
@@ -172,7 +158,7 @@ insert_anchor_links = "right"
|
||||
opposite inside market, it is re-priced to cross the opposite inside
|
||||
market as defined by “cross ticks”
|
||||
|
||||

|
||||
{{ image(name="image70.png", alt="screenshot") }}
|
||||
|
||||
- Time Based Cross - Basically the same as Ticks Away Cross,
|
||||
however, this is based on time (in ms) on when to automatically cross
|
||||
@@ -181,7 +167,7 @@ insert_anchor_links = "right"
|
||||
away from the opposite inside market, it is re-priced to cross the
|
||||
opposite inside market as defined by “cross ticks”
|
||||
|
||||

|
||||
{{ image(name="image40.png", alt="screenshot") }}
|
||||
|
||||
- Size Based Cross - similar to ticks and time based cross, but based
|
||||
on size instead. If you define a threshold of the opposite inside
|
||||
@@ -189,5 +175,3 @@ insert_anchor_links = "right"
|
||||
the market. If a legged hedge order’s price gets X amount of
|
||||
“ticks” away from the opposite inside market, it is re-priced to
|
||||
cross the opposite inside market as defined by “cross ticks”
|
||||
|
||||

|
||||
@@ -4,6 +4,10 @@ weight = 1
|
||||
sort_by = "weight"
|
||||
insert_anchor_links = "right"
|
||||
aliases = ["./bts_spark/Algos/"]
|
||||
|
||||
|
||||
[extra]
|
||||
page_description = "Definitions of the Algos built into BTS Spark and their parameters"
|
||||
+++
|
||||
|
||||
## Lean
|
||||
|
||||
@@ -3,6 +3,9 @@ title = "Trading"
|
||||
weight = 5
|
||||
sort_by = "weight"
|
||||
insert_anchor_links = "right"
|
||||
|
||||
[extra]
|
||||
page_description = "BTS Spark's Trading module, including The Order Book, Fills, P&L, Ladder, Order Ticket, and Algo Studio"
|
||||
+++
|
||||
|
||||
|
||||
@@ -10,13 +13,11 @@ insert_anchor_links = "right"
|
||||
Order Book, Fills, P&L, Ladder, and Order Ticket
|
||||
- It appears like below:
|
||||
|
||||

|
||||
{{ image( name = "image44.png", alt = "screenshot") }}
|
||||
|
||||
## Order Book
|
||||
|
||||
<div>
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/ygMFkjBBGeU" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</div>
|
||||
{{ youtube(id="ygMFkjBBGeU") }}
|
||||
|
||||
- This provides a list of all orders a user has placed, by default it
|
||||
will display only working orders
|
||||
@@ -26,7 +27,7 @@ insert_anchor_links = "right"
|
||||
other windows within BTS
|
||||
- Appears like the following:
|
||||
|
||||

|
||||
{{ lightbox( name = "image5.png", alt = "screenshot") }}
|
||||
|
||||
- You can sort all columns by single left clicking on the column
|
||||
header which will sort in either descending or ascending order, an
|
||||
@@ -34,14 +35,14 @@ insert_anchor_links = "right"
|
||||
Below is a display of the security column sorting in descending
|
||||
fashion.
|
||||
|
||||

|
||||
{{ image( name = "image60.png", alt = "screenshot") }}
|
||||
|
||||
- Filtering can occur, by hovering over any column header which will
|
||||
display a “Filter” box. Clicking on this will then display the
|
||||
available components which can be filtered, below is an example of
|
||||
clicking on the securities column
|
||||
|
||||

|
||||
{{ image( name = "image52.png", alt = "screenshot") }}
|
||||
|
||||
- If the column is displaying time base information, a special style
|
||||
box will appear when clicking on the filtering box providing more
|
||||
@@ -53,49 +54,45 @@ insert_anchor_links = "right"
|
||||
- Since Open
|
||||
- A specific user-defined period of time
|
||||
|
||||

|
||||
{{ image( name = "image25.png", alt = "screenshot") }}
|
||||
|
||||
- The left-hand box within an order book provides users with further
|
||||
functionality to quickly perform various tasks with live orders as
|
||||
well as launch other modules. It appears like the below:
|
||||
well as launch other modules.
|
||||
{{ image(name="spark_menu_order_book.png", alt="the spark menu in the order book", pull="right") }}
|
||||
|
||||

|
||||
|
||||
- Fills -
|
||||
- {{ icon(name="image48.png", alt="Fills icon") }} Fills -
|
||||
clicking on this will launch a fills window
|
||||
-  Modify -
|
||||
- {{ icon(name="image57.png", alt = "modify icon") }} Modify -
|
||||
clicking on this will launch an order ticket for a live order
|
||||
highlighted in the Order Book.
|
||||
- Cancel
|
||||
- {{ icon(name="image73.png", alt = "cancel selected icon")}} Cancel
|
||||
selected - clicking on this will cancel the selected orders you have
|
||||
highlighted in the order book. You can choose more than one by
|
||||
holding hold the Ctrl key when clicking on each row of orders
|
||||
- Cancel
|
||||
- {{ icon(name="image74.png", alt = "cancel buys icon")}} Cancel
|
||||
buys - clicking on this will cancel all the buy orders you have in
|
||||
the order book
|
||||
- Cancel
|
||||
- {{ icon(name="image33.png", alt = "cancel all icon")}} Cancel
|
||||
sells - clicking on this will cancel all the sell orders you have in
|
||||
the order book
|
||||
- Cancel
|
||||
- {{ icon(name="image2.png", alt = "cancel all icon")}} Cancel
|
||||
all - clicking on this will cancel all working orders you have the
|
||||
order book
|
||||
-  Recreate - clicking this will recreate already cancelled orders, sending them back to market with the same price and quantity as they were previously at before being cancelled.
|
||||
-  Collapse all - This will collapse all trees inside the order book to show only the top level of the order.
|
||||
-  Expand all - This will expand to show everything inside the order book.
|
||||
-  Settings - This launches the settings for the orderbook.
|
||||
- Furthermore, there is a “floating” or “mini orderbook” feature as well
|
||||
integrated within the ladder itself.
|
||||
- To access this, you need to center click with your mouse wheel over
|
||||
working orders on the ladder.
|
||||
- From here, you can change the price and quantity of any working order
|
||||
within the mini orderbook straight from the window
|
||||
- This looks like below:
|
||||

|
||||
- {{ icon(name = "recreate_icon.png", alt = "screenshot") }} Recreate - clicking this will recreate already cancelled orders, sending them back to market with the same price and quantity as they were previously at before being cancelled.
|
||||
- {{ image( name = "collapse_all_icon.png", alt = "screenshot") }} Collapse all - This will collapse all trees inside the order book to show only the top level of the order.
|
||||
- {{ icon( name = "expand_all_icon.png", alt = "screenshot") }} Expand all - This will expand to show everything inside the order book.
|
||||
- {{ icon( name = "settings_icon.png", alt = "screenshot") }} Settings - This launches the settings for the orderbook.
|
||||
- The mini orderbook is integrated into the ladder
|
||||
|
||||
- Middle click (click the mouse wheel) on a working order to display the mini orderbook
|
||||
- From here, you can change the price and quantity of any working order
|
||||
{{ image( name = "mini_orderbook.png", alt = "screenshot") }}
|
||||
|
||||
## Fills
|
||||
|
||||
- This provides a list of all fills a user has had for a given time
|
||||
period, by default it will open up with “since open” timeframe
|
||||
period, by default it will open up with “since open” time frame
|
||||
selected showing you fills on the day thus far
|
||||
- You can create multiple fill windows, filtered however you
|
||||
like
|
||||
@@ -106,9 +103,7 @@ insert_anchor_links = "right"
|
||||
|
||||
## P&L
|
||||
|
||||
<div>
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/xj6cEQ6By34" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</div>
|
||||
{{ youtube(id="xj6cEQ6By34") }}
|
||||
|
||||
- This provides a running ledger of a users account(s) profit and
|
||||
loss, broken down per symbol
|
||||
@@ -125,20 +120,18 @@ insert_anchor_links = "right"
|
||||
- This is accomplished on the top bar, which when clicked on, displays
|
||||
the choices for calculation, this appears like below:
|
||||
|
||||

|
||||
{{ image( name = "pnl_calculation.png", alt = "screenshot") }}
|
||||
|
||||
|
||||
- Below is an example P&L window showing a user’s multiple accounts and
|
||||
various positions in each:
|
||||
|
||||

|
||||
{{ image( name = "pnl_window.png", alt = "screenshot") }}
|
||||
|
||||
|
||||
## Ladder
|
||||
|
||||
<div>
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/Q0qsyc1nvYo" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</div>
|
||||
{{ youtube(id="Q0qsyc1nvYo") }}
|
||||
|
||||
- The ladder was designed to be the most logically produced ladder on
|
||||
the market, engineered and designed by professional traders for
|
||||
@@ -149,12 +142,12 @@ insert_anchor_links = "right"
|
||||
market with a single click
|
||||
- Below is an example ladder:
|
||||
|
||||

|
||||
{{ image( name = "ladder.png", alt = "screenshot") }}
|
||||
|
||||
- The ladder consists of 2 major parts, the Ladder itself and the
|
||||
information and control section on the left-hand side
|
||||
|
||||
- The information section on the left contains the following: 
|
||||
- The information section on the left contains the following: {{ image( name = "image1.png", alt = "screenshot") }}
|
||||
- Day - showing the current price of the security on the day
|
||||
- High - showing the high price of the security on the day
|
||||
- Low - showing the low price of the security on the day
|
||||
@@ -167,7 +160,7 @@ insert_anchor_links = "right"
|
||||
- The control section right underneath the information section on the
|
||||
left-hand side offers the following:
|
||||
|
||||

|
||||
{{ image( name = "image62.png", alt = "screenshot") }}
|
||||
|
||||
- The account in which the orders will flow into when trading this
|
||||
security
|
||||
@@ -202,7 +195,7 @@ insert_anchor_links = "right"
|
||||
the stop price, by clicking on the “<” to bring up the stop price
|
||||
option:
|
||||
|
||||

|
||||
{{ image( name = "image61.png", alt = "screenshot") }}
|
||||
|
||||
- Iceberg
|
||||
|
||||
@@ -213,7 +206,7 @@ insert_anchor_links = "right"
|
||||
quantity. You will need to define what type of order that will
|
||||
be used for the child order to be sent.
|
||||
|
||||

|
||||
{{ image( name = "image47.png", alt = "screenshot") }}
|
||||
|
||||
- Time Box
|
||||
|
||||
@@ -233,9 +226,9 @@ insert_anchor_links = "right"
|
||||
- Below are images of the type of time frame that can be used within
|
||||
the time box
|
||||
|
||||

|
||||
{{ image( name = "image42.png", alt = "screenshot") }}
|
||||
|
||||

|
||||
{{ image( name = "image50.png", alt = "screenshot") }}
|
||||
|
||||
- Lean
|
||||
- This is a specialized algo order which allows the user to
|
||||
@@ -244,14 +237,14 @@ insert_anchor_links = "right"
|
||||
- “Cross” means to take an order working on the bid and 'cross' by
|
||||
buying into the asks. This is often referred to as “paying up” as well
|
||||
|
||||

|
||||
{{ image( name = "lean_algo_control.png", alt = "screenshot") }}
|
||||
|
||||
- Join
|
||||
- This is a specialized algo order which allows the user to enter an
|
||||
order which will watch the opposite-inside market and join when the
|
||||
market flips and has at least threshold size as defined.
|
||||
|
||||

|
||||
{{ image( name = "join_algo_control.png", alt = "screenshot") }}
|
||||
|
||||
- Top
|
||||
- This is a specialized algo order which allows the user to
|
||||
@@ -259,14 +252,14 @@ insert_anchor_links = "right"
|
||||
- If the order is on the market (current bid price) and the quantity
|
||||
on that bid price is below the top threshold defined the order will
|
||||
cancel and do nothing else
|
||||

|
||||
{{ image( name = "top_algo_control.png", alt = "screenshot") }}
|
||||
|
||||
- Offset
|
||||
|
||||
- The goal of the offset order is to send your order X amount of ticks
|
||||
from where you actually place it on the ladder. This is sometimes
|
||||
known as a "fat finger" safety.
|
||||

|
||||
{{ image( name = "offset_algo_control.png", alt = "screenshot") }}
|
||||
|
||||
- OCO
|
||||
|
||||
@@ -276,26 +269,26 @@ insert_anchor_links = "right"
|
||||
of the fill. Composing this order with Cover simulates scalping
|
||||
functionality.
|
||||
|
||||

|
||||
{{ image( name = "oco_algo_control.png", alt = "screenshot") }}
|
||||
|
||||
- Cover
|
||||
|
||||
- A Cover order’s purpose is to fire a hedge order (of any algo-type) in response to fills from it’s child order on the opposite side of the market N ticks away.
|
||||
|
||||

|
||||
{{ image( name = "cover_algo_control.png", alt = "screenshot") }}
|
||||
|
||||
- Trigger
|
||||
|
||||
- The Trigger order is exactly as it sounds, where it will trigger an order based on conditions defined.
|
||||
- This order also has exit strategy built in where a user can define when the trigger order can auto-cancel based on time as well as price conditional.
|
||||
|
||||

|
||||
{{ image( name = "trigger_algo_control.png", alt = "screenshot") }}
|
||||
|
||||
- The middle of the control section is where you can click on
|
||||
predefined values to quickly populate the volume at which you wish
|
||||
to enter the market.
|
||||
|
||||

|
||||
{{ image( name = "image17.png", alt = "screenshot") }}
|
||||
|
||||
- You can manually type in a quantity here as well
|
||||
- Furthermore, if you have a value in the volume bar, you can
|
||||
@@ -305,7 +298,7 @@ insert_anchor_links = "right"
|
||||
- By having the auto clear box checked, it will bring the value back
|
||||
to zero after placing an order at the size chosen.
|
||||
|
||||

|
||||
{{ image( name = "image59.png", alt = "screenshot") }}
|
||||
|
||||
- The bottom section of the control area of a ladder has 4 aspects
|
||||
to it
|
||||
@@ -317,7 +310,7 @@ insert_anchor_links = "right"
|
||||
- Cancel All, which will cancel all orders on the ladder
|
||||
- Settings, which will launch the ladder settings window which
|
||||
appears like below
|
||||

|
||||
{{ image( name = "ladder_settings.PNG", alt = "screenshot") }}
|
||||
- Fonts and Colors - This is where you can customize the overall main
|
||||
aspects of the ladder.
|
||||
- Market Break Lines - These are where can control the viewing of what
|
||||
@@ -339,7 +332,7 @@ insert_anchor_links = "right"
|
||||
- The other, main part of the ladder, is the ladder itself as
|
||||
displayed below
|
||||
|
||||

|
||||
{{ image( name = "ladder_main_part.png", alt = "screenshot") }}
|
||||
|
||||
- There are 5 main columns
|
||||
|
||||
@@ -356,7 +349,7 @@ insert_anchor_links = "right"
|
||||
- To enter an order directly by clicking in the ladder, left click on either the bid or ask volume with a volume greater than 0 on the predefined value box on the left-hand section
|
||||
- A badge will be displayed within the orders column of the value you have chosen and the quantity filled as displayed below
|
||||
|
||||

|
||||
{{ image( name = "ladder_badges.png", alt = "screenshot") }}
|
||||
|
||||
- To change the price level you wish to work the order, you can right-click and hold on the badge to move it up or down the ladder for the
|
||||
desired price
|
||||
@@ -367,9 +360,7 @@ insert_anchor_links = "right"
|
||||
|
||||
## Order Ticket
|
||||
|
||||
<div>
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/bdC5pZ6T35I" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</div>
|
||||
{{ youtube(id="bdC5pZ6T35I") }}
|
||||
|
||||
- The order ticket was designed to provide another means other than
|
||||
the ladder to enter orders into the market
|
||||
@@ -378,7 +369,7 @@ insert_anchor_links = "right"
|
||||
which security to populate
|
||||
- The order ticket appears like below
|
||||
|
||||

|
||||
{{ image( name = "image27.png", alt = "screenshot") }}
|
||||
|
||||
- On the top left, you have the price for the order as well as the
|
||||
volume
|
||||
@@ -416,7 +407,7 @@ insert_anchor_links = "right"
|
||||
|
||||
- This is all in place in a very user friendly GUI as shown below:
|
||||
|
||||

|
||||
{{ image( name = "algo_studio.png", alt = "screenshot") }}
|
||||
|
||||
|
||||
- There are 3 main areas of the Algo Studio:
|
||||
|
||||
@@ -3,6 +3,9 @@ title = "BTS Spark"
|
||||
weight = 1
|
||||
sort_by = "weight"
|
||||
insert_anchor_links = "right"
|
||||
|
||||
[extra]
|
||||
page_description = "Documentation for Blue Trading Systems' BTS Spark"
|
||||
+++
|
||||
|
||||
Click on the headings on the left to expand their contents. If you need specific information quickly use the Search button in the top right of this page.
|
||||
|
||||
@@ -3,7 +3,98 @@ title = "Release notes"
|
||||
weight = 3
|
||||
sort_by = "weight"
|
||||
insert_anchor_links = "right"
|
||||
|
||||
[extra]
|
||||
page_description = "Release notes for BTS Spark"
|
||||
+++
|
||||
## 2.13.0
|
||||
### User Visible Changes
|
||||
- Added the name of the spreader to the parent algo badge (for spreader child orders), in the fills, orderbook and floating orderbook windows
|
||||
- Added support for sounds for new orders
|
||||
- Added a new quoting throttle parameter for the spreader, that throttles quotes that are moving toward the inside market but are still a configurable number of ticks away
|
||||
- Enabled the ladder to remember the left panel scroll position across front end restarts
|
||||
### Bug Fixes
|
||||
- Fixed the local fills window so that it does not show the admin fills
|
||||
- Removed the deleted accounts from the ladder accounts dropdown
|
||||
- Fixed the orderbook price for iceberg of spreaders
|
||||
|
||||
## 2.12.0
|
||||
### User Visible Changes
|
||||
- Added support for ICE market data and order execution
|
||||
### Internal Changes
|
||||
- Lots of permission / admin changes to facilitate ICE
|
||||
|
||||
## 2.11.0
|
||||
### User Visible Changes
|
||||
- Fixed fills form time filter to also apply to SOD fills
|
||||
- Addressed an issue that could prevent the web Admin UI from displaying over slow HTTP connections
|
||||
- Removed the option to enter manual spread fills
|
||||
- Fixed an issue that could cause erroneous fill account attribution in the event of a crash
|
||||
### Internal Changes
|
||||
- Added support for tag 1031. Currently defaults to Y, can it be override through config.
|
||||
- To facilitate support, allowed the bts user to view and edit algos from all other users
|
||||
- Improved system tests
|
||||
- Improved log messages in UI to include dispatcher thread name
|
||||
- Added support for Windows core dumps in the UI
|
||||
|
||||
## 2.10.0
|
||||
### User Visible Changes
|
||||
- Fills now include information about the algo that originated the fill
|
||||
- A new, more powerful PnL form is now available
|
||||
### API Changes
|
||||
- Added security state information (pre open, halted, normal, closed, etc)
|
||||
### Bug Fixes
|
||||
- Brought back the "select all" check box in the mini order book
|
||||
- Fixed an issue in the market data subsystem that on rare occasions could result in a startup crash
|
||||
### Internal Changes
|
||||
- Fixed an issue that was stopping us from interpreting SOD times as local rather than GMT
|
||||
## 2.9.3
|
||||
### Internal Changes
|
||||
- Fixed system test scripts
|
||||
## 2.9.2
|
||||
### Bug Fixes
|
||||
- Fixed an issue with the exchange simulator that could lead to crossed markets
|
||||
## 2.9.1
|
||||
### Bug Fixes
|
||||
- Fixed an issue with trade sound alerts, where in some cases the use of a "In Between" condition could lead to a UI failure.
|
||||
- Fixed an issue with the display of the new raw position column in the market view window.
|
||||
- Fixed the popup label that describes the raw position information in the ladder
|
||||
### Internal Changes
|
||||
- Avoided shipping production configuration defaults that lead to trying to download a position file for the development sftp server.
|
||||
### Api
|
||||
- C# API sample now uses synchronous calls.
|
||||
|
||||
## 2.9.0
|
||||
### User Visible Changes
|
||||
- Improved Workspace management User Interface
|
||||
- Added the ability to change grid background colors
|
||||
- The Spark UI Window group now has a title in the Windows task bar
|
||||
- Added sound alerts for trade events, see Launcher -> Settings -> Alerts
|
||||
- Allowed composite algos that are attached to existing orders to identify fills that were already present prior to attachment
|
||||
- Added import facilities for GMI position files
|
||||
- Added the ability for risk managers to enter manual fills
|
||||
- Added "raw" P&L columns, that is columns that *do not* include spread legs in their accounting
|
||||
### Bug Fixes
|
||||
- Fixed the settings action menu (Load/Save/Reset to Factory)
|
||||
- Fixed the method used to determine if a security is expired to take into account the start of day time
|
||||
### API Changes
|
||||
- Fixed an issue in the Client SDK that could lead to occasional failures to connect to the spark server as well as excessive memory usage.
|
||||
- Added the ability for algo orders to distinguish fills existing prior to launch
|
||||
### Internal Changes
|
||||
- Changed how we packaged certain third-party components
|
||||
- Added logging of entitlement status
|
||||
- Tagged outgoing orders with sequence number of marketdata or FIX event that triggered them
|
||||
## 2.8.3
|
||||
### Bug Fixes
|
||||
- Fixed a bug that could cause an OrderBook's Security column filter to be blank
|
||||
- Fixed a bug that could cause a UI failure when clearing a filter selection on a filtering widget
|
||||
## 2.8.2
|
||||
### Bug Fixes
|
||||
- Added proper display factors for SOM spreads
|
||||
- Fixed a bug that could cause a UI failure when trying to change settings in a synthetic ladder
|
||||
## 2.8.1
|
||||
### Bug fixes
|
||||
- Fixed an error in the UI grids filtering widget
|
||||
## 2.8.0
|
||||
### User Visible Changes
|
||||
- Added ProRata and Scratch algos
|
||||
@@ -16,14 +107,15 @@ insert_anchor_links = "right"
|
||||
selected by default
|
||||
- Increased width of login panel to better show login error messages
|
||||
- Added optional 'Maker/Taker' pricing to Spreader algo
|
||||
- Algo buttons in ladder can now be made to deactivate after launching an algo or remain 'sticky'
|
||||
### Internal changes
|
||||
- Made it easier to generate simple UI's for new order types
|
||||
### API Changes
|
||||
- Dynamic orders can now use QuantityMeasure parameter types
|
||||
|
||||
|
||||
## 2.7.2
|
||||
### User Visible Changes
|
||||
- Changed the login dialog to avoid leaking workspace names from other users.
|
||||
- Changed the login dialog to avoid leaking workspace names from other users.
|
||||
- Added new Splitter algo. From the manual: The splitter is useful
|
||||
for pro-rata markets where you want to vary your exposure
|
||||
independent of the order quantity that you want to fill. The
|
||||
@@ -31,13 +123,13 @@ insert_anchor_links = "right"
|
||||
the order quantity but it will put exposed_qty total size on the
|
||||
market. Splitter favors order size over queue position.
|
||||
### Internal Changes
|
||||
- Made spark more resilient to lack of connectivity to the CME web site for downloading of templates.
|
||||
|
||||
- Made spark more resilient to lack of connectivity to the CME web site for downloading of templates.
|
||||
|
||||
## 2.7.1
|
||||
### User Visible Changes
|
||||
- Fixed some issues with the Cover algo, where in some circumstances
|
||||
it would erroneously cancel launched hedges on completion.
|
||||
|
||||
|
||||
## 2.7.0
|
||||
### User Visible Changes
|
||||
- Allowed algos to process "in-flight" fills while shutting down
|
||||
@@ -56,36 +148,36 @@ insert_anchor_links = "right"
|
||||
### User Visible Changes
|
||||
- Fixed an issue in the ladder where in some cases the mini order book could not be brought up from a badge
|
||||
- Fixed a rare race condition that could lead to erroneous limit enforcement
|
||||
- Fixed an issue with the margin limits where an error could occur if an account name with more than 12 chars was used
|
||||
- Fixed an issue with the margin limits where an error could occur if an account name with more than 12 chars was used
|
||||
|
||||
## 2.6.1
|
||||
### User Visible Changes
|
||||
- Fixed an issue in the ladder where an error could occur when trying to change ladder settings for the first time
|
||||
|
||||
|
||||
## 2.6.0
|
||||
### User Visible Changes
|
||||
- In the ladder made last trade more distinctive when overlayed on the volumn column
|
||||
- In the ladder, corrected display of volume tool tip
|
||||
- In the ladder made last trade more distinctive when overlaid on the volume column
|
||||
- In the ladder, corrected display of volume tool tip
|
||||
- In the ladder, changed the consolidation of last trade to consider only the price ignoring aggressor changes
|
||||
- Added an option for the Top Algo to delete itself if within N ticks from top of book
|
||||
- Address a rare issue that could lead to an error report on UI exit
|
||||
- Added margin risk limits
|
||||
- Added the "Offset" algo. Offset prices a child algo at a parameterizable distance from the top of the book
|
||||
- Avoided switching the current account and order type on open ladders when limits are changed
|
||||
- Avoided switching the current account and order type on open ladders when limits are changed
|
||||
### Internal Changes
|
||||
- Ensure that admin logins are always allowed to login, regardless of keycode status.
|
||||
|
||||
|
||||
## 2.5.0
|
||||
### User Visible Changes
|
||||
- Added loss limit risk check
|
||||
- Made algos, synthetics and user names private so that multiple users can share a single system privately.
|
||||
- Allowed the mini order book defaults for column widths to be changed from the mini order book
|
||||
- Allowed the mini order book to shrink to the minimum size that will be needed to display the selected columns
|
||||
- Improved accuracy of the directional arrow when displaying last trades in the volumn column
|
||||
- Improved accuracy of the directional arrow when displaying last trades in the volume column
|
||||
## 2.4.0
|
||||
### User Visible Settings
|
||||
- In the ladder, changed the last trade column to accumulate successive trades at the same price
|
||||
- Fixed a bug in the order book where the right side ladder would display the top leve order's security rather then current row's
|
||||
- Fixed a bug in the order book where the right side ladder would display the top level order's security rather then current row's
|
||||
- Added OK, Cancel buttons to the security picker for ladder profiles or sounds
|
||||
- Added ladder settings for the mini order book
|
||||
- Added a safety check to guard against unintentional market crosses
|
||||
@@ -101,16 +193,16 @@ insert_anchor_links = "right"
|
||||
### User Visible Changes
|
||||
- Introduced multiple settings profiles for the ladder
|
||||
- This allows multiple standard configuration for the ladder, optionally with security specific variations
|
||||
- Made Cover order more independent from its hedging chidren:
|
||||
- Made Cover order more independent from its hedging children:
|
||||
- Cover continues to operate even if an hedging child is canceled
|
||||
- When a cover is canceled it will detach from any running hedging children, instead of canceling them
|
||||
- Changed Lean, Join and Cover algos to hide themselves in the ladder once they have completed their work
|
||||
- Changed Lean, Join and Cover algos to hide themselves in the ladder once they have completed their work
|
||||
- Changed manual fills to appear in day PnL rather than in the SOD records
|
||||
- Add buy/sell coloring to fill rows in fills window
|
||||
- Streamlined the mini order book:
|
||||
- Display of the mini order book popup is quicker
|
||||
- Only exchange orders are displayed
|
||||
- Update buttons are only displayed for orders that are under control of an algo with the update applying to the entire algo, not just the exchange order
|
||||
- Update buttons are only displayed for orders that are under control of an algo with the update applying to the entire algo, not just the exchange order
|
||||
- We can now select multiple rows to attach, detach, update or cancel multiple orders in a batch
|
||||
- A checkbox column has been added to make clearer which rows are selected
|
||||
### API Changes
|
||||
@@ -120,7 +212,7 @@ insert_anchor_links = "right"
|
||||
- Added system requirements to Spark documentation
|
||||
- Implemented keycodes
|
||||
- Temporarily rejected stop and stop limit orders, pending bug fixes
|
||||
|
||||
|
||||
## 2.2.0
|
||||
### User Visible Changes
|
||||
- Made our orders easier to spot in MBO display
|
||||
@@ -131,41 +223,41 @@ insert_anchor_links = "right"
|
||||
- Improved handling of orders with undiscovered securities
|
||||
- Added feedback to the ladder when the user attempts to middle click on bid/ask columns using an order that does not have parameters
|
||||
- Fixed display of algo studio algo types in order book
|
||||
- Hid net change setting in synthetic ladders
|
||||
- Hid net change setting in synthetic ladders
|
||||
- Fixed a number of problems with filtering on the Fills form
|
||||
- On the Lean algo, OnToward and Away are now calculated with respect to the opposite inside market at time of the order launch
|
||||
- Iceberg Spreaders with queue holders are not erroneously cancelled after the first fill
|
||||
- Added security symbol column to fills window
|
||||
- Re-organized ladder settings dialog to make it clearer and easier to use
|
||||
|
||||
|
||||
## 2.1.4
|
||||
### User Visible Changes
|
||||
- Fixed handling of cancel button in security picker
|
||||
|
||||
|
||||
## 2.1.3
|
||||
### User Visible Changes
|
||||
- Fixed a simulator bug in the handling of 0 sized orders
|
||||
- Fixed a simulator bug in the handling of 0 sized orders
|
||||
|
||||
## 2.2.1
|
||||
### User Visible Changes
|
||||
- Fixed order book form exception when display a spreader order for whichs the legs were not present yet
|
||||
|
||||
- Fixed order book form exception when display a spreader order for which the legs were not present yet
|
||||
|
||||
## 2.1.1
|
||||
### User Visible Changes
|
||||
- Added PIQ to GLBX Iceberg orders
|
||||
- Corrected handling of stop limit orders
|
||||
|
||||
|
||||
## 2.1.0
|
||||
### User Visible Changes
|
||||
- Added support for the GLBX Iceberg order type
|
||||
- Allowed quick algo param edits by middle-clicking on either the bid/ask columns or a "favorite" button
|
||||
- Added support for manual fills, either entered manually or imported from file. Manual fills are used only for P&L purposes, they have no impact on limits
|
||||
- Allowed the LTQ and VAP values to be overlayed on the same ladder column
|
||||
- Allowed the LTQ and VAP values to be overlaid on the same ladder column
|
||||
- Added day position information to the ladder
|
||||
- Added PIQ to the mini order book
|
||||
- Fixed a rare bug that could lead to server failure when requesting market data
|
||||
- Fixed a bug that could cause incorrect price displays for certain types of synthetic securities
|
||||
|
||||
|
||||
## 2.0.5
|
||||
### User Visible Changes
|
||||
- Fixed a bug in the handling of rejected QHO orders
|
||||
@@ -175,19 +267,19 @@ insert_anchor_links = "right"
|
||||
## 2.0.4
|
||||
### User Visible Changes
|
||||
- Fixed performance regression in order manager
|
||||
|
||||
|
||||
### Internal changes
|
||||
- Improved market data diagnostics for bad configurations
|
||||
- Changed market data default buffer size
|
||||
|
||||
|
||||
## 2.0.3
|
||||
### Internal changes
|
||||
- Improved backwards compatibility in UI settings
|
||||
|
||||
|
||||
|
||||
## 2.0.2
|
||||
### User Visible Changes
|
||||
- Middle click the ladder price column to show the orders for that price level
|
||||
- Middle click the ladder price column to show the orders for that price level
|
||||
- Middle click the bid or ask column in the ladder no longer sends an order
|
||||
|
||||
### Internal changes
|
||||
@@ -215,8 +307,8 @@ insert_anchor_links = "right"
|
||||
- Improved settings manager tool output
|
||||
- Added diagnostics in the event MD memory corruption is detected
|
||||
- Added systems tests for join,lean, iceberg and spreader orders
|
||||
- Made exchange order recovery more resilient in the presence of database loss
|
||||
|
||||
- Made exchange order recovery more resilient in the presence of database loss
|
||||
|
||||
## 1.6.2
|
||||
### User Visible Changes
|
||||
### Exchange simulator
|
||||
@@ -241,7 +333,7 @@ insert_anchor_links = "right"
|
||||
- Integrated stunnel into UI to make VPN setup unnecessary in unsecured environments.
|
||||
## 1.5.7
|
||||
### User Visible Changes
|
||||
- New videos have been added to the manual describing the [Algo Studio](./bts_spark/Trading/_index.md#algo-studio) and [Spreader](./bts_spark/Spreader/_index.md)
|
||||
- New videos have been added to the manual describing the [Algo Studio](@/bts_spark/Trading/_index.md#algo-studio) and [Spreader](@/bts_spark/Spreader/_index.md)
|
||||
- Fixed a bug that occasionally would cause windows to be position outside the visible screen on startup
|
||||
- Fixed a bug in the order book form that would occasionally cause the Recreate Order option to be unavailable
|
||||
- Added a confirmation step to Cancel All, Cancel Buys and Cancel Sells commands
|
||||
@@ -255,21 +347,21 @@ insert_anchor_links = "right"
|
||||
- These columns can be restored by toggling their visibility within the PnL's Settings form
|
||||
- A new Traded Today column has been added to the PnL
|
||||
- Filtering on this column will allow a user to restrict the report to only show today's position
|
||||
### Internal changes
|
||||
- Improved organization of the shell notification architecture
|
||||
### Internal changes
|
||||
- Improved organization of the shell notification architecture
|
||||
- Added logging to help troubleshoot shell exit hang
|
||||
|
||||
## 1.5.6
|
||||
### User Visible Changes
|
||||
- Fixed a bug that could cause limits to be erroneously enforced
|
||||
- Fixed a bug that could cause limits to be erroneously enforced
|
||||
- Improved algo documentation
|
||||
- Changed how the spreader uses net change
|
||||
- Simplified trigger algo user interface
|
||||
### Internal changes
|
||||
### Internal changes
|
||||
- Defaulted to not recording sim market data
|
||||
- Improved documentation build
|
||||
- Improved documentation build
|
||||
- Added additional performance tracing
|
||||
|
||||
|
||||
## 1.5.5
|
||||
- Fixed Market View 'stale working orders' bug
|
||||
|
||||
@@ -277,11 +369,11 @@ insert_anchor_links = "right"
|
||||
- Avoided logging when warming up cache
|
||||
|
||||
## 1.5.3
|
||||
- Fixed sounds startup issue
|
||||
- Fixed sounds startup issue
|
||||
|
||||
## 1.5.2
|
||||
- Added better logging to AlgoDefinitionService
|
||||
|
||||
|
||||
## 1.5.1
|
||||
- Fixed missing securities in the Fills and P&L windows.
|
||||
|
||||
@@ -302,7 +394,7 @@ insert_anchor_links = "right"
|
||||
#### Bug Fixes
|
||||
- Fixed the "Since Open" time filter to use the exchange open time rather than 8:30 AM
|
||||
- Fixed a bug in the order book where sometimes parent orders would not update their last message column.
|
||||
|
||||
|
||||
#### Algos
|
||||
- Added OCO Algo
|
||||
- An OCO order creates a relationship between a child order and a 'stop' or 'other' order such that when one of these is cancelled, both cancel, or when one is filled, the other order's size is debited in the amount of the fill. Composing this order with Cover simulates scalping functionality
|
||||
@@ -310,14 +402,14 @@ insert_anchor_links = "right"
|
||||
- Improved SDK documentation and usability
|
||||
- Dynamic orders are now properly identified in the order book
|
||||
#### Documentation
|
||||
- Information on the Spark API has been added to the Spark manual
|
||||
- Information on the Spark API has been added to the Spark manual
|
||||
- The documentation has been updated and reorganized to make information easier to find
|
||||
### Internal Changes
|
||||
- Improved robustness of limit system test
|
||||
- Fixed a bug in handling of built-in bts to user that could lead to failure to login as bts in old systems
|
||||
- Improved market data subsystem to support security definition updates
|
||||
- Fixed a startup race in market data that could lead to data corruption on startup
|
||||
- Increased default order price precision to 8 digis as required by some CME products
|
||||
- Increased default order price precision to 8 digits as required by some CME products
|
||||
|
||||
## 1.4.11
|
||||
### New Features
|
||||
@@ -385,7 +477,7 @@ insert_anchor_links = "right"
|
||||
|
||||
### Ladder Usability Improvements
|
||||
- Controls found in Left Pane of the ladder can now be hidden via the checkboxes found under Ladder Form -> Settings button -> Left Pane tab
|
||||
- The Left Pane is now scrollable with the mouse wheel when there isn't enough vertical space to accomodate the entire form
|
||||
- The Left Pane is now scrollable with the mouse wheel when there isn't enough vertical space to accommodate the entire form
|
||||
- The Left Pane can now grown and shrunk horizontally via the splitter between the left pane and the main ladder area
|
||||
### Performance Improvements
|
||||
- Requoting and hedging latency has been reduced by up to 30%
|
||||
|
||||
@@ -3,6 +3,9 @@ title = "System Requirements"
|
||||
weight = 4
|
||||
sort_by = "weight"
|
||||
insert_anchor_links = "right"
|
||||
|
||||
[extra]
|
||||
page_description = "Recommended and minimum systems requirements for BTS Spark"
|
||||
+++
|
||||
|
||||
|
||||
|
||||
@@ -1,15 +1,20 @@
|
||||
#/bin/bash
|
||||
#python -m mkdocs build -d site
|
||||
|
||||
./run_zola.sh build
|
||||
|
||||
ssh bts@bluetradesys.com "rm -r /home/bts/bts_website/zola/content/docs"
|
||||
scp -r ./content bts@bluetradesys.com:/home/bts/bts_website/zola/content/docs
|
||||
scp -r ./public bts@bluetradesys.com:/home/bts/doc/
|
||||
|
||||
ssh bts@bluetradesys.com << EOF
|
||||
cd doc
|
||||
cd /home/bts/doc/
|
||||
sudo rm -r /var/www/documentation/*
|
||||
sudo mv ./public/* /var/www/documentation/
|
||||
|
||||
cd /home/bts/bts_website/zola/
|
||||
./fix_links.sh
|
||||
./deploy.sh
|
||||
|
||||
EOF
|
||||
|
||||
rm -r public
|
||||
@@ -1,4 +1,4 @@
|
||||
.page {
|
||||
.page, .menu-open .page {
|
||||
position: absolute;
|
||||
width: calc(100% - #{$sidebar-width});
|
||||
height: 100%;
|
||||
@@ -7,15 +7,24 @@
|
||||
background: #f6f6f6;
|
||||
padding-bottom: 20px;
|
||||
transition: 0.5s;
|
||||
left: $sidebar-width;
|
||||
|
||||
h1:hover .zola-anchor, h2:hover .zola-anchor, h3:hover .zola-anchor, h4:hover .zola-anchor, h5:hover .zola-anchor, h6:hover .zola-anchor {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.zola-anchor {
|
||||
color: #4183c4;
|
||||
padding-left: 10px;
|
||||
padding-right: .5em;
|
||||
margin-left: -1.5em;
|
||||
text-decoration: none;
|
||||
font-weight: initial;
|
||||
float: left;
|
||||
visibility: hidden;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
text-decoration: none;
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,13 +164,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
@include min-screen(600px) {
|
||||
.page {
|
||||
left: $sidebar-width;
|
||||
}
|
||||
}
|
||||
// @include min-screen(600px) {
|
||||
// .page {
|
||||
// left: $sidebar-width;
|
||||
// }
|
||||
// }
|
||||
|
||||
.page-without-menu {
|
||||
.menu-closed .page {
|
||||
width: 100%;
|
||||
left: 0;
|
||||
|
||||
|
||||
+46
-19
@@ -123,27 +123,9 @@
|
||||
|
||||
.page__header {
|
||||
height: 50px;
|
||||
position: fixed;
|
||||
|
||||
.menu-icon {
|
||||
height: 50px;
|
||||
width: 50px;
|
||||
font-size: 24px;
|
||||
text-align: center;
|
||||
float: left;
|
||||
position: relative;
|
||||
transition: background .5s;
|
||||
cursor: pointer;
|
||||
|
||||
@include menu-icon();
|
||||
|
||||
&:hover {
|
||||
span {
|
||||
background-color: black;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.search-icon {
|
||||
height: 50px;
|
||||
width: 50px;
|
||||
display: inline-block;
|
||||
@@ -156,5 +138,50 @@
|
||||
&:hover {
|
||||
color: black
|
||||
}
|
||||
|
||||
@include menu-icon();
|
||||
|
||||
&:hover {
|
||||
span {
|
||||
background-color: black;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.search-icon, .font-icon {
|
||||
height: 40px;
|
||||
width: 40px;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
line-height: 40px;
|
||||
color: rgba(0, 0, 0, 0.5);
|
||||
cursor: pointer;
|
||||
font-size: 2rem;
|
||||
|
||||
&:hover {
|
||||
color: #eee;
|
||||
background-color:#666;
|
||||
border-radius: .2ex;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.font-icon{
|
||||
display: inline-block;
|
||||
// padding:0.6ex 1ex;
|
||||
margin-left:1rem;
|
||||
background:#333;
|
||||
color:#eee;
|
||||
border-radius: .2ex;
|
||||
|
||||
&:hover {
|
||||
background:#666;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.dark-mode .font-icon{
|
||||
background:#aaa;
|
||||
color:#333;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
.menu {
|
||||
.menu, .menu-open .menu {
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
@@ -39,7 +39,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.menu-hidden {
|
||||
.menu-closed .menu {
|
||||
width: 0;
|
||||
}
|
||||
|
||||
@@ -47,4 +47,19 @@
|
||||
.menu {
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.menu-close-icon {
|
||||
display: block;
|
||||
padding:1ex;
|
||||
font-size: 1.5em;
|
||||
float:right;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@include min-screen(600px) {
|
||||
|
||||
.menu-close-icon {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
+98
-3
@@ -1,6 +1,7 @@
|
||||
@charset "utf-8";
|
||||
|
||||
@import "normalize";
|
||||
@import "colorbox";
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
@@ -21,6 +22,10 @@ body {
|
||||
letter-spacing: 0.2px;
|
||||
}
|
||||
|
||||
body.dark-mode .page{
|
||||
background:#444;
|
||||
color:#eee;
|
||||
}
|
||||
|
||||
@mixin min-screen($min-width: $body-width) {
|
||||
@media screen and (min-width: $min-width) {
|
||||
@@ -40,9 +45,21 @@ $sidebar-width: 300px;
|
||||
@import "content";
|
||||
@import "header";
|
||||
|
||||
img {
|
||||
transform: scale(0.666);
|
||||
transform-origin: top left;
|
||||
@media screen and (min-width: 1920px)
|
||||
{
|
||||
// img.scaled-image {
|
||||
// transform: scale(0.666);
|
||||
// transform-origin: top left;
|
||||
// }
|
||||
}
|
||||
|
||||
.colorbox-inline img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.icon-image {
|
||||
display:inline;
|
||||
max-height: 1.4em;
|
||||
}
|
||||
|
||||
.back-button {
|
||||
@@ -58,4 +75,82 @@ img {
|
||||
iframe {
|
||||
width:560px;
|
||||
height:315px;
|
||||
}
|
||||
|
||||
.youtube-thumb {
|
||||
margin-top:2em;
|
||||
position:relative;
|
||||
max-width:500px;
|
||||
}
|
||||
|
||||
.youtube-overlay {
|
||||
position:absolute;
|
||||
width:8rem;
|
||||
height:4.5rem;
|
||||
line-height:4.5rem;
|
||||
font-size: 2.5rem;
|
||||
left:calc(50% - 4rem);
|
||||
top:calc(50% - 2.25rem);
|
||||
text-align:center;
|
||||
opacity:.8;
|
||||
background:#f68a28;
|
||||
color:white;
|
||||
border-radius: .3rem;
|
||||
}
|
||||
|
||||
.youtube-overlay:hover {
|
||||
background:#f68a28;
|
||||
opacity:1;
|
||||
}
|
||||
|
||||
.video-parent {
|
||||
position: relative;
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
.video-parent:hover .play-pause, .video-parent.paused .play-pause {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.play-pause {
|
||||
display:none;
|
||||
opacity:.7;
|
||||
position:absolute;
|
||||
width:8rem;
|
||||
height:4.5rem;
|
||||
line-height:4.5rem;
|
||||
font-size: 2.5rem;
|
||||
left:calc(50% - 4rem);
|
||||
top:calc(50% - 2.25rem);
|
||||
text-align:center;
|
||||
background:#f68a28;
|
||||
color:#fff;
|
||||
border-radius: .3rem;
|
||||
z-index:1000;
|
||||
}
|
||||
|
||||
.play-pause:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
@media (hover: none) {
|
||||
.play-pause {
|
||||
display:block;
|
||||
}
|
||||
|
||||
.video-parent.playing:hover .play-pause {
|
||||
display:none;
|
||||
}
|
||||
}
|
||||
|
||||
.is-clearfix {
|
||||
clear:both;
|
||||
}
|
||||
|
||||
.is-pulled-left {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.is-pulled-right {
|
||||
float: right;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#colorbox, #cboxOverlay, #cboxWrapper{position:absolute;top:0;left:0;z-index:9999;overflow:hidden;-webkit-transform:translate3d(0,0,0);}
|
||||
#cboxWrapper{max-width:none;}
|
||||
#cboxOverlay{position:fixed;width:100%;height:100%;}
|
||||
#cboxMiddleLeft, #cboxBottomLeft{clear:left;}
|
||||
#cboxContent{position:relative;}
|
||||
#cboxLoadedContent{overflow:auto;-webkit-overflow-scrolling:touch;}
|
||||
#cboxTitle{margin:0;}
|
||||
#cboxLoadingOverlay, #cboxLoadingGraphic{position:absolute;top:0;left:0;width:100%;height:100%;}
|
||||
#cboxPrevious, #cboxNext, #cboxClose, #cboxSlideshow{cursor:pointer;}
|
||||
.cboxPhoto{float:left;margin:auto;border:0;display:block;max-width:none;-ms-interpolation-mode:bicubic;}
|
||||
.cboxIframe{width:100%;height:100%;display:block;border:0;padding:0;margin:0;}
|
||||
#colorbox, #cboxContent, #cboxLoadedContent{box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;}
|
||||
#cboxOverlay{background:#000;opacity:0.9;filter:alpha(opacity = 90);}
|
||||
#colorbox{outline:0;}
|
||||
#cboxTopLeft{width:14px;height:14px;background:url(colorbox-images/controls.png) no-repeat 0 0;}
|
||||
#cboxTopCenter{height:14px;background:url(colorbox-images/border.png) repeat-x top left;}
|
||||
#cboxTopRight{width:14px;height:14px;background:url(colorbox-images/controls.png) no-repeat -36px 0;}
|
||||
#cboxBottomLeft{width:14px;height:43px;background:url(colorbox-images/controls.png) no-repeat 0 -32px;}
|
||||
#cboxBottomCenter{height:43px;background:url(colorbox-images/border.png) repeat-x bottom left;}
|
||||
#cboxBottomRight{width:14px;height:43px;background:url(colorbox-images/controls.png) no-repeat -36px -32px;}
|
||||
#cboxMiddleLeft{width:14px;background:url(colorbox-images/controls.png) repeat-y -175px 0;}
|
||||
#cboxMiddleRight{width:14px;background:url(colorbox-images/controls.png) repeat-y -211px 0;}
|
||||
#cboxContent{background:#fff;overflow:visible;}
|
||||
.cboxIframe{background:#fff;}
|
||||
#cboxError{padding:50px;border:1px solid #ccc;}
|
||||
#cboxLoadedContent{margin-bottom:5px;}
|
||||
#cboxLoadingOverlay{background:url(colorbox-images/loading_background.png) no-repeat center center;}
|
||||
#cboxLoadingGraphic{background:url(colorbox-images/loading.gif) no-repeat center center;}
|
||||
#cboxTitle{position:absolute;bottom:-25px;left:0;text-align:center;width:100%;font-weight:bold;color:#7C7C7C;}
|
||||
#cboxCurrent{position:absolute;bottom:-25px;left:58px;font-weight:bold;color:#7C7C7C;}
|
||||
#cboxPrevious, #cboxNext, #cboxSlideshow, #cboxClose{border:0;padding:0;margin:0;overflow:visible;position:absolute;bottom:-29px;background:url(colorbox-images/controls.png) no-repeat 0px 0px;width:23px;height:23px;text-indent:-9999px;}
|
||||
#cboxPrevious:active, #cboxNext:active, #cboxSlideshow:active, #cboxClose:active{outline:0;}
|
||||
#cboxPrevious{left:0px;background-position:-51px -25px;}
|
||||
#cboxPrevious:hover{background-position:-51px 0px;}
|
||||
#cboxNext{left:27px;background-position:-75px -25px;}
|
||||
#cboxNext:hover{background-position:-75px 0px;}
|
||||
#cboxClose{right:0;background-position:-100px -25px;}
|
||||
#cboxClose:hover{background-position:-100px 0px;}
|
||||
.cboxSlideshow_on #cboxSlideshow{background-position:-125px 0px;right:27px;}
|
||||
.cboxSlideshow_on #cboxSlideshow:hover{background-position:-150px 0px;}
|
||||
.cboxSlideshow_off #cboxSlideshow{background-position:-150px -25px;right:27px;}
|
||||
.cboxSlideshow_off #cboxSlideshow:hover{background-position:-125px 0px;}
|
||||
+15
-6
@@ -1,10 +1,19 @@
|
||||
function initToggleMenu() {
|
||||
var $menu = document.querySelector(".menu");
|
||||
var $menuIcon = document.querySelector(".menu-icon");
|
||||
var $page = document.querySelector(".page");
|
||||
$menuIcon.addEventListener("click", function () {
|
||||
$menu.classList.toggle("menu-hidden");
|
||||
$page.classList.toggle("page-without-menu");
|
||||
$(".menu-icon").click(function (e) {
|
||||
let body = $("body");
|
||||
let mobile = window.innerWidth < 600;
|
||||
let menu_closed = body.hasClass("menu-closed");
|
||||
let menu_open = body.hasClass("menu-open");
|
||||
let new_page = !(menu_closed || menu_open);
|
||||
|
||||
if((!mobile && (new_page || menu_open)) || mobile && menu_open) {
|
||||
body.addClass("menu-closed");
|
||||
body.removeClass("menu-open");
|
||||
}
|
||||
else {
|
||||
body.removeClass("menu-closed");
|
||||
body.addClass("menu-open");
|
||||
}
|
||||
});
|
||||
}
|
||||
function debounce(func, wait) {
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 139 B |
Binary file not shown.
|
After Width: | Height: | Size: 2.0 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 8.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 131 B |
@@ -1,11 +1,40 @@
|
||||
|
||||
$(document).ready(function() {
|
||||
$("img").each(function(idx, elm){
|
||||
$(elm).css("margin-bottom", elm.height * -0.333);
|
||||
}).on("load", function(e){
|
||||
$(e.target).css("margin-bottom", e.target.height * -0.333);
|
||||
jQuery('a.thumbnail').colorbox({rel:'gal'});
|
||||
jQuery('a.gallery_image').colorbox({rel:'gal'});
|
||||
jQuery(".youtube").colorbox({iframe:true, innerWidth:'75%', innerHeight:'75%'});
|
||||
|
||||
jQuery(".font-icon").click(function (){
|
||||
jQuery("body").toggleClass("dark-mode");
|
||||
if(getCookie("dark-mode") === "true") {
|
||||
setCookie("dark-mode", "false", 365);
|
||||
}
|
||||
else {
|
||||
setCookie("dark-mode", "true", 365);
|
||||
}
|
||||
});
|
||||
|
||||
if(getCookie("dark-mode") === "true") {
|
||||
jQuery("body").toggleClass("dark-mode");
|
||||
}
|
||||
|
||||
if(window.innerWidth >= 1920) {
|
||||
|
||||
// $("img.scaled-image").each(function(idx, elm){
|
||||
// $(elm).css("margin-bottom", elm.height * -0.333);
|
||||
// }).on("load", function(e){
|
||||
// $(e.target).css("margin-bottom", e.target.height * -0.333);
|
||||
// });
|
||||
$("a.colorbox-inline").each(function(idx, elm){
|
||||
let child = $(elm).children("img")[0];
|
||||
let w = (child.naturalWidth * 0.666) + 1
|
||||
let h = (child.naturalHeight * 0.666) + 1
|
||||
$(elm).colorbox({inline: true, innerWidth: w, innerHeight: h, scrolling: false});
|
||||
});
|
||||
}
|
||||
else {
|
||||
jQuery("a.colorbox-inline").colorbox({inline:true});
|
||||
}
|
||||
$(".back-button")
|
||||
.html("Go Back")
|
||||
.click(function(_) { window.history.back()});
|
||||
@@ -14,4 +43,29 @@ $(document).ready(function() {
|
||||
console.log(navigator.userAgent);
|
||||
$(".search-icon").css("display", "none");
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
function setCookie(cname, cvalue, exdays) {
|
||||
var d = new Date();
|
||||
d.setTime(d.getTime() + (exdays*24*60*60*1000));
|
||||
var expires = "expires="+ d.toUTCString();
|
||||
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
|
||||
}
|
||||
|
||||
function getCookie(cname) {
|
||||
var name = cname + "=";
|
||||
var decodedCookie = decodeURIComponent(document.cookie);
|
||||
var ca = decodedCookie.split(';');
|
||||
for(var i = 0; i <ca.length; i++) {
|
||||
var c = ca[i];
|
||||
while (c.charAt(0) == ' ') {
|
||||
c = c.substring(1);
|
||||
}
|
||||
if (c.indexOf(name) == 0) {
|
||||
return c.substring(name.length, c.length);
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
/*!
|
||||
Colorbox 1.6.3
|
||||
license: MIT
|
||||
http://www.jacklmoore.com/colorbox
|
||||
*/
|
||||
(function(t,e,i){function n(i,n,o){var r=e.createElement(i);return n&&(r.id=Z+n),o&&(r.style.cssText=o),t(r)}function o(){return i.innerHeight?i.innerHeight:t(i).height()}function r(e,i){i!==Object(i)&&(i={}),this.cache={},this.el=e,this.value=function(e){var n;return void 0===this.cache[e]&&(n=t(this.el).attr("data-cbox-"+e),void 0!==n?this.cache[e]=n:void 0!==i[e]?this.cache[e]=i[e]:void 0!==X[e]&&(this.cache[e]=X[e])),this.cache[e]},this.get=function(e){var i=this.value(e);return t.isFunction(i)?i.call(this.el,this):i}}function h(t){var e=W.length,i=(A+t)%e;return 0>i?e+i:i}function a(t,e){return Math.round((/%/.test(t)?("x"===e?E.width():o())/100:1)*parseInt(t,10))}function s(t,e){return t.get("photo")||t.get("photoRegex").test(e)}function l(t,e){return t.get("retinaUrl")&&i.devicePixelRatio>1?e.replace(t.get("photoRegex"),t.get("retinaSuffix")):e}function d(t){"contains"in x[0]&&!x[0].contains(t.target)&&t.target!==v[0]&&(t.stopPropagation(),x.focus())}function c(t){c.str!==t&&(x.add(v).removeClass(c.str).addClass(t),c.str=t)}function g(e){A=0,e&&e!==!1&&"nofollow"!==e?(W=t("."+te).filter(function(){var i=t.data(this,Y),n=new r(this,i);return n.get("rel")===e}),A=W.index(_.el),-1===A&&(W=W.add(_.el),A=W.length-1)):W=t(_.el)}function u(i){t(e).trigger(i),ae.triggerHandler(i)}function f(i){var o;if(!G){if(o=t(i).data(Y),_=new r(i,o),g(_.get("rel")),!$){$=q=!0,c(_.get("className")),x.css({visibility:"hidden",display:"block",opacity:""}),I=n(se,"LoadedContent","width:0; height:0; overflow:hidden; visibility:hidden"),b.css({width:"",height:""}).append(I),j=T.height()+k.height()+b.outerHeight(!0)-b.height(),D=C.width()+H.width()+b.outerWidth(!0)-b.width(),N=I.outerHeight(!0),z=I.outerWidth(!0);var h=a(_.get("initialWidth"),"x"),s=a(_.get("initialHeight"),"y"),l=_.get("maxWidth"),f=_.get("maxHeight");_.w=Math.max((l!==!1?Math.min(h,a(l,"x")):h)-z-D,0),_.h=Math.max((f!==!1?Math.min(s,a(f,"y")):s)-N-j,0),I.css({width:"",height:_.h}),J.position(),u(ee),_.get("onOpen"),O.add(F).hide(),x.focus(),_.get("trapFocus")&&e.addEventListener&&(e.addEventListener("focus",d,!0),ae.one(re,function(){e.removeEventListener("focus",d,!0)})),_.get("returnFocus")&&ae.one(re,function(){t(_.el).focus()})}var p=parseFloat(_.get("opacity"));v.css({opacity:p===p?p:"",cursor:_.get("overlayClose")?"pointer":"",visibility:"visible"}).show(),_.get("closeButton")?B.html(_.get("close")).appendTo(b):B.appendTo("<div/>"),w()}}function p(){x||(V=!1,E=t(i),x=n(se).attr({id:Y,"class":t.support.opacity===!1?Z+"IE":"",role:"dialog",tabindex:"-1"}).hide(),v=n(se,"Overlay").hide(),L=t([n(se,"LoadingOverlay")[0],n(se,"LoadingGraphic")[0]]),y=n(se,"Wrapper"),b=n(se,"Content").append(F=n(se,"Title"),R=n(se,"Current"),P=t('<button type="button"/>').attr({id:Z+"Previous"}),K=t('<button type="button"/>').attr({id:Z+"Next"}),S=n("button","Slideshow"),L),B=t('<button type="button"/>').attr({id:Z+"Close"}),y.append(n(se).append(n(se,"TopLeft"),T=n(se,"TopCenter"),n(se,"TopRight")),n(se,!1,"clear:left").append(C=n(se,"MiddleLeft"),b,H=n(se,"MiddleRight")),n(se,!1,"clear:left").append(n(se,"BottomLeft"),k=n(se,"BottomCenter"),n(se,"BottomRight"))).find("div div").css({"float":"left"}),M=n(se,!1,"position:absolute; width:9999px; visibility:hidden; display:none; max-width:none;"),O=K.add(P).add(R).add(S)),e.body&&!x.parent().length&&t(e.body).append(v,x.append(y,M))}function m(){function i(t){t.which>1||t.shiftKey||t.altKey||t.metaKey||t.ctrlKey||(t.preventDefault(),f(this))}return x?(V||(V=!0,K.click(function(){J.next()}),P.click(function(){J.prev()}),B.click(function(){J.close()}),v.click(function(){_.get("overlayClose")&&J.close()}),t(e).bind("keydown."+Z,function(t){var e=t.keyCode;$&&_.get("escKey")&&27===e&&(t.preventDefault(),J.close()),$&&_.get("arrowKey")&&W[1]&&!t.altKey&&(37===e?(t.preventDefault(),P.click()):39===e&&(t.preventDefault(),K.click()))}),t.isFunction(t.fn.on)?t(e).on("click."+Z,"."+te,i):t("."+te).live("click."+Z,i)),!0):!1}function w(){var e,o,r,h=J.prep,d=++le;if(q=!0,U=!1,u(he),u(ie),_.get("onLoad"),_.h=_.get("height")?a(_.get("height"),"y")-N-j:_.get("innerHeight")&&a(_.get("innerHeight"),"y"),_.w=_.get("width")?a(_.get("width"),"x")-z-D:_.get("innerWidth")&&a(_.get("innerWidth"),"x"),_.mw=_.w,_.mh=_.h,_.get("maxWidth")&&(_.mw=a(_.get("maxWidth"),"x")-z-D,_.mw=_.w&&_.w<_.mw?_.w:_.mw),_.get("maxHeight")&&(_.mh=a(_.get("maxHeight"),"y")-N-j,_.mh=_.h&&_.h<_.mh?_.h:_.mh),e=_.get("href"),Q=setTimeout(function(){L.show()},100),_.get("inline")){var c=t(e);r=t("<div>").hide().insertBefore(c),ae.one(he,function(){r.replaceWith(c)}),h(c)}else _.get("iframe")?h(" "):_.get("html")?h(_.get("html")):s(_,e)?(e=l(_,e),U=_.get("createImg"),t(U).addClass(Z+"Photo").bind("error."+Z,function(){h(n(se,"Error").html(_.get("imgError")))}).one("load",function(){d===le&&setTimeout(function(){var e;_.get("retinaImage")&&i.devicePixelRatio>1&&(U.height=U.height/i.devicePixelRatio,U.width=U.width/i.devicePixelRatio),_.get("scalePhotos")&&(o=function(){U.height-Line truncated
|
||||
@@ -0,0 +1,131 @@
|
||||
jQuery(function($)
|
||||
{
|
||||
|
||||
// Default time delay before checking location
|
||||
var call_back_delay = 500;
|
||||
|
||||
// Set some flags for tracking & execution
|
||||
var scroll_timer = null;
|
||||
var scroller = false; // indicate the user has begun scrolling
|
||||
|
||||
scroll_points_in_page = jQuery(".scroll_point");
|
||||
video_screenshots = jQuery(".video-screenshot");
|
||||
video_parents = jQuery(".video-parent");
|
||||
|
||||
var apply_video_click = function (video) {
|
||||
$(video).click(function (e) {
|
||||
var v = $(this)[0];
|
||||
if(v.paused) {
|
||||
v.play();
|
||||
$(v).attr("data-paused", "false");
|
||||
}
|
||||
else {
|
||||
v.pause();
|
||||
$(v).attr("data-paused", "true");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for(var i = 0; i < video_parents.length; i++) {
|
||||
let video_with_event = $(video_parents[i]).children("video")[0];
|
||||
let play_icon = $($(video_parents[i]).children(".play-pause")[0]).children("i");
|
||||
let parent = $(video_parents[i]);
|
||||
|
||||
parent.addClass("playing");
|
||||
|
||||
video_with_event.onpause = function () {
|
||||
parent.addClass("paused");
|
||||
parent.removeClass("playing");
|
||||
play_icon.addClass("fa-play");
|
||||
play_icon.removeClass("fa-pause");
|
||||
}
|
||||
video_with_event.onplay = function () {
|
||||
parent.removeClass("paused");
|
||||
parent.addClass("playing");
|
||||
play_icon.removeClass("fa-play");
|
||||
play_icon.addClass("fa-pause");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for(var i = 0; i < video_screenshots.length; i++) {
|
||||
apply_video_click(video_screenshots[i]);
|
||||
}
|
||||
|
||||
$(".play-pause").click(function (e) { $(this).next("video").click();});
|
||||
|
||||
|
||||
// Check the location and track user
|
||||
function track_location()
|
||||
{
|
||||
view_bottom = $(window).height() + $(window).scrollTop();// the bottom of the visible area
|
||||
|
||||
// loop through the scroll points and send events for any within the visible part of the page
|
||||
for(var i = 0; i < scroll_points_in_page.length; i++)
|
||||
{
|
||||
check_scroll_point(scroll_points_in_page[i]);
|
||||
}
|
||||
for(var i = 0; i < video_screenshots.length; i++)
|
||||
{
|
||||
video_screenshots_play_pause(video_screenshots[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
var check_scroll_point = function(current_value)
|
||||
{
|
||||
var current_object = $(current_value);
|
||||
|
||||
if (view_bottom >= current_object.offset().top && $(window).scrollTop() <= current_object.offset().top && (current_object.attr("hit") === undefined || current_object.attr("hit") === null))
|
||||
{
|
||||
if (!debug_mode)
|
||||
{
|
||||
ga('send', 'event', current_object.attr("data-eventCategory") + "_scroll_points", "in_view", current_object.attr("data-eventLabel"));
|
||||
}
|
||||
else
|
||||
{
|
||||
console.log(current_object.attr("data-eventCategory") + "_scroll_points, " + current_object.attr("data-eventLabel"));
|
||||
}
|
||||
|
||||
$("[data-eventLabel='" + current_object.attr("data-eventLabel")+ "']").attr("hit", "1"); // after the point has been hit don't count it again
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var video_screenshots_play_pause = function(current_value)
|
||||
{
|
||||
var current_object = $(current_value);
|
||||
var video_middle = current_object.offset().top + (current_object.height() / 2);
|
||||
var video_on_screen = view_bottom > video_middle && video_middle > $(window).scrollTop();
|
||||
|
||||
if (
|
||||
window.innerWidth > 600
|
||||
&& video_on_screen
|
||||
&& current_value.paused
|
||||
&& current_object.attr("data-paused") === "false"
|
||||
)
|
||||
{
|
||||
current_value.play();
|
||||
}
|
||||
else if (!current_value.paused && !video_on_screen) {
|
||||
current_value.pause();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Track the scrolling and track location
|
||||
$(".page").scroll(function()
|
||||
{
|
||||
if (scroll_timer) {
|
||||
clearTimeout(scroll_timer);
|
||||
}
|
||||
|
||||
// Use a buffer so we don't call track_location too often.
|
||||
scroll_timer = setTimeout(track_location, call_back_delay);
|
||||
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
@@ -0,0 +1 @@
|
||||
<a class="zola-anchor" href="#{{ id }}" aria-label="Anchor link for: {{ id }}"><i class="fas fa-link"></i></a>
|
||||
@@ -5,9 +5,12 @@
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
||||
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600" rel="stylesheet" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1">
|
||||
<meta name="keywords" content="Futures, Options, Derivatives, Trade, Trading, Professional, options trading, futures trading, Software" />
|
||||
<meta name="rights" content="© Blue Trading Systems" />
|
||||
<meta name="description" content="Documentation for Blue Trading Systems' BTS Spark" />
|
||||
|
||||
<!-- <meta name="keywords" content="Futures, Derivatives, Trade, Trading, Trader, Professional, futures trading, Software" />
|
||||
<meta name="description" content="Documentation for Blue Trading Systems' BTS Spark" /> -->
|
||||
{% block meta %}
|
||||
{% endblock meta %}
|
||||
|
||||
<title>{% block title %}{{ config.title }}{% endblock title %}</title>
|
||||
|
||||
@@ -36,12 +39,8 @@
|
||||
|
||||
}
|
||||
</script>
|
||||
<script src="https://kit.fontawesome.com/93aca32d82.js"></script>
|
||||
|
||||
<script
|
||||
src="https://code.jquery.com/jquery-3.3.1.min.js"
|
||||
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
|
||||
crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" src="{{ get_url(path="image.js") | safe }}"></script>
|
||||
{% block js %}
|
||||
|
||||
{% endblock js %}
|
||||
@@ -60,6 +59,9 @@
|
||||
{% block before_menu %}
|
||||
{% endblock before_menu %}
|
||||
<nav role="navigation">
|
||||
<div class="menu-icon menu-close-icon">
|
||||
<i class="fas fa-arrow-left"></i>
|
||||
</div>
|
||||
<ul>
|
||||
{% block menu %}
|
||||
{% set index = get_section(path="_index.md") %}
|
||||
@@ -116,14 +118,14 @@
|
||||
|
||||
<div class="page">
|
||||
<div class="page__header">
|
||||
<div class="menu-icon">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</div>
|
||||
<span class="menu-icon">
|
||||
<i class="fas fa-bars"></i>
|
||||
</span>
|
||||
{% if config.build_search_index %}
|
||||
<span class="search-icon">🔎</span>
|
||||
<span class="search-icon"><i class="fas fa-search"></i></span>
|
||||
{% endif %}
|
||||
<span class="font-icon"><i class="fas fa-font"></i></span>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="page__content">
|
||||
@@ -154,11 +156,19 @@
|
||||
</div>
|
||||
|
||||
{% block js_body %}
|
||||
<script
|
||||
src="https://code.jquery.com/jquery-3.3.1.min.js"
|
||||
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
|
||||
crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" src="{{ get_url(path="jquery.colorbox-min.js") | safe }}"></script>
|
||||
<script type="text/javascript" src="{{ get_url(path="image.js") | safe }}"></script>
|
||||
<script type="text/javascript" src="{{ get_url(path="scroll_actions.js") | safe }}"></script>
|
||||
{% if config.build_search_index %}
|
||||
<script type="text/javascript" src="{{ get_url(path="elasticlunr.min.js") | safe }}"></script>
|
||||
<script type="text/javascript" src="{{ get_url(path="search_index.en.js") | safe }}"></script>
|
||||
{% endif %}
|
||||
<script type="text/javascript" src="{{ get_url(path="book.js") | safe }}"></script>
|
||||
|
||||
{% endblock js_body %}
|
||||
</body>
|
||||
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
{% extends "index.html" %}
|
||||
|
||||
{% block meta %}
|
||||
{% if page.extra.page_description %}
|
||||
<meta name="description" content="{{ page.extra.page_description }}" />
|
||||
{% else %}
|
||||
<meta name="description" content="{{ page.title }} Documentation for Blue Trading Systems' BTS Spark" />
|
||||
{% endif %}
|
||||
{% endblock meta %}
|
||||
|
||||
{% block title %}{{ page.title }} • {{ config.title }}{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
{% extends "index.html" %}
|
||||
|
||||
{% block meta %}
|
||||
{% if section.extra.page_description %}
|
||||
<meta name="description" content="{{ section.extra.page_description }}" />
|
||||
{% else %}
|
||||
<meta name="description" content="{{ section.title }} Documentation for Blue Trading Systems' BTS Spark" />
|
||||
{% endif %}
|
||||
{% endblock meta %}
|
||||
|
||||
{% block title %}{{ section.title }} • {{ config.title }}{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<div style="clear:both;"></div>
|
||||
@@ -0,0 +1,17 @@
|
||||
{% if class %}
|
||||
{% set cls = class %}
|
||||
{% else %}
|
||||
{% set cls = "" %}
|
||||
{% endif %}
|
||||
|
||||
{% if page %}
|
||||
{% set context = page %}
|
||||
{% elif section %}
|
||||
{% set context = section %}
|
||||
{% endif %}
|
||||
|
||||
<img
|
||||
class="icon-image {{cls}}"
|
||||
src="{{name}}"
|
||||
alt="{{alt}}"
|
||||
/>
|
||||
@@ -0,0 +1,34 @@
|
||||
{% if pull %}
|
||||
{% if pull == "left" %}
|
||||
{% set float = "is-pulled-left" %}
|
||||
{% elif pull == "right" %}
|
||||
{% set float = "is-pulled-right" %}
|
||||
{% else %}
|
||||
{% set float = "is-pulled-over-there" %}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% set float = " " %}
|
||||
{% endif %}
|
||||
|
||||
{% if class %}
|
||||
{% set cls = class %}
|
||||
{% else %}
|
||||
{% set cls = "" %}
|
||||
{% endif %}
|
||||
|
||||
{% if page %}
|
||||
{% set context = page %}
|
||||
{% elif section %}
|
||||
{% set context = section %}
|
||||
{% endif %}
|
||||
|
||||
{% set image_path = context.path ~ name %}
|
||||
{% set meta = get_image_metadata(path = image_path) %}
|
||||
{% set image_width = (meta.width * 0.666)%}
|
||||
|
||||
<img
|
||||
class="{{cls}} {{float}}"
|
||||
style="width:{{image_width}}px;"
|
||||
src="{{name}}"
|
||||
alt="{{alt}}"
|
||||
/>
|
||||
@@ -0,0 +1,52 @@
|
||||
{% if pull %}
|
||||
{% if pull == "left" %}
|
||||
{% set float = "is-pulled-left" %}
|
||||
{% elif pull == "right" %}
|
||||
{% set float = "is-pulled-right" %}
|
||||
{% else %}
|
||||
{% set float = "is-pulled-over-there" %}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% set float = " " %}
|
||||
{% endif %}
|
||||
|
||||
{% if class %}
|
||||
{% set cls = class %}
|
||||
{% else %}
|
||||
{% set cls = "" %}
|
||||
{% endif %}
|
||||
|
||||
{% if width %}
|
||||
{% set wdth = width %}
|
||||
{% else %}
|
||||
{% set wdth = "100%" %}
|
||||
{% endif %}
|
||||
|
||||
{% if page %}
|
||||
{% set context = page %}
|
||||
{% elif section %}
|
||||
{% set context = section %}
|
||||
{% endif %}
|
||||
|
||||
{% set image_path = context.path ~ name %}
|
||||
{% set meta = get_image_metadata(path = image_path) %}
|
||||
{% set image_width = (meta.width * 0.666)%}
|
||||
{% set id = name | replace(from=".", to="-") %}
|
||||
|
||||
<a class="colorbox-inline" href="#{{id}}">
|
||||
<img
|
||||
class="{{cls}} {{float}}"
|
||||
style="width: {{wdth}}; max-width:{{image_width}}"
|
||||
src="{{name}}"
|
||||
alt="{{alt}}"
|
||||
/>
|
||||
</a>
|
||||
|
||||
<div id="colorbox-inline-content" style="display: none;">
|
||||
<div id="{{id}}">
|
||||
<img class = "" style="width:{{image_width}}; max-width:95vw; max-height:95vh; object-fit: scale-down"
|
||||
src="{{name}}"
|
||||
alt="{{alt}}"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,6 @@
|
||||
<div class="video-parent">
|
||||
<div class="play-pause"><i class="fas fa-play"></i></div>
|
||||
<video class="video-screenshot" style="width: {{width}}; max-width:100%;" muted loop data-paused="false">
|
||||
<source src="{{name}}" type="video/mp4">
|
||||
</video>
|
||||
</div>
|
||||
@@ -0,0 +1,8 @@
|
||||
<div {% if class %}class="{{class}}"{% endif %}>
|
||||
<div class="embed-responsive embed-responsive-16by9 youtube-thumb">
|
||||
<a class="gallery_image youtube cboxElement" href="https://www.youtube.com/embed/{{id}}" style="display:block;">
|
||||
<img class="video_thumb" style="width:100%;" src="https://img.youtube.com/vi/{{id}}/0.jpg" alt="Video Thumbnail" />
|
||||
<div class="youtube-overlay"><i class="fas fa-play"></i></div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
+1
-1
Submodule docker/linux updated: e13bb5d8df...c40e6eba4b.
+1
-1
Submodule externals updated: 67a79263ba...6d8f64ca5c.
@@ -1,83 +1,74 @@
|
||||
using bts;
|
||||
using bts.api.admin;
|
||||
using bts.api.core;
|
||||
using bts.utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
using System.Reactive.Subjects;
|
||||
using bts.api.core;
|
||||
using mbts.ui.shell;
|
||||
|
||||
namespace mbts.spark {
|
||||
[Export]
|
||||
class AdminModel : IDisposable {
|
||||
public readonly UserTuple user;
|
||||
|
||||
readonly BehaviorSubject<IReadOnlyDictionary<uint, string>>
|
||||
_accounts_subject = new BehaviorSubject<IReadOnlyDictionary<uint, string>>(new Dictionary<uint, string>()),
|
||||
_users_subject = new BehaviorSubject<IReadOnlyDictionary<uint, string>>(new Dictionary<uint, string>());
|
||||
IReadOnlyDictionary<uint, string>
|
||||
_account_map = new Dictionary<uint, string>(),
|
||||
_user_map = new Dictionary<uint, string>();
|
||||
readonly BehaviorSubject<AdminModelWrapper> _wrapper_subject = new BehaviorSubject<AdminModelWrapper>(new AdminModelWrapper());
|
||||
IDisposable _dispose;
|
||||
|
||||
IDisposable _dispose;
|
||||
IReadOnlyDictionary<uint, string> _account_map = DictionaryHelper.empty<uint, string>();
|
||||
|
||||
[ImportingConstructor]
|
||||
AdminModel(AdminService service, [Import]UserTuple user) {
|
||||
AdminModel(AdminService service, UserTuple user) {
|
||||
this.user = user;
|
||||
_dispose = service.subscribei_admin_data().Select(update => {
|
||||
_wrapper_subject.OnNext(new AdminModelWrapper(update.all.TryFirst(), user.name));
|
||||
IEnumerable<BTSUserImmutable> active_users =
|
||||
from admin_data in update.all
|
||||
from bts_user in admin_data.Users
|
||||
where bts_user.Name == user.name && bts_user.HasUserData && bts_user.UserData.HasAccountPermissions
|
||||
select bts_user;
|
||||
|
||||
IEnumerable<BTSAccountImmutable> active_accounts =
|
||||
from admin_data in update.all
|
||||
from bts_account in admin_data.Accounts
|
||||
where bts_account.IsPresent && _wrapper_subject.Value.can_view_account(bts_account.Name)
|
||||
join account_id in (
|
||||
from bts_user in active_users
|
||||
from account_id in bts_user.UserData.AccountPermissions.AccountPermissions.Keys
|
||||
select account_id
|
||||
) on bts_account.Id equals account_id
|
||||
select bts_account;
|
||||
|
||||
var users = active_users.ToDictionary(u => u.Id, u => u.Name);
|
||||
var accounts = active_accounts.ToDictionary(a => a.Id, a => a.Name);
|
||||
return (users, accounts);
|
||||
}).Subscribe(t => {
|
||||
_account_map = t.accounts;
|
||||
_user_map = t.users;
|
||||
_users_subject.OnNext(_user_map = t.users);
|
||||
_accounts_subject.OnNext(_account_map = t.accounts);
|
||||
});
|
||||
// accounts
|
||||
on_accounts = service.subscribei_admin_data()
|
||||
.Select(up => up.all.TryGetFirst(out var ad) && ad.Users.Where(u => u.Name == user.name).TryGetSingle(out var usr) && usr.HasUserData && usr.UserData.HasAccountPermissions ?
|
||||
usr.UserData.AccountPermissions.AccountPermissions
|
||||
.Where(kv => (kv.Value.TradingPermission != null && kv.Value.TradingPermission.HasPermissions) || kv.Value.AdminPermission.HasPermissions)
|
||||
.Select(kv => ad.Accounts.Where(a => a.Id == kv.Key).TryGetSingle(out var acc) ? acc : (BTSAccountImmutable?)null)
|
||||
.Where(acc => acc.HasValue && acc.Value.IsPresent)
|
||||
.Select(acc => acc.Value)
|
||||
.ToDictionary(acc => acc.Id, acc => acc.Name) :
|
||||
new Dictionary<uint, string>(0))
|
||||
.Replay(1)
|
||||
.RefCount();
|
||||
// users
|
||||
on_users = Observable.Return(DictionaryHelper.wrap_value(user.id, user.name));
|
||||
all_user_tuples = user.permissions == UserTuple.Permissions.Admin ?
|
||||
service.subscribei_admin_data()
|
||||
.Select(u => u.all.TryFirst())
|
||||
.Where(ad => ad.HasValue)
|
||||
.Select(ad => ad.Value.Users
|
||||
.Where(u => user.can_access_user_data(u.Id))
|
||||
.Select(u => new UserTuple(u.Id, u.Name))
|
||||
.ToDictionary(UserTuple.key_fn))
|
||||
.Table(UserTuple.key_fn)
|
||||
.Cache() :
|
||||
Observable.Return(TableUpdate<UserTuple, uint>.mk_empty(UserTuple.key_fn).with_added(new[] { user }));
|
||||
_dispose = on_accounts.Subscribe(map => _account_map = map);
|
||||
}
|
||||
|
||||
public IObservable<IReadOnlyDictionary<uint, string>> on_users => _users_subject.AsObservable();
|
||||
public IObservable<IReadOnlyDictionary<uint, string>> on_accounts => _accounts_subject.AsObservable();
|
||||
public IObservable<IReadOnlyList<UserTuple>> on_user_tuples => on_users.Select(d => d.Select(kv => new UserTuple(kv.Key, kv.Value)).ToList());
|
||||
public IObservable<IReadOnlyList<AccountTuple>> on_account_tuples => on_accounts.Select(d => d.Select(kv => new AccountTuple(kv.Key, kv.Value)).ToList());
|
||||
public IObservable<AdminModelWrapper> on_admin_data => _wrapper_subject.AsObservable();
|
||||
public IObservable<IReadOnlyDictionary<uint, string>> on_users { get; }
|
||||
public IObservable<IReadOnlyDictionary<uint, string>> on_accounts { get; }
|
||||
public IObservable<TableUpdate<UserTuple, uint>> all_user_tuples { get; }
|
||||
public IObservable<IReadOnlyList<AccountTuple>> on_account_tuples => on_accounts.Select(d => d.Select(kv => new AccountTuple(kv.Key, kv.Value)).ToListSorted(a => a.name));
|
||||
|
||||
public AccountTuple? get_default_account() {
|
||||
foreach (var kv in _account_map) {
|
||||
return new AccountTuple(kv.Key, kv.Value);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public uint? get_user_id(string user) => _id_for_name(user, _user_map);
|
||||
public uint? get_account_id(string account) => _id_for_name(account, _account_map);
|
||||
public void Dispose() => Disposable.dispose(ref _dispose);
|
||||
public IObservable<Update<T, TKey>> permission_filter<T, TKey>(IObservable<Update<T, TKey>> positions, Func<T, uint> get_account_id) where TKey : IEquatable<TKey> =>
|
||||
user.permissions == UserTuple.Permissions.Admin ?
|
||||
positions :
|
||||
positions.Filter(on_accounts.Select(map => new Func<T, bool>(p => map.ContainsKey(get_account_id(p)))));
|
||||
|
||||
static uint? _id_for_name(string name, IReadOnlyDictionary<uint, string> map) {
|
||||
foreach (var kv in map) {
|
||||
if (kv.Value == name)
|
||||
return kv.Key;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public IObservable<Update<T, TKey>> permission_filter<T, TKey>(IObservable<Update<T, TKey>> positions, Func<T, string> get_account_name) where TKey : IEquatable<TKey> =>
|
||||
user.permissions == UserTuple.Permissions.Admin ?
|
||||
positions :
|
||||
positions.Filter(on_accounts.Select(map => {
|
||||
var hash = new HashSet<string>(map.Values);
|
||||
return new Func<T, bool>(v => hash.Contains(get_account_name(v)));
|
||||
}));
|
||||
|
||||
public AccountTuple? get_default_account() =>
|
||||
_account_map.Select(kv => new AccountTuple(kv.Key, kv.Value)).TryFirst();
|
||||
|
||||
public void Dispose() =>
|
||||
Disposable.dispose(ref _dispose);
|
||||
}
|
||||
}
|
||||
@@ -70,7 +70,6 @@ namespace mbts.ui.shell
|
||||
{
|
||||
Log.Gen.info("Application.OnExit");
|
||||
if (_runtime != null) _runtime.Dispose();
|
||||
utils.BTSNativeMethods.finit_spark_lib();
|
||||
base.OnExit(e);
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
@@ -3,15 +3,10 @@ using mbts;
|
||||
using mbts.config;
|
||||
using mbts.spark;
|
||||
using mbts.ui;
|
||||
using mbts.ui.shell;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
|
||||
@@ -23,8 +18,8 @@ namespace bts.ui {
|
||||
IDisposable _dispose;
|
||||
|
||||
[ImportingConstructor]
|
||||
public AboutDaemon(IBus bus, [Import(LoginContainer.Exports.UserName)]string username) {
|
||||
_user = username;
|
||||
public AboutDaemon(IBus bus, UserTuple user) {
|
||||
_user = user.name;
|
||||
_bus = bus;
|
||||
_dispose = bus.subscribe(SparkTags.About).OnDispatcher().Subscribe(_ => show_about());
|
||||
}
|
||||
@@ -63,4 +58,4 @@ namespace bts.ui {
|
||||
Disposable.dispose(ref _dispose);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,13 +7,11 @@ using mbts.ui;
|
||||
using System;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Reactive.Linq;
|
||||
using System.Windows.Threading;
|
||||
using System.Windows;
|
||||
using System.Threading.Tasks;
|
||||
using mbts.ui.shell;
|
||||
using System.Windows;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace bts.spark
|
||||
{
|
||||
namespace bts.spark {
|
||||
[Export, Export(typeof(IShellDaemon))]
|
||||
public class ErrorReporter : IShellDaemon, IDisposable {
|
||||
readonly ErrorReportService _svc;
|
||||
@@ -21,9 +19,9 @@ namespace bts.spark
|
||||
IDisposable _dispose;
|
||||
|
||||
[ImportingConstructor]
|
||||
public ErrorReporter(ErrorReportService svc, IBus bus, [Import(LoginContainer.Exports.UserName)] string username) {
|
||||
public ErrorReporter(ErrorReportService svc, IBus bus, UserTuple user) {
|
||||
_svc = svc;
|
||||
_username = username;
|
||||
_username = user.name;
|
||||
_dispose = bus.subscribe(SparkTags.Support).OnDispatcher().Subscribe(msg => show_support_window(msg, "Report a problem"));
|
||||
}
|
||||
|
||||
@@ -48,6 +46,45 @@ namespace bts.spark
|
||||
ErrorMessage = message,
|
||||
});
|
||||
}
|
||||
public async Task report_silently(string contact, string description, string userdata) {
|
||||
var request = append_logs(new ErrorReport {
|
||||
User = _username,
|
||||
ErrorMessage = description,
|
||||
UserDescription = userdata,
|
||||
Contact = contact
|
||||
}.immutable());
|
||||
var reply = await _svc.send_report_async(request);
|
||||
}
|
||||
|
||||
public static ErrorReportImmutable append_logs(ErrorReportImmutable src) {
|
||||
var result = src.CloneToMutable();
|
||||
|
||||
var windows_log = LogUtil.read_windows_event_log();
|
||||
if (!windows_log.IsEmpty) {
|
||||
result.Files.Add(new FileData {
|
||||
Name = "Application.evtx.gz",
|
||||
Contents = windows_log
|
||||
});
|
||||
}
|
||||
|
||||
var (data,date) = LogUtil.read_latest_crash_dump();
|
||||
if (!data.IsEmpty) {
|
||||
result.Files.Add(new FileData {
|
||||
Name = $"spark-{date.ToString("s")}.dmp.gz",
|
||||
Contents = data
|
||||
});
|
||||
}
|
||||
|
||||
var spark_log = LogUtil.read_logs_compressed();
|
||||
if (!spark_log.IsEmpty) {
|
||||
result.Files.Add(new FileData {
|
||||
Name = "log.gz",
|
||||
Contents = spark_log
|
||||
});
|
||||
}
|
||||
return result.immutable();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class ErrorReporterExtensions {
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
using bts.api;
|
||||
using bts.shell;
|
||||
using mbts;
|
||||
using mbts.persist;
|
||||
using mbts.spark;
|
||||
using mbts.ui;
|
||||
using mbts.ui.spark;
|
||||
using mbts.ui.utilities;
|
||||
using System;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Linq;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Reactive.Linq;
|
||||
using System.Windows;
|
||||
using Disposable = mbts.Disposable;
|
||||
|
||||
namespace bts {
|
||||
[Export(typeof(IShellDaemon))]
|
||||
class GlobalAlertsDaemon : IShellDaemon, IDisposable {
|
||||
const string
|
||||
// used for logging/diagnostic purposes
|
||||
_window_name = "Global Alerts Dialog",
|
||||
// actual window title
|
||||
_window_title = "Alerts";
|
||||
|
||||
readonly ThreadedWindowLauncher _launcher;
|
||||
readonly UserSettingsHub _hub;
|
||||
readonly IBus _bus;
|
||||
readonly INotificationService _notification_service;
|
||||
IDisposable _dispose;
|
||||
|
||||
[ImportingConstructor]
|
||||
public GlobalAlertsDaemon(IBus bus, UserSettingsHub hub, INotificationService notification_service) {
|
||||
_bus = bus;
|
||||
_hub = hub;
|
||||
_notification_service = notification_service;
|
||||
_launcher = new ThreadedWindowLauncher(_window_name);
|
||||
_dispose = Disposable.Create(
|
||||
bus.subscribe(SparkTags.ShowGlobalAlertsTag)
|
||||
.Subscribe(_ => _launcher.show(_view_factory)),
|
||||
_hub.subscribe_default_settings()
|
||||
.SubscribeEach(s => new CompositeDisposable(
|
||||
s.alerts.trade_alerts.Where(t => t.is_enabled).Select(
|
||||
a => _notification_service.link_to_trades(
|
||||
a.predicate.security_criteria, a.predicate.create(), a.sound)))));
|
||||
}
|
||||
|
||||
Window _view_factory() {
|
||||
var vm = new GlobalAlertsVM();
|
||||
vm.load_from(_hub.current.alerts);
|
||||
vm.request_commit += commit;
|
||||
var sec_sub = _bus.subscribe(SparkTags.SecuritiesTag).OnDispatcher().Subscribe(m => vm.security_map = m);
|
||||
var win = new GlobalAlertsDialog {
|
||||
Title = "Alerts",
|
||||
DataContext = vm
|
||||
};
|
||||
win.Closed += (s, e) => Disposable.dispose(ref sec_sub);
|
||||
return win;
|
||||
void commit() {
|
||||
var s = _hub.current.with(alerts: vm.create());
|
||||
_hub.save_default(s).ignore();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose() =>
|
||||
Disposable.dispose(ref _dispose);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using bts.api;
|
||||
using bts.api.synthetic;
|
||||
using bts.md;
|
||||
using mbts;
|
||||
using mbts.co2;
|
||||
using mbts.spark;
|
||||
@@ -7,15 +8,10 @@ using mbts.ui;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Linq;
|
||||
using SecurityKey = System.UInt32;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Threading;
|
||||
using bts.api.user;
|
||||
using bts.md;
|
||||
using mbts.ui.shell;
|
||||
|
||||
namespace bts {
|
||||
[Export(typeof(IInitializable))]
|
||||
@@ -25,17 +21,21 @@ namespace bts {
|
||||
readonly Lazy<SyntheticSecurityService> _ss;
|
||||
readonly Dictionary<SecurityKey, SecurityMD> _deleted_synthetics = new Dictionary<SecurityKey, SecurityMD>();
|
||||
|
||||
static uint get_naggle() => mbts.config.Configuration.get<md.RelayOptions>().naggle_ms;
|
||||
|
||||
[ImportingConstructor]
|
||||
public MDDaemon(Lazy<IBus> bus, Lazy<AuthTokenImmutable> token, Lazy<SyntheticSecurityService> ss, [Import(LoginContainer.Exports.UserID)]uint user_id) :
|
||||
base(get_naggle(), MDSourceOptions.DeferInit, user_id) {
|
||||
public MDDaemon(Lazy<IBus> bus, Lazy<AuthTokenImmutable> token, Lazy<SyntheticSecurityService> ss, UserTuple user)
|
||||
: base(mbts.config.Configuration.get<md.RelayOptions>().naggle_ms, MDSourceOptions.DeferInit, user) {
|
||||
_bus = bus;
|
||||
_token = token;
|
||||
_ss = ss;
|
||||
_ss = ss;
|
||||
}
|
||||
|
||||
override public void initialize() {
|
||||
public int priority => 55;
|
||||
|
||||
[Export]
|
||||
MDConsumer consumer => _consumer;
|
||||
IBus bus => _bus.Value;
|
||||
|
||||
public override void initialize() {
|
||||
_relay.set_token(_token.Value);
|
||||
_dispose.Add(
|
||||
_ss.Value.subscribei_metadata()
|
||||
@@ -60,16 +60,8 @@ namespace bts {
|
||||
// Post full dictionary of syntheics here
|
||||
bus.post(SparkTags.SyntheticstrategiesTag, t);
|
||||
}));
|
||||
_dispose.Add( this.on_securities.Subscribe( (md) => {
|
||||
bus.post(SparkTags.SecuritiesTag, md);
|
||||
}));
|
||||
_dispose.Add(on_securities.Subscribe(md => bus.post(SparkTags.SecuritiesTag, md)));
|
||||
Task.Run(run);
|
||||
}
|
||||
|
||||
[Export]
|
||||
MDConsumer consumer => _consumer;
|
||||
|
||||
public int priority => 55;
|
||||
IBus bus => _bus.Value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.ComponentModel.Composition;
|
||||
using mbts.ui;
|
||||
using mbts;
|
||||
using Newtonsoft.Json;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace bts.spark {
|
||||
[Export(typeof(IShellDaemon))]
|
||||
class OopsDaemon : IShellDaemon, IDisposable {
|
||||
[ImportingConstructor]
|
||||
public OopsDaemon(ErrorReporter e) {
|
||||
var pid = get_pid();
|
||||
if (pid.HasValue) {
|
||||
handle_unclean_shutdown(e, pid.Value);
|
||||
}
|
||||
save_pid();
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
clear_pid();
|
||||
}
|
||||
|
||||
void handle_unclean_shutdown(ErrorReporter e, int oldpid) {
|
||||
string extra = "";
|
||||
try {
|
||||
var conf = mbts.config.Configuration.get<bts.config.System>();
|
||||
extra = JsonConvert.SerializeObject(conf, Formatting.Indented);
|
||||
}
|
||||
catch { }
|
||||
Task.Run(() => e.report_silently(
|
||||
$"Host: {Environment.MachineName}",
|
||||
$"pid: {oldpid}\n{extra}",
|
||||
"Automated crash report")
|
||||
);
|
||||
}
|
||||
|
||||
const string _subkey = @"Software\BTS";
|
||||
private void save_pid() {
|
||||
using (var key = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(_subkey)) {
|
||||
key.SetValue("pid", System.Diagnostics.Process.GetCurrentProcess().Id, Microsoft.Win32.RegistryValueKind.DWord);
|
||||
}
|
||||
}
|
||||
private void clear_pid() {
|
||||
using (var key = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(_subkey)) {
|
||||
key.DeleteValue("pid",false);
|
||||
}
|
||||
}
|
||||
private int? get_pid() {
|
||||
using (var key = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(_subkey)) {
|
||||
return key.GetValue("pid") as int?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,11 @@ namespace bts.shell {
|
||||
void _show_order_window(Window window) {
|
||||
foreach (var kv in AlgoStudioModelUtils.get_dynamic_resources(_model.algo_model.ui_configuration))
|
||||
window.Resources[kv.Key] = kv.Value;
|
||||
// the dynamic algo 'SecurityKey' template has a ContractPickerPopup that expects the security map to be available as a DynamicResource.
|
||||
var sub = _bus.subscribe(SparkTags.SecuritiesTag)
|
||||
.OnDispatcher()
|
||||
.Subscribe(sec_map => window.Resources[ResourceKeys.Securities] = sec_map);
|
||||
window.Closed += (s, e) => Disposable.dispose(ref sub);
|
||||
window.Show(-200, -160, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,17 +3,13 @@ using bts.metrics;
|
||||
using mbts;
|
||||
using mbts.config;
|
||||
using mbts.ui;
|
||||
using mbts.ui.shell;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Linq;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace bts.perf {
|
||||
|
||||
[Export, Export(typeof(IShellDaemon))]
|
||||
class ShellLatencyDaemon : IShellDaemon, IDisposable {
|
||||
readonly ShellLatencyService _service;
|
||||
@@ -24,10 +20,10 @@ namespace bts.perf {
|
||||
Ping _pinger = new Ping();
|
||||
|
||||
[ImportingConstructor]
|
||||
public ShellLatencyDaemon(ShellLatencyService service, [Import(LoginContainer.Exports.UserName)] string user) {
|
||||
public ShellLatencyDaemon(ShellLatencyService service, UserTuple user) {
|
||||
_service = service;
|
||||
_version = Configuration.get<bts.config.System>().version;
|
||||
_username = user;
|
||||
_username = user.name;
|
||||
_hostname = Environment.MachineName;
|
||||
|
||||
_forever_ping_host(_pinger);
|
||||
@@ -105,4 +101,4 @@ namespace bts.perf {
|
||||
Disposable.dispose(ref _subs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,14 +40,18 @@ namespace mbts.ui {
|
||||
EditDocumentAltGeometryKey = nameof(EditDocumentAltGeometryKey),
|
||||
EditDocumentGeometryKey = nameof(EditDocumentGeometryKey),
|
||||
GearGeometryKey = nameof(GearGeometryKey),
|
||||
HornGeometryKey = nameof(HornGeometryKey),
|
||||
KeyGeometryKey = nameof(KeyGeometryKey),
|
||||
LetterAKey = nameof(LetterAKey),
|
||||
LetterDKey = nameof(LetterDKey),
|
||||
OrdersGeometryKey = nameof(OrdersGeometryKey),
|
||||
PauseGeometryKey = nameof(PauseGeometryKey),
|
||||
PaymentGeometryKey = nameof(PaymentGeometryKey),
|
||||
PencilGeometryKey = nameof(PencilGeometryKey),
|
||||
PlayGeometryKey = nameof(PlayGeometryKey),
|
||||
ProhibitedGeometryKey = nameof(ProhibitedGeometryKey),
|
||||
RubberStampGeometryKey = nameof(RubberStampGeometryKey),
|
||||
SpeakerGeometryKey = nameof(SpeakerGeometryKey),
|
||||
StarGeometryKey = nameof(StarGeometryKey),
|
||||
ToolsGeometryKey = nameof(ToolsGeometryKey),
|
||||
TrashGeometryKey = nameof(TrashGeometryKey),
|
||||
@@ -149,7 +153,7 @@ namespace mbts.ui {
|
||||
public static ImageSource CheckMark => create_icon(CheckMarkGeometryKey);
|
||||
public static ImageSource Clock { get { return load_resource_and_freeze("Clock"); } }
|
||||
public static ImageSource CopyWF => create_icon(CopyWFGeometryKey);
|
||||
public static ImageSource DataEdit => create_icon(DataEditGeometryKey, Brushes.White, new Pen(Brushes.Black, 1).frozen());
|
||||
public static ImageSource DataEdit => create_icon(DataEditGeometryKey);
|
||||
public static ImageSource Defrag { get { return load_resource_and_freeze("Defrag"); } }
|
||||
public static ImageSource DetachAlgos => create_icon_and_rotate(DetachAlgosKey, Brushes.Red);
|
||||
public static ImageSource Disk => create_icon(DiskGeometryKey);
|
||||
@@ -168,14 +172,19 @@ namespace mbts.ui {
|
||||
public static ImageSource FilterActive { get { return load_resource_and_freeze("FilterActive"); } }
|
||||
public static ImageSource FilterError { get { return load_resource_and_freeze("FilterError"); } }
|
||||
public static ImageSource Gear => create_icon(GearGeometryKey);
|
||||
public static ImageSource Horn => create_icon(HornGeometryKey);
|
||||
public static ImageSource Import => load_resource_and_freeze("Import");
|
||||
public static ImageSource Key => create_icon(KeyGeometryKey);
|
||||
public static ImageSource Knight { get { return load_resource_and_freeze("Knight"); } }
|
||||
public static ImageSource Pause => create_icon(PauseGeometryKey);
|
||||
public static ImageSource Payment => create_icon(PaymentGeometryKey);
|
||||
public static ImageSource Pencil => create_icon(PencilGeometryKey);
|
||||
public static ImageSource Play => create_icon(PlayGeometryKey);
|
||||
public static ImageSource Prohibited => create_icon(ProhibitedGeometryKey);
|
||||
public static ImageSource RubberStamp => create_icon(RubberStampGeometryKey);
|
||||
public static ImageSource RedoCircular => create_icon(UndoCircularGeometryKey, Brushes.Black, null, new ScaleTransform(-1, 1));
|
||||
public static ImageSource Spawn { get { return load_resource_and_freeze("Spawn"); } }
|
||||
public static ImageSource Speaker => create_icon(SpeakerGeometryKey);
|
||||
public static ImageSource Star => create_icon(StarGeometryKey);
|
||||
public static ImageSource Target { get { return load_resource_and_freeze("Target"); } }
|
||||
public static ImageSource Tetris { get { return load_resource_and_freeze("Tetris"); } }
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:mbts="clr-namespace:mbts.ui"
|
||||
xmlns:sys="clr-namespace:System;assembly=mscorlib"
|
||||
>
|
||||
@@ -18,9 +18,7 @@
|
||||
Ttile: Add free icon
|
||||
Credit: Icon made by Gregor Cresnar from www.flaticon.com-->
|
||||
<sys:String x:Key="{x:Static mbts:Icons.AddBoxesGeometryKey}">
|
||||
M393,480.3c0-5-4.1-9.1-9.1-9.1H18.2V105.5c0-5-4.1-9.1-9.1-9.1S0,100.5,0,105.5v374.8c0,5,4.1,9.1,9.1,9.1h374.8 C388.9,489.4,393,485.3,393,480.3z
|
||||
M373.9,187.5H302v-71.9c0-5-4.1-9.1-9.1-9.1s-9.1,4.1-9.1,9.1v71.9h-71.9c-5,0-9.1,4.1-9.1,9.1s4.1,9.1,9.1,9.1h71.9v71.9 c0,5,4.1,9.1,9.1,9.1s9.1-4.1,9.1-9.1v-71.9h71.9c5,0,9.1-4.1,9.1-9.1C382.9,191.5,378.9,187.5,373.9,187.5z
|
||||
M105.5,393h374.8c5,0,9.1-4.1,9.1-9.1V9.1c0-5-4.1-9.1-9.1-9.1H105.5c-5,0-9.1,4.1-9.1,9.1v374.8 C96.4,388.9,100.5,393,105.5,393z M114.5,18.2h356.7v356.7H114.5V18.2z
|
||||
M 87.5 10 C 80.313542 10 74.400391 15.913151 74.400391 23.099609 V 397.90039 C 74.400391 405.08685 80.313541 411 87.5 411 h 374.80078 c 7.18646 0 13.09961 -5.91315 13.09961 -13.09961 V 23.099609 C 475.40039 15.913151 469.48724 10 462.30078 10 Z m 13 26.199219 H 449.19922 V 384.90039 H 100.5 Z M 21.099609 76.400391 C 13.912943 76.400391 8 82.313333 8 89.5 v 374.80078 c 0 7.18667 5.912943 13.09961 13.099609 13.09961 H 395.90039 c 7.18667 0 13.09961 -5.91294 13.09961 -13.09961 0 -7.18667 -5.91294 -13.10156 -13.09961 -13.10156 H 34.199219 V 89.5 c 0 -7.186667 -5.912943 -13.099609 -13.09961 -13.099609 z M 274.90039 116.5 c -7.18667 0 -13.09961 5.91294 -13.09961 13.09961 V 197.5 h -67.90039 c -7.18667 0 -13.09961 5.91294 -13.09961 13.09961 0 7.18667 5.91294 13.09961 13.09961 13.09961 h 67.90039 v 67.90039 c 0 7.18667 5.91294 13.09961 13.09961 13.09961 7.18667 0 13.09961 -5.91294 13.09961 -13.09961 v -67.90039 h 67.90039 c 7.18667 0 13.09961 -5.91294 13.09961 -13.09961 v -0.0391 -0.0391 C 368.85982 203.37217 363.03372 197.5 355.90039 197.5 H 288 V 129.59961 C 288 122.41294 282.08706 116.5 274.90039 116.5 Z
|
||||
</sys:String>
|
||||
|
||||
<!--File (the icon is free to use if we include this information in our credit section)
|
||||
@@ -116,7 +114,7 @@
|
||||
</sys:String>
|
||||
|
||||
<sys:String x:Key="{x:Static mbts:Icons.DataEditGeometryKey}">
|
||||
M17.997977,17.396268C18.197928,17.396268,18.297904,17.496276,18.497975,17.596284L19.497972,18.295283C19.99797,18.595292,20.697919,19.195308,21.197917,19.495299L22.196937,20.195323C22.696935,20.495315,22.596959,20.995322,22.096961,21.195338L20.997966,21.695346C20.497968,21.89434,19.597947,22.294355,19.097949,22.494355L17.997977,22.994363C17.497979,23.194362,17.097957,22.894355,17.197932,22.394347L17.297908,21.195338C17.398005,20.595323,17.497979,19.695315,17.497979,19.195308L17.597955,17.995277C17.497979,17.695283,17.69793,17.396268,17.997977,17.396268z M1.799981,13.597213L19.697923,13.597213 17.997977,15.896244C17.797906,16.096259 17.69793,16.396253 17.69793,16.69626 17.197932,16.796268 16.79791,17.296275 16.697934,17.895284L16.597959,19.195308 1.799981,19.195308C0.79998477,19.195308,0,18.395291,0,17.396268L0,15.396237C0,14.396221,0.79998477,13.597213,1.799981,13.597213z M1.799981,6.7981106L21.796914,6.7981106C22.696935,6.7981106,23.49698,7.498118,23.596955,8.3981257L20.697919,12.397197 1.799981,12.397197C0.79998477,12.397197,0,11.597181,0,10.597165L0,8.5981418C0,7.598126,0.79998477,6.7981106,1.799981,6.7981106z M27.796891,4.3990708C27.996963,4.3990708,28.096938,4.3990708,28.296889,4.5990711L31.695924,7.0981179C31.995851,7.3981105,32.095948,7.7981258,31.895875,8.0981341L23.296908,19.795308C23.096957,20.095315,22.596959,20.195323,22.196937,19.895314L18.797902,17.396268C18.497975,17.096274,18.398002,16.69626,18.597951,16.396253L27.196918,4.6990786C27.396869,4.4990784,27.59694,4.3990708,27.796891,4.3990708z M1.799981,0L21.796914,0C22.79691,4.9549271E-08,23.596955,0.8000156,23.596955,1.800031L23.596955,3.7990554C23.596955,4.7990709,22.79691,5.5990864,21.796914,5.5990864L1.799981,5.5990864C0.79998477,5.4990941,0,4.6990786,0,3.6990629L0,1.7000236C0,0.8000156,0.79998477,4.9549271E-08,1.799981,0z
|
||||
M 22.589844 14.470703 H 0.82421875 C 0.36896661 14.470586 -1.1747368e-4 14.83967 0 15.294922 v 4.669922 c -1.1747368e-4 0.455252 0.36896661 0.824336 0.82421875 0.824218 H 16.940231 l 0.425003 -1.09375 0.554688 -0.554687 H 1.6484375 V 16.119141 H 20.941406 Z M 27.462891 9.5976562 V 8.0742188 A 0.8240064 0.8240064 0 0 0 26.638672 7.25 H 0.82421875 A 0.8240064 0.8240064 0 0 0 0 8.0742188 v 4.6699222 a 0.8240064 0.8240064 0 0 0 0.82421875 0.824218 H 23.492188 l 1.648437 -1.648437 H 1.6484375 V 8.8984375 H 25.814453 V 11.246094 Z M 0.82421878 2.736881e-8 A 0.8240064 0.8240064 0 0 0 2.7433281e-8 0.82421879 V 5.4941406 A 0.8240064 0.8240064 0 0 0 0.82421878 6.3183594 H 26.638672 A 0.8240064 0.8240064 0 0 0 27.46289 5.4941406 V 0.82421879 A 0.8240064 0.8240064 0 0 0 26.638672 2.736881e-8 Z M 1.6484375 1.6484375 H 25.814453 V 4.6699219 H 1.6484375 Z M 31.628051 7.2558423 19.165575 19.718635 23.70324 24.256618 36.166032 11.793823 Z m -0.0013 3.5965607 0.941422 0.94142 -8.866233 8.866232 -0.94142 -0.94142 z m -13.240122 9.708458 -1.636234 6.110706 6.109329 -1.637606 z
|
||||
</sys:String>
|
||||
<sys:String x:Key="{x:Static mbts:Icons.DiskGeometryKey}">
|
||||
M403.213,20H0v472h512V128.787L403.213,20z M131,50h180v100h10h20h10V50h30v130H131V50z M381,462H131V315
|
||||
@@ -274,10 +272,22 @@
|
||||
M16.000015,9.6000061C12.500012,9.6000061 9.5999844,12.5 9.5999844,16 9.5999844,19.5 12.500012,22.399994 16.000015,22.399994 19.500019,22.399994 22.400015,19.5 22.400015,16 22.400015,12.5 19.500019,9.6000061 16.000015,9.6000061z M14.199995,0L17.800005,0C18.199999,0,18.599993,0.29998779,18.599993,0.79998779L18.599993,4.7999878C19.900013,5.1000061,21.000019,5.6000061,22.099997,6.2999878L25.000023,3.3999939C25.099999,3.2999878 25.300011,3.1999817 25.500025,3.1999817 25.700007,3.1999817 25.900019,3.2999878 26.000025,3.3999939L28.600033,6C28.900021,6.2999878,28.900021,6.7999878,28.600033,7.1000061L25.700007,10C26.400019,11.100006,26.900019,12.299988,27.200007,13.5L31.20001,13.5C31.600037,13.5,31.999998,13.799988,31.999998,14.299988L31.999998,17.899994C31.999998,18.299988,31.700012,18.699982,31.20001,18.699982L27.200007,18.699982C26.900019,20,26.400019,21.100006,25.700007,22.199982L28.600033,25.100006C28.700009,25.199982 28.799984,25.399994 28.799984,25.600006 28.799984,25.799988 28.700009,26 28.600033,26.100006L26.000025,28.600006C25.900019,28.699982 25.700007,28.799988 25.500025,28.799988 25.300011,28.799988 25.099999,28.699982 25.000023,28.600006L22.099997,25.699982C21.000019,26.399994,19.800007,26.899994,18.599993,27.199982L18.599993,31.199982C18.599993,31.600006,18.300005,32,17.800005,32L14.199995,32C13.8,32,13.400006,31.699982,13.400006,31.199982L13.400006,27.199982C12.099987,26.899994,11.000011,26.399994,9.9000027,25.699982L7.0000064,28.600006C6.9000003,28.699982 6.6999881,28.799988 6.5000059,28.799988 6.2999937,28.799988 6.099981,28.699982 6.0000054,28.600006L3.3999967,26C3.0999784,25.699982,3.0999784,25.199982,3.3999967,24.899994L6.2999937,22C5.5999805,20.899994,5.0999801,19.699982,4.7999923,18.5L0.79998828,18.5C0.39999409,18.5,-1.933513E-07,18.199982,0,17.699982L0,14.100006C-1.933513E-07,13.699982,0.2999879,13.299988,0.79998828,13.299988L4.7999923,13.299988C5.0999801,12,5.5999805,10.899994,6.2999937,9.7999878L3.3999967,7C3.2999908,6.8999939 3.1999845,6.6999817 3.1999845,6.5 3.1999845,6.2999878 3.2999908,6.1000061 3.3999967,6L6.0000054,3.3999939C6.099981,3.2999878 6.2999937,3.1999817 6.5000059,3.1999817 6.6999881,3.1999817 6.9000003,3.2999878 7.0000064,3.3999939L9.9000027,6.2999878C11.000011,5.6000061,12.199993,5.1000061,13.400006,4.7999878L13.400006,0.79998779C13.400006,0.29998779,13.8,0,14.199995,0z
|
||||
</sys:String>
|
||||
|
||||
<sys:String x:Key="{x:Static mbts:Icons.HornGeometryKey}">
|
||||
M4.0499969,7.0870913C2.9519978,7.0870913 2.0249984,8.4780906 2.0249987,10.125091 2.0249984,11.771091 2.9519978,13.162091 4.0499969,13.162091 5.1479961,13.162091 6.0749954,11.771091 6.0749955,10.125091 6.0749954,8.4780906 5.1479961,7.0870913 4.0499969,7.0870913z M29.975016,3.316155C23.883831,8.2016557,11.829888,8.9691842,8.1184387,9.0896781L8.0151367,9.0928462 8.0175586,9.1059306C8.0716033,9.4352315 8.0999939,9.7760909 8.0999942,10.125091 8.0999939,10.473966 8.0716033,10.814716 8.0175586,11.143921L8.0098858,11.185364 8.193316,11.195448C12.163719,11.420399,23.994581,12.458921,29.975016,17.005057z M31.176758,0.00019051835C31.280359,-0.0022594665 31.391857,0.01889403 31.514975,0.065146674 31.908983,0.21413228 31.999985,0.59114302 31.999985,1.0121596L31.999985,19.236969C31.999985,19.653958 31.913988,20.028956 31.525991,20.179955 31.405998,20.226952 31.450981,20.250023 31.32699,20.250023 31.050991,20.250023 30.778992,20.13601 30.583986,19.925928 25.229074,14.140572 9.6001122,13.269665 7.2865356,13.172559L7.2813506,13.172345 7.1739591,13.343056C6.4304952,14.468533 5.3060585,15.187091 4.0499969,15.187091 1.8169985,15.187091 0,12.916091 0,10.125091 0,7.3330911 1.8169985,5.0620912 4.0499969,5.0620912 5.3060585,5.0620912 6.4304952,5.78065 7.1739591,6.9063042L7.2852713,7.0832756 7.3087114,7.0828188C9.6077337,7.036146 25.141474,6.4939421 30.567997,0.34315929 30.75913,0.12521249 30.948835,0.005580858 31.176758,0.00019051835z
|
||||
</sys:String>
|
||||
|
||||
<sys:String x:Key="{x:Static mbts:Icons.KeyGeometryKey}">
|
||||
M22.399981,2.4000006C22.099982,2.4000006 21.899982,2.5 21.599982,2.6999998 21.199983,3.1000004 21.199983,3.8000002 21.599982,4.2000003L26.199979,8.9000001C26.599978,9.3000002 27.299977,9.3000002 27.699977,8.9000001 28.099977,8.5000002 28.099977,7.8000002 27.699977,7.4000006L23.099981,2.6999998C22.899981,2.5,22.699981,2.4000006,22.399981,2.4000006z M21.499982,0C22.299982,0,23.199981,0.30000019,23.79998,0.90000057L29.299976,6.4000001C30.599975,7.7000003,30.599975,9.7000003,29.299976,11L22.599981,17.7C21.299983,19,19.299984,19,17.999985,17.7L17.299985,17 12.699989,21.6 10.399991,20.900001 10.899991,23.400001 8.4999928,22.8 8.9999924,25.5 6.2999945,25.1 6.7999945,27.6 4.2999964,27 4.7999954,29.6 2.4999971,32 0,26.6 13.499989,13.1 16.999986,16.6 12.699989,12.3C11.399991,11,11.399991,9.0000002,12.699989,7.7000003L19.399984,1C19.899983,0.30000019,20.699983,0,21.499982,0z
|
||||
</sys:String>
|
||||
|
||||
<sys:String x:Key="{x:Static mbts:Icons.OrdersGeometryKey}">
|
||||
M50.14375,33.389126C50.416863,33.394688,50.653496,33.587773,50.705998,33.864617L50.015995,45.114388C49.810295,46.291462,49.130394,45.097489,49.130394,45.097489L47.65659,42.640538C42.747776,49.635197 34.633152,54.221001 25.433924,54.221001 14.884193,54.221001 5.7437552,48.204125 1.2449617,39.419205 0.80087067,38.552021 0.21358696,37.705738 0.052086769,36.736958 -0.49735315,33.490925 3.4507786,32.901036 4.8049124,34.432404 5.3674143,35.067692 6.034036,36.16407 6.5079177,37.026051 10.106778,43.799416 17.2321,48.413819 25.433924,48.413819 32.656544,48.413819 39.026364,44.826695 42.903977,39.351506L40.229367,38.854115C40.229367,38.854115,38.677464,38.647118,39.742466,37.996033L50.024895,33.398526C50.064972,33.391365,50.104733,33.388333,50.14375,33.389126z M23.030291,9.0310004L27.889918,9.0310004 27.889918,13.028299C30.539786,13.205498,32.324932,13.958096,33.464161,14.528294L33.964176,14.775793 32.417435,20.038878 31.706417,19.68068C30.579987,19.11958 28.839241,18.244583 26.149073,18.244583 24.006916,18.244583 22.723183,19.122181 22.723183,20.590876 22.723183,21.894272 23.943314,22.804369 27.551308,24.187165 32.706444,26.124659 34.911,28.702853 34.911,32.817341 34.911,36.892929 32.090527,40.05172 27.673611,40.989117L27.673611,45.540001 22.767485,45.540001 22.767485,41.330414C20.252919,41.155815,17.695551,40.424118,16.101811,39.404721L15.683999,39.137619 17.221739,33.731438 17.969059,34.180634C19.088988,34.851235 21.402748,35.97873 24.340325,35.97873 26.734886,35.97873 28.276728,34.921635 28.276728,33.291336 28.276728,31.986641 27.547409,30.853846 23.986016,29.57255 20.083815,28.144253 16.095511,26.04406 16.095511,21.239174 16.095511,17.280985 18.737379,14.291395 23.030291,13.329098z M25.268765,0C35.819447,2.7347414E-07 44.961449,6.0155495 49.458798,14.804573 49.902695,15.669173 50.490094,16.516972 50.651287,17.48427 51.198281,20.734265 47.255726,21.318962 45.901341,19.789065 45.336346,19.153567 44.669552,18.051968 44.19566,17.19517 40.5957,10.421881 33.473275,5.8072398 25.268765,5.8072393 18.047545,5.8072398 11.678013,9.3918336 7.8003562,14.867073L10.474627,15.367072C10.474627,15.367072,12.026909,15.574172,10.962921,16.223872L0.67933281,20.826762C0.36037083,20.880062,0.057029126,20.669165,0.00099972012,20.354063L0.69093342,9.1118043C0.89552094,7.9296158,1.5738537,9.124924,1.5738539,9.124924L3.0452772,11.583379C7.9566038,4.584462,16.073666,2.7347414E-07,25.268765,0z
|
||||
</sys:String>
|
||||
|
||||
<sys:String x:Key="{x:Static mbts:Icons.PauseGeometryKey}">
|
||||
M17.94,0L29.150001,0 29.150001,32 17.94,32z M0,0L11.210002,0 11.210002,32 0,32z
|
||||
</sys:String>
|
||||
|
||||
<sys:String x:Key="{x:Static mbts:Icons.PaymentGeometryKey}">
|
||||
M28.000001,6.0000026L28.000001,15 6.0010006,15 6.0010006,17.000003 30.001,17.000003 30.001,6.0000026z M14.231,2.9540056L14.979999,2.9540056 14.979999,3.987005C15.704998,4.009005,16.200997,4.178005,16.550998,4.3600049L16.248998,5.0620046C15.994998,4.9340047 15.499998,4.7010047 14.725999,4.7010047 13.796,4.7010047 13.445001,5.1900046 13.445001,5.6160046 13.445001,6.1710043 13.893,6.4470041 14.943999,6.8310037 16.187998,7.2780037 16.816998,7.8320036 16.816998,8.7800031 16.816998,9.6210027 16.151998,10.409003 14.907999,10.591002L14.907999,11.698002 14.146,11.698002 14.146,10.622003C13.445001,10.611002,12.720001,10.420002,12.297002,10.154003L12.587001,9.4400029C13.022001,9.696003 13.651,9.8980026 14.328,9.8980026 15.185999,9.8980026 15.765998,9.4620028 15.765998,8.8540034 15.765998,8.2680035 15.293999,7.9060035 14.4,7.5870035 13.167001,7.1610038 12.406001,6.6710041 12.406001,5.7440041 12.406001,4.8600047 13.119,4.189005 14.231,4.0290052z M2,2.0000002L2,13 26.000001,13 26.000001,2.0000002z M0,0L28.000001,0 28.000001,4.0000031 32.001,4.0000031 32.001,19.000003 4.0010006,19.000003 4.0010006,15 0,15z
|
||||
</sys:String>
|
||||
@@ -327,6 +337,11 @@
|
||||
M33.5,4h-6v10h6V4z M31.5,12h-2V6h2V12z
|
||||
</sys:String>
|
||||
</x:Array>
|
||||
|
||||
<sys:String x:Key="{x:Static mbts:Icons.SpeakerGeometryKey}">
|
||||
M18,12.839666L18,19.159448 18.029955,19.131576C18.848108,18.314159 19.332083,17.192702 19.332083,15.999873 19.332083,14.806357 18.848108,13.684685 18.029955,12.867527z M21.738388,4.748316C21.868353,4.7515661 21.999973,4.7804414 22.126221,4.8376924 26.511095,6.8177201 29.344013,11.199782 29.344013,15.999849 29.344013,20.799915 26.511095,25.181977 22.126221,27.162004 21.992224,27.223004 21.853228,27.251006 21.715233,27.251006 21.333244,27.251006 20.970255,27.032003 20.803259,26.662997 20.575266,26.15899 20.799259,25.566981 21.302244,25.339978 24.973139,23.681956 27.34407,20.015905 27.34407,15.999849 27.34407,11.983792 24.973139,8.3177406 21.302244,6.6597177 20.799259,6.4327146 20.575266,5.8407065 20.803259,5.3366992 20.973503,4.9594442 21.348494,4.7385656 21.738388,4.748316z M16,3.1854247L6.6530151,11.257323C6.4719848,11.414303,6.2399902,11.500301,6,11.500301L1.9999998,11.500301 1.9999998,21.500148 6,21.500148C6.2219848,21.500148,6.4370117,21.573144,6.6110229,21.709129L16,28.964023z M17.000252,1.186163E-08C17.141373,-2.1778678E-05 17.283264,0.02997845 17.416016,0.091477852 17.770996,0.25450047 18,0.60843792 18,1.0004608L18,10.368904 18.170259,10.465408C20.111607,11.612996 21.331976,13.716092 21.331976,15.999873 21.331976,18.282748 20.111607,20.38576 18.170259,21.53334L18,21.629842 18,31.000003C18,31.382016 17.78302,31.728995 17.440002,31.896962 17.301025,31.965991 17.150024,31.99999 17,31.99999 16.78302,31.99999 16.567017,31.929982 16.388977,31.791007L5.65802,23.500117 0.99999966,23.500117C0.44702145,23.500117,-3.9348969E-08,23.053104,3.5527137E-15,22.500133L3.5527137E-15,10.500316C-3.9348969E-08,9.9473459,0.44702145,9.5003311,0.99999966,9.5003311L5.6279907,9.5003311 16.346985,0.24345344C16.531998,0.083467316,16.765053,3.6392792E-05,17.000252,1.186163E-08z
|
||||
</sys:String>
|
||||
|
||||
<sys:String x:Key="{x:Static mbts:Icons.StarGeometryKey}">
|
||||
M1540.22,2082.07L1546.95,2102.78 1568.73,2102.78 1551.11,2115.58 1557.84,2136.29 1540.22,2123.49 1522.6,2136.29 1529.33,2115.58 1511.71,2102.78 1533.49,2102.78 1540.22,2082.07z
|
||||
</sys:String>
|
||||
@@ -336,7 +351,7 @@
|
||||
</sys:String>
|
||||
|
||||
<sys:String x:Key="{x:Static mbts:Icons.TrashGeometryKey}">
|
||||
M0,12.568994L23.662999,12.568994 20.910989,31.999999 2.7520113,31.999999z M8.0689915,1.6269979L8.0689915,4.6679968 15.594984,4.6679968 15.594984,1.6269979z M6.4420097,0L17.221997,0 17.221997,4.6679968 23.662999,4.6679968 23.662999,8.7949938 0,8.7949938 0,4.6679968 6.4420097,4.6679968z
|
||||
M15.000001,8.0000272L17,8.0000272 17,27.000028 15.000001,27.000028z M11.000001,8.0000272L13.000001,8.0000272 13.000001,27.000028 11.000001,27.000028z M7.0000005,8.0000272L9.000001,8.0000272 9.000001,27.000028 7.0000005,27.000028z M3.0790101,5.0000274L4.9959994,29.922999 19.000006,30.000026 20.918949,5.0000274z M13.771989,1.9959999L10.198989,2.0000001C10.158989,2.025,9.9989892,2.241,9.9989892,2.6000001L9.9989892,3.0000258 13.998989,3.0000258 13.998989,2.6000001C13.998989,2.241,13.838988,2.025,13.771989,1.9959999z M10.198989,0L13.798988,0C15.031989,0,15.998989,1.142,15.998989,2.6000001L15.998989,3.0000258 23.07898,3.0000258 24,3.0000272 24,5.0000274 22.925121,5.0000274 20.995976,30.076991C20.999027,31.102992,20.100956,32.000026,18.999029,32.000026L4.9990512,32.000026C3.8960255,32.000026,2.9990543,31.102992,2.999054,30.000026L1.073059,5.0000274 0,5.0000274 0,3.0000272 0.91897895,3.0000272 7.9989887,3.0000258 7.9989887,2.6000001C7.9989887,1.142,8.9659892,0,10.198989,0z
|
||||
</sys:String>
|
||||
|
||||
<!--UndoCircular (the icon is free to use if we include this information in our credit/about section)
|
||||
@@ -396,10 +411,10 @@
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing Geometry="
|
||||
M 32.868601,3.8869994 C31.026201,3.8869996 29.534,5.3791947 29.534,7.2190399 29.534,9.0588851 31.026201,10.553 32.868601,10.553 34.7085,10.553 36.202,9.0588851 36.202,7.2190399 36.202,5.3791947 34.7085,3.8869996 32.868601,3.8869994z
|
||||
M 42.868601,3.8869994 C41.026201,3.8869996 39.534,5.3791947 39.534,7.2190399 39.534,9.0588851 41.026201,10.553 42.868601,10.553 44.7085,10.553 46.202,9.0588851 46.202,7.2190399 46.202,5.3791947 44.7085,3.8869996 42.868601,3.8869994z
|
||||
M 52.868601,3.8869994 C51.026201,3.8869996 49.534,5.3791947 49.534,7.2190399 49.534,9.0588851 51.026201,10.553 52.868601,10.553 54.7085,10.553 56.202,9.0588851 56.202,7.2190399 56.202,5.3791947 54.7085,3.8869996 52.868601,3.8869994z
|
||||
M5.2010002,14.812L5.2010002,43.573997 56.098,43.573997 56.098,14.812z
|
||||
M 32.868601,3.8869994 C31.026201,3.8869996 29.534,5.3791947 29.534,7.2190399 29.534,9.0588851 31.026201,10.553 32.868601,10.553 34.7085,10.553 36.202,9.0588851 36.202,7.2190399 36.202,5.3791947 34.7085,3.8869996 32.868601,3.8869994z
|
||||
M 42.868601,3.8869994 C41.026201,3.8869996 39.534,5.3791947 39.534,7.2190399 39.534,9.0588851 41.026201,10.553 42.868601,10.553 44.7085,10.553 46.202,9.0588851 46.202,7.2190399 46.202,5.3791947 44.7085,3.8869996 42.868601,3.8869994z
|
||||
M 52.868601,3.8869994 C51.026201,3.8869996 49.534,5.3791947 49.534,7.2190399 49.534,9.0588851 51.026201,10.553 52.868601,10.553 54.7085,10.553 56.202,9.0588851 56.202,7.2190399 56.202,5.3791947 54.7085,3.8869996 52.868601,3.8869994z
|
||||
M5.2010002,14.812L5.2010002,43.573997 56.098,43.573997 56.098,14.812z
|
||||
M0,0L63.999001,0 63.999001,48.792999 0,48.792999z">
|
||||
<GeometryDrawing.Pen>
|
||||
<Pen Thickness="1" Brush="Black" />
|
||||
@@ -415,10 +430,10 @@ M0,0L63.999001,0 63.999001,48.792999 0,48.792999z">
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing Brush="Black" Geometry="
|
||||
M 32.868601,3.8869994 C31.026201,3.8869996 29.534,5.3791947 29.534,7.2190399 29.534,9.0588851 31.026201,10.553 32.868601,10.553 34.7085,10.553 36.202,9.0588851 36.202,7.2190399 36.202,5.3791947 34.7085,3.8869996 32.868601,3.8869994z
|
||||
M 42.868601,3.8869994 C41.026201,3.8869996 39.534,5.3791947 39.534,7.2190399 39.534,9.0588851 41.026201,10.553 42.868601,10.553 44.7085,10.553 46.202,9.0588851 46.202,7.2190399 46.202,5.3791947 44.7085,3.8869996 42.868601,3.8869994z
|
||||
M 52.868601,3.8869994 C51.026201,3.8869996 49.534,5.3791947 49.534,7.2190399 49.534,9.0588851 51.026201,10.553 52.868601,10.553 54.7085,10.553 56.202,9.0588851 56.202,7.2190399 56.202,5.3791947 54.7085,3.8869996 52.868601,3.8869994z
|
||||
M5.2010002,14.812L5.2010002,43.573997 56.098,43.573997 56.098,14.812z
|
||||
M 32.868601,3.8869994 C31.026201,3.8869996 29.534,5.3791947 29.534,7.2190399 29.534,9.0588851 31.026201,10.553 32.868601,10.553 34.7085,10.553 36.202,9.0588851 36.202,7.2190399 36.202,5.3791947 34.7085,3.8869996 32.868601,3.8869994z
|
||||
M 42.868601,3.8869994 C41.026201,3.8869996 39.534,5.3791947 39.534,7.2190399 39.534,9.0588851 41.026201,10.553 42.868601,10.553 44.7085,10.553 46.202,9.0588851 46.202,7.2190399 46.202,5.3791947 44.7085,3.8869996 42.868601,3.8869994z
|
||||
M 52.868601,3.8869994 C51.026201,3.8869996 49.534,5.3791947 49.534,7.2190399 49.534,9.0588851 51.026201,10.553 52.868601,10.553 54.7085,10.553 56.202,9.0588851 56.202,7.2190399 56.202,5.3791947 54.7085,3.8869996 52.868601,3.8869994z
|
||||
M5.2010002,14.812L5.2010002,43.573997 56.098,43.573997 56.098,14.812z
|
||||
M0,0L63.999001,0 63.999001,48.792999 0,48.792999z">
|
||||
<GeometryDrawing.Pen>
|
||||
<Pen Thickness="1" Brush="Black" />
|
||||
@@ -834,7 +849,7 @@ M0,0L63.999001,0 63.999001,48.792999 0,48.792999z">
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing
|
||||
<GeometryDrawing
|
||||
Brush="Black"
|
||||
Geometry="M23,14C24.10498,14 25,14.89502 25,16 25,17.10498 24.10498,18 23,18 21.89502,18 21,17.10498 21,16 21,14.89502 21.89502,14 23,14z M16,14C17.105,14 18,14.895 18,16 18,17.105 17.105,18 16,18 14.895,18 14,17.105 14,16 14,14.895 14.895,14 16,14z M9,14C10.105,14 11,14.895 11,16 11,17.105 10.105,18 9,18 7.8950005,18 7,17.105 7,16 7,14.895 7.8950005,14 9,14z M16,2C8.2799997,2 2,8.2800002 2,16 2,23.72 8.2799997,30 16,30 23.72,30 30,23.72 30,16 30,8.2800002 23.72,2 16,2z M16,0C24.822,0 32,7.178 32,16 32,24.822 24.822,32 16,32 7.1780005,32 0,24.822 0,16 0,7.178 7.1780005,0 16,0z" />
|
||||
</DrawingGroup.Children>
|
||||
@@ -847,7 +862,7 @@ M0,0L63.999001,0 63.999001,48.792999 0,48.792999z">
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing
|
||||
<GeometryDrawing
|
||||
Brush="Black"
|
||||
Geometry="M299.152955025434,0L496.426178902388,0 268.890046089888,280.247772216797 198.190201729536,367.407897949219 199.87503144145,369.495361328125 271.502137154341,457.706451416016 498.999970406294,738 301.717621773481,738 101.234124153852,491.008697509766 99.5304498374462,488.936553955078 98.6409082114697,490.003173828125 0,368.488952636719 98.6409082114697,246.945526123047z" />
|
||||
</DrawingGroup.Children>
|
||||
@@ -859,7 +874,7 @@ M0,0L63.999001,0 63.999001,48.792999 0,48.792999z">
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing
|
||||
<GeometryDrawing
|
||||
Brush="{mbts:BTSColor MarketData.bid}"
|
||||
Geometry="m 24.706673 31.196264 -3.086182 3.086182 5.965481 5.963348 -5.965481 5.96548 3.086182 3.084049 5.963348 -5.963348 5.96548 5.963348 3.084049 -3.084049 -5.963347 -5.96548 5.963347 -5.963348 -3.084049 -3.086182 -5.96548 5.965481 z M 5.3507926 32.045363 H 17.816449 v 2.401501 H 5.3507926 Z m 0 -4.937233 H 24.132994 v 2.401501 H 5.3507926 Z m 0 9.874466 h 5.5381524 v 2.401501 H 5.3507926 Z M 1.3730469 0 A 1.3741374 1.3741374 0 0 0 0 1.3730469 V 45.630859 a 1.3741374 1.3741374 0 0 0 1.3730469 1.373047 H 16.853516 a 17.906029 17.906029 0 0 1 -0.05859 -1.373047 17.906029 17.906029 0 0 1 0.06836 -1.375 H 2.7480469 V 2.7480469 H 33.326172 V 27.783203 a 17.906029 17.906029 0 0 1 1.375 -0.05859 17.906029 17.906029 0 0 1 1.373047 0.06836 V 1.3730469 A 1.3741374 1.3741374 0 0 0 34.701172 0 Z M 10.662215 24.759265 V 5.1202697 h 7.148923 q 3.286862 0 5.05355 1.2051818 1.766687 1.2051838 1.766687 3.3964241 0 1.5886494 -1.081924 2.7801354 -1.068231 1.191488 -2.739053 1.657126 v 0.05479 q 2.095375 0.26021 3.341644 1.547564 1.259962 1.287354 1.259962 3.136214 0 2.697964 -1.93103 4.286613 -1.931032 1.574956 -5.272673 1.574956 z M 15.085783 8.3797408 v 4.6563852 h 1.944726 q 1.369526 0 2.150155 -0.657372 0.794325 -0.671068 0.794325 -1.835164 0 -2.1638492 -3.23208 -2.1638492 z m 0 7.9432472 v 5.176805 h 2.39667 q 1.533868 0 2.39667 -0.712152 0.876495 -0.712155 0.876495 -1.944728 0 -1.17779 -0.862802 -1.848858 -0.849105 -0.671067 -2.382974 -0.671067 z" />
|
||||
</DrawingGroup.Children>
|
||||
@@ -871,7 +886,7 @@ M0,0L63.999001,0 63.999001,48.792999 0,48.792999z">
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing
|
||||
<GeometryDrawing
|
||||
Brush="{mbts:BTSColor MarketData.ask}"
|
||||
Geometry="m 19.060265 26.797642 v -2.144583 q 0.583058 0.489233 1.266644 0.737201 0.683586 0.241265 1.380576 0.241265 0.408811 0 0.710393 -0.07372 0.308284 -0.07372 0.509339 -0.201055 0.207756 -0.134036 0.308284 -0.308283 0.100527 -0.18095 0.100527 -0.388706 0 -0.281477 -0.160844 -0.502637 -0.160844 -0.22116 -0.44232 -0.408811 -0.274775 -0.187651 -0.656779 -0.361898 -0.382004 -0.174248 -0.824324 -0.355197 -1.125906 -0.469128 -1.682158 -1.146012 -0.549549 -0.676884 -0.549549 -1.635245 0 -0.750604 0.301582 -1.28675 0.301582 -0.542847 0.817622 -0.891342 0.522743 -0.348495 1.206328 -0.509339 0.683586 -0.167545 1.447594 -0.167545 0.750604 0 1.326961 0.09383 0.583059 0.08712 1.072292 0.274775 v 2.003845 q -0.241266 -0.167545 -0.529444 -0.29488 -0.281477 -0.127335 -0.583059 -0.207757 -0.301582 -0.08712 -0.603164 -0.127334 -0.29488 -0.04021 -0.562953 -0.04021 -0.3686 0 -0.670182 0.07372 -0.301582 0.06702 -0.509339 0.194353 -0.207756 0.127334 -0.321687 0.308284 -0.113931 0.174247 -0.113931 0.395407 0 0.241266 0.127334 0.435619 0.127335 0.187651 0.361899 0.361898 0.234564 0.167546 0.569655 0.335091 0.335091 0.160844 0.757306 0.335091 0.576356 0.241266 1.03208 0.516041 0.462426 0.268073 0.790816 0.609866 0.328389 0.341793 0.502636 0.784113 0.174248 0.435618 0.174248 1.018677 0 0.804219 -0.308284 1.353768 -0.301582 0.542848 -0.824324 0.884641 -0.522743 0.335091 -1.219732 0.482531 -0.690288 0.14744 -1.460998 0.14744 -0.790815 0 -1.50791 -0.134036 -0.710393 -0.134037 -1.233135 -0.40211 z m 6.620223 3.788289 -1.556212 1.556212 3.008102 3.007026 -3.008102 3.008101 1.556212 1.555136 3.007026 -3.007026 3.008101 3.007026 1.555136 -1.555136 -3.007026 -3.008101 3.007026 -3.007026 -1.555136 -1.556212 -3.008101 3.008102 z m -9.76023 2.917766 h 2.792621 v 1.21096 h -2.792621 z m 0 -2.489606 h 6.285825 v 1.21096 h -6.285825 z m 0 -2.489607 h 9.470951 v 1.210961 H 15.920258 Z M 13.914475 14.855173 a 0.69291063 0.69291063 0 0 0 -0.692361 0.692361 v 22.317061 a 0.69291063 0.69291063 0 0 0 0.692361 0.692361 h 7.806047 a 9.0291392 9.0291392 0 0 1 -0.02954 -0.692361 9.0291392 9.0291392 0 0 1 0.03447 -0.693345 H 14.60782 V 16.24088 h 15.419061 v 12.624011 a 9.0291392 9.0291392 0 0 1 0.693346 -0.02954 9.0291392 9.0291392 0 0 1 0.692361 0.03447 V 15.547534 a 0.69291063 0.69291063 0 0 0 -0.692361 -0.692361 z" />
|
||||
</DrawingGroup.Children>
|
||||
@@ -884,7 +899,7 @@ M0,0L63.999001,0 63.999001,48.792999 0,48.792999z">
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing
|
||||
<GeometryDrawing
|
||||
Brush="Black"
|
||||
Geometry="M 5.3507926 32.045363 H 17.81645 v 2.401501 H 5.3507926 Z m 0 -4.937233 H 24.132995 v 2.401501 H 5.3507926 Z M 18.799228 22.222041 v 2.32929 h -1.567173 v -2.264886 q -2.179014 -0.01073 -4.057475 -0.987533 v -2.973336 q 0.622575 0.504501 1.856993 0.933864 1.234417 0.429362 2.200482 0.493766 v -3.907198 q -2.511771 -0.933863 -3.4349 -2.018003 -0.912395 -1.094874 -0.912395 -2.662047 0 -1.685248 1.191482 -2.8659947 1.19148 -1.1914807 3.155813 -1.3846939 V 4.918734 h 1.567173 v 1.9535992 q 2.264887 0.1073411 3.38123 0.7299162 V 10.500446 Q 20.677689 9.5880506 18.799228 9.3841034 v 4.0682086 q 2.35076 0.847992 3.370495 1.942866 1.019736 1.08414 1.019736 2.629845 0 1.781854 -1.137811 2.876728 -1.13781 1.08414 -3.25242 1.32029 z M 17.232055 12.829737 V 9.4270397 q -1.492034 0.2683516 -1.492034 1.5564393 0 1.105608 1.492034 1.846258 z m 1.567173 3.628113 v 3.25242 q 1.53497 -0.236149 1.53497 -1.53497 0 -1.051939 -1.53497 -1.71745 z m 13.258587 13.65074 h -3.954117 l 0.0014 7.641804 -7.643169 -10e-7 0.0014 3.952751 h 7.640439 l 0.0014 7.641803 h 3.951385 l 0.0014 -7.641802 7.640437 -10e-7 0.0014 -3.952751 -7.643169 10e-7 z M 5.3507926 36.982596 h 5.5381524 v 2.401501 H 5.3507926 Z M 1.3730469 0 A 1.3741374 1.3741374 0 0 0 0 1.3730469 V 45.630859 a 1.3741374 1.3741374 0 0 0 1.3730469 1.373047 H 16.853516 a 17.906029 17.906029 0 0 1 -0.05859 -1.373047 17.906029 17.906029 0 0 1 0.06836 -1.375 H 2.7480469 V 2.7480469 H 33.326172 V 27.783203 a 17.906029 17.906029 0 0 1 1.375 -0.05859 17.906029 17.906029 0 0 1 1.373047 0.06836 V 1.3730469 A 1.3741374 1.3741374 0 0 0 34.701172 0 Z" />
|
||||
</DrawingGroup.Children>
|
||||
@@ -896,7 +911,7 @@ M0,0L63.999001,0 63.999001,48.792999 0,48.792999z">
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing
|
||||
<GeometryDrawing
|
||||
Brush="Black"
|
||||
Geometry="m 26.463403 27.963318 h -2.359042 l -0.683586 -2.137882 h -3.417929 l -0.676884 2.137882 h -2.345638 l 3.498351 -9.610414 h 2.566798 z M 22.92484 24.163384 21.89276 20.933106 q -0.113931 -0.361899 -0.160844 -0.864535 h -0.05361 q -0.03351 0.422214 -0.167545 0.837727 l -1.045485 3.257086 z m 2.065112 7.055953 -1.51223 1.51223 2.923087 2.922042 -2.923087 2.923086 1.51223 1.511185 2.922042 -2.922042 2.923086 2.922042 1.511185 -1.511185 -2.922041 -2.923086 2.922041 -2.922042 -1.511185 -1.51223 -2.923086 2.923087 z m -9.484387 0.416058 h 6.108175 v 1.176737 h -6.108175 z m 0 -2.419244 h 9.203284 v 1.176735 h -9.203284 z m 0 4.83849 h 2.713696 v 1.176736 H 15.505565 Z M 13.556469 15.93316 a 0.67332766 0.67332766 0 0 0 -0.672794 0.672793 v 21.686339 a 0.67332766 0.67332766 0 0 0 0.672794 0.672793 h 7.585433 a 8.7739586 8.7739586 0 0 1 -0.02871 -0.672793 8.7739586 8.7739586 0 0 1 0.0335 -0.673751 H 14.230219 V 17.279703 h 14.983289 v 12.267233 a 8.7739586 8.7739586 0 0 1 0.67375 -0.02871 8.7739586 8.7739586 0 0 1 0.672794 0.0335 V 16.605953 A 0.67332766 0.67332766 0 0 0 29.887258 15.93316 Z" />
|
||||
</DrawingGroup.Children>
|
||||
@@ -908,7 +923,7 @@ M0,0L63.999001,0 63.999001,48.792999 0,48.792999z">
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing
|
||||
<GeometryDrawing
|
||||
Brush="Black"
|
||||
Geometry="m 24.706673 31.196264 -3.086181 3.086182 5.96548 5.963348 -5.96548 5.96548 3.086181 3.084049 5.963348 -5.963348 5.96548 5.963348 3.084049 -3.084049 -5.963347 -5.96548 5.963347 -5.963348 -3.084049 -3.086182 -5.96548 5.965481 z M 5.3507926 32.045363 H 17.81645 v 2.401501 H 5.3507926 Z m 0 -4.937233 H 24.132994 v 2.401501 H 5.3507926 Z M 26.434166 6.0031559 14.993666 17.443656 9.6399578 12.089946 6.0100982 15.719802 c 2.9622322 2.959826 6.0772448 6.092263 8.9969908 8.970151 L 30.064121 9.6329208 Z M 5.3507926 36.982596 h 5.5381524 v 2.401501 H 5.3507926 Z M 1.3730469 0 A 1.3741374 1.3741374 0 0 0 0 1.3730469 V 45.630859 a 1.3741374 1.3741374 0 0 0 1.3730469 1.373047 H 16.853516 a 17.906029 17.906029 0 0 1 -0.05859 -1.373047 17.906029 17.906029 0 0 1 0.06836 -1.375 H 2.7480469 V 2.7480469 H 33.326172 V 27.783203 a 17.906029 17.906029 0 0 1 1.375 -0.05859 17.906029 17.906029 0 0 1 1.373047 0.06836 V 1.3730469 A 1.3741374 1.3741374 0 0 0 34.701172 0 Z" />
|
||||
</DrawingGroup.Children>
|
||||
@@ -931,7 +946,7 @@ M0,0L63.999001,0 63.999001,48.792999 0,48.792999z">
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing
|
||||
<GeometryDrawing
|
||||
Brush="{mbts:BTSColor MarketData.bid}"
|
||||
Geometry="M 9.9417804 -0.02293875 1.9154138 8.0034278 17.4301 23.512569 1.9154138 39.027256 9.9417804 47.048077 25.450922 31.538936 40.965607 47.048077 48.986428 39.027256 33.47729 23.512569 48.986428 8.0034278 40.965607 -0.02293875 25.450922 15.491746 Z" />
|
||||
</DrawingGroup.Children>
|
||||
@@ -943,7 +958,7 @@ M0,0L63.999001,0 63.999001,48.792999 0,48.792999z">
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing
|
||||
<GeometryDrawing
|
||||
Brush="{mbts:BTSColor MarketData.ask}"
|
||||
Geometry="M 9.9417804 -0.02293875 1.9154138 8.0034278 17.4301 23.512569 1.9154138 39.027256 9.9417804 47.048077 25.450922 31.538936 40.965607 47.048077 48.986428 39.027256 33.47729 23.512569 48.986428 8.0034278 40.965607 -0.02293875 25.450922 15.491746 Z" />
|
||||
</DrawingGroup.Children>
|
||||
@@ -955,7 +970,7 @@ M0,0L63.999001,0 63.999001,48.792999 0,48.792999z">
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing
|
||||
<GeometryDrawing
|
||||
Brush="Black"
|
||||
Geometry="M 9.9417804 -0.02293875 1.9154138 8.0034278 17.4301 23.512569 1.9154138 39.027256 9.9417804 47.048077 25.450922 31.538936 40.965607 47.048077 48.986428 39.027256 33.47729 23.512569 48.986428 8.0034278 40.965607 -0.02293875 25.450922 15.491746 Z" />
|
||||
</DrawingGroup.Children>
|
||||
@@ -968,7 +983,7 @@ M0,0L63.999001,0 63.999001,48.792999 0,48.792999z">
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing
|
||||
<GeometryDrawing
|
||||
Brush="Black"
|
||||
Geometry="m 69.641861 87.129943 a 36.813842 36.813842 0 0 0 -36.813776 36.813767 36.813842 36.813842 0 0 0 31.044618 36.31355 l 1.208194 21.35839 1.804543 31.90967 a 41.092964 41.092964 0 0 0 -29.828154 39.50509 41.092964 41.092964 0 0 0 41.09258 41.0931 41.092964 41.092964 0 0 0 41.093104 -41.0931 41.092964 41.092964 0 0 0 -0.10284 -2.9068 41.092964 41.092964 0 0 0 -38.048841 -38.03902 l -2.962092 -52.36321 a 36.813842 36.813842 0 0 0 20.093347 -12.61939 l 33.150946 15.70705 v 5.3e-4 a 27.542416 27.542416 0 0 0 -0.12557 2.49907 27.542416 27.542416 0 0 0 27.54251 27.54249 27.542416 27.542416 0 0 0 27.5425 -27.5425 27.542416 27.542416 0 0 0 -27.5425 -27.5425 27.542416 27.542416 0 0 0 -22.44618 11.61479 l -31.44563 -14.89935 a 36.813842 36.813842 0 0 0 1.55701 -10.53786 36.813842 36.813842 0 0 0 -36.813769 -36.813767 z" />
|
||||
</DrawingGroup.Children>
|
||||
@@ -980,7 +995,7 @@ M0,0L63.999001,0 63.999001,48.792999 0,48.792999z">
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing
|
||||
<GeometryDrawing
|
||||
Brush="Black"
|
||||
Geometry="M 36.50044 86.999995 A 36.813842 36.813842 0 0 0 -0.3133356 123.81377 36.813842 36.813842 0 0 0 30.731282 160.12732 l 1.208194 21.35839 1.804543 31.90967 a 41.092964 41.092964 0 0 0 -29.8281546 39.50509 41.092964 41.092964 0 0 0 41.0925806 41.0931 41.092964 41.092964 0 0 0 41.093099 -41.0931 41.092964 41.092964 0 0 0 -0.102836 -2.9068 41.092964 41.092964 0 0 0 -38.04884 -38.03902 l -2.962092 -52.36321 a 36.813842 36.813842 0 0 0 20.093347 -12.61939 l 33.150948 15.70705 v 5.3e-4 a 27.542416 27.542416 0 0 0 -0.125574 2.49907 27.542416 27.542416 0 0 0 27.542513 27.54249 27.542416 27.542416 0 0 0 27.5425 -27.5425 27.542416 27.542416 0 0 0 -27.5425 -27.5425 27.542416 27.542416 0 0 0 -22.44618 11.61479 L 71.757201 134.35163 A 36.813842 36.813842 0 0 0 73.314213 123.81377 36.813842 36.813842 0 0 0 36.50044 86.999995 Z m 116.60981 115.628085 0.007 37.48967 h -37.49716 l 0.007 19.39257 h 37.48344 L 153.11751 297 h 19.38493 l 0.007 -37.48968 h 37.48342 L 210 240.11775 h -37.49727 l 0.007 -37.48967 z" />
|
||||
</DrawingGroup.Children>
|
||||
@@ -1005,7 +1020,7 @@ M0,0L63.999001,0 63.999001,48.792999 0,48.792999z">
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing
|
||||
<GeometryDrawing
|
||||
Brush="Black"
|
||||
Geometry="M 37.03498 86.999995 A 36.813842 36.813842 0 0 0 0.2212037 123.81377 36.813842 36.813842 0 0 0 31.265822 160.12732 l 1.208194 21.35839 1.804543 31.90967 a 41.092964 41.092964 0 0 0 -29.8281553 39.50509 41.092964 41.092964 0 0 0 41.0925813 41.0931 41.092964 41.092964 0 0 0 41.093099 -41.0931 41.092964 41.092964 0 0 0 -0.102836 -2.9068 41.092964 41.092964 0 0 0 -38.04884 -38.03902 l -2.962092 -52.36321 a 36.813842 36.813842 0 0 0 20.093347 -12.61939 l 33.150948 15.70705 v 5.3e-4 a 27.542416 27.542416 0 0 0 -0.125574 2.49907 27.542416 27.542416 0 0 0 27.542503 27.54249 27.542416 27.542416 0 0 0 27.5425 -27.5425 27.542416 27.542416 0 0 0 -27.5425 -27.5425 27.542416 27.542416 0 0 0 -22.44618 11.61479 L 72.291741 134.35163 A 36.813842 36.813842 0 0 0 73.848753 123.81377 36.813842 36.813842 0 0 0 37.03498 86.999995 Z m 145.03189 90.486735 -76.71431 76.71435 27.93311 27.93293 L 210 205.41986 Z m -0.008 22.13769 5.79522 5.79544 -54.57645 54.57644 -5.7952 -5.79522 z m -81.50016 59.76108 -10.071854 37.61451 37.606034 -10.0803 z" />
|
||||
</DrawingGroup.Children>
|
||||
@@ -1017,7 +1032,7 @@ M0,0L63.999001,0 63.999001,48.792999 0,48.792999z">
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing
|
||||
<GeometryDrawing
|
||||
Brush="Black"
|
||||
Geometry="m 139.80129 180.78831 a 20.783495 20.783495 0 0 0 -20.78345 20.78346 20.783495 20.783495 0 0 0 17.52643 20.50105 l 0.68209 12.05803 1.01877 18.01482 a 23.1993 23.1993 0 0 0 -16.83968 22.30284 23.1993 23.1993 0 0 0 23.1991 23.19938 23.1993 23.1993 0 0 0 23.19935 -23.19938 23.1993 23.1993 0 0 0 -0.058 -1.64105 23.1993 23.1993 0 0 0 -21.4807 -21.47518 l -1.67225 -29.56198 a 20.783495 20.783495 0 0 0 11.34383 -7.12437 l 18.71558 8.86752 v 3.1e-4 a 15.549251 15.549251 0 0 0 -0.0708 1.41086 15.549251 15.549251 0 0 0 15.5493 15.54927 15.549251 15.549251 0 0 0 15.54931 -15.54927 15.549251 15.549251 0 0 0 -15.54931 -15.54932 15.549251 15.549251 0 0 0 -12.67213 6.5572 l -17.75282 -8.41152 a 20.783495 20.783495 0 0 0 0.87902 -5.94921 20.783495 20.783495 0 0 0 -20.78345 -20.78346 z M 31.983713 88.265691 A 30.676234 30.676234 0 0 0 1.3075339 118.94187 30.676234 30.676234 0 0 0 27.17639 149.20122 l 1.006764 17.79752 1.503689 26.58969 A 34.241941 34.241941 0 0 0 4.8316412 226.50722 34.241941 34.241941 0 0 0 39.073263 260.74928 34.241941 34.241941 0 0 0 73.315316 226.50722 34.241941 34.241941 0 0 0 73.229625 224.08505 34.241941 34.241941 0 0 0 41.524291 192.3879 L 39.05604 148.75469 A 30.676234 30.676234 0 0 0 55.799422 138.2392 l 27.624018 13.08837 v 4.4e-4 a 22.950541 22.950541 0 0 0 -0.104638 2.08242 22.950541 22.950541 0 0 0 22.950618 22.9506 22.950541 22.950541 0 0 0 22.95062 -22.9506 22.950541 22.950541 0 0 0 -22.95062 -22.95061 22.950541 22.950541 0 0 0 -18.703946 9.67837 L 61.362463 127.72286 A 30.676234 30.676234 0 0 0 62.65989 118.94187 30.676234 30.676234 0 0 0 31.983713 88.265691 Z" />
|
||||
</DrawingGroup.Children>
|
||||
@@ -1141,7 +1156,7 @@ M0,0L63.999001,0 63.999001,48.792999 0,48.792999z">
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing
|
||||
Brush="Black"
|
||||
Geometry="M17.740002,11.999007C17.254002,11.999007,16.859001,12.394008,16.859001,12.879008L16.859001,24.458791 16.860127,24.479386C16.861003,24.607261 16.813003,24.735511 16.716002,24.834012 16.667502,24.883012 16.611378,24.91995 16.551394,24.944762L16.521562,24.955436 16.507633,24.960536 16.506465,24.960837 16.50574,24.961097 16.49194,24.964574 16.459728,24.972863C16.42719,24.979527,16.393502,24.983027,16.359002,24.983027L16.316763,24.980893 16.315716,24.980851 16.307903,24.980445C16.223895,24.971904,16.146014,24.942538,16.07951,24.897597L16.067752,24.887895 16.047276,24.873078 16.015234,24.844558 16.005502,24.836528 16.001236,24.831357 13.737002,22.600011C13.267003,22.134011 12.502003,22.135011 12.031003,22.600011 11.805003,22.82301 11.680003,23.120011 11.680003,23.436011 11.680003,23.751012 11.805003,24.048011 12.031003,24.272012L16.842003,29.031013C19.311003,31.189013 21.546002,31.119014 22.656003,30.886014 23.939002,30.614013 25.015002,29.846013 25.464002,28.880013 25.857001,28.036012 26.301002,27.080012 26.263001,26.195012 26.262002,26.178012 26.268003,26.074012 26.269002,26.056012L26.268003,20.974011C26.268003,20.55601 25.922002,20.215011 25.496001,20.215011 25.335502,20.215011 25.239001,20.246511 25.179877,20.283135L25.144,20.309762 25.144,21.215013C25.144,21.491012 24.919999,21.715013 24.644,21.715013 24.367999,21.715013 24.144,21.491012 24.144,21.215013L24.144,19.278017C24.144,18.793018 23.749,18.399019 23.263,18.399019 22.808312,18.399019 22.432727,18.745308 22.387555,19.18822L22.383004,19.277944 22.383004,19.716007C22.383004,19.992006 22.159003,20.216004 21.883002,20.216004 21.607003,20.216004 21.383002,19.992006 21.383002,19.716007L21.383002,19.278054 21.383002,18.504013C21.383002,18.018016 20.988002,17.623017 20.502002,17.623017 20.016002,17.623017 19.621001,18.018016 19.621001,18.504013L19.621001,20.24402C19.621001,20.52102 19.397001,20.74402 19.121001,20.74402 18.844001,20.74402 18.621001,20.52102 18.621001,20.24402L18.621001,18.504035 18.621001,12.879008C18.621001,12.394008,18.226001,11.999007,17.740002,11.999007z M17.740002,10.999005C18.777001,10.999005,19.621001,11.843007,19.621001,12.879008L19.621001,16.842839 19.687315,16.808824C19.933955,16.689783 20.210345,16.623022 20.502002,16.623022 21.247346,16.623022 21.892987,17.059031 22.197202,17.689331L22.211675,17.721288 22.212884,17.720384C22.513,17.517568 22.874499,17.399021 23.263,17.399021 24.267594,17.399021 25.091062,18.190155 25.141547,19.181478L25.143222,19.247425 25.174827,19.241074C25.276639,19.223799 25.383876,19.21501 25.496001,19.21501 26.473002,19.21501 27.268003,20.00401 27.268003,20.974011L27.268003,26.087012C27.268003,26.098012 27.262002,26.194013 27.262002,26.205012 27.311002,27.281013 26.790002,28.401013 26.371001,29.302012 25.783002,30.566012 24.472001,31.523013 22.863002,31.864013 22.513001,31.938014 22.067002,31.999013 21.547002,31.999013 20.149003,31.999013 18.216002,31.561013 16.161002,29.763013L11.328003,24.983012C10.910003,24.570012 10.680003,24.020011 10.680003,23.436011 10.680003,22.85101 10.910003,22.302011 11.328003,21.88901 12.187003,21.040011 13.583003,21.041011 14.440002,21.88901L15.859002,23.287391 15.859002,12.879008C15.859002,11.843007,16.703002,10.999005,17.740002,10.999005z M6.8659983,4.0500388L19.083997,4.0500388C20.668996,4.0500388,21.957997,5.3460296,21.957997,6.9390478L21.957997,14.653042C21.957997,14.93005 21.734998,15.153042 21.457997,15.153042 21.181996,15.153042 20.957997,14.93005 20.957997,14.653042L20.957997,6.9390478C20.957997,5.8980318,20.116998,5.0500394,19.083997,5.0500394L6.8659983,5.0500394C5.8319979,5.0500394,4.9909983,5.8980318,4.9909984,6.9390478L4.9909984,26.116061C4.9909983,27.157046,5.8319979,28.00504,6.8659983,28.00504L11.696996,28.00504C11.972997,28.00504 12.196996,28.229039 12.196996,28.50504 12.196996,28.781041 11.972997,29.00504 11.696996,29.00504L6.8659983,29.00504C5.2809954,29.00504,3.9909983,27.70905,3.9909983,26.116061L3.9909983,6.9390478C3.9909983,5.3460296,5.2809954,4.0500388,6.8659983,4.0500388z M6.4360008,0L17.467001,0C17.743001,0 17.967001,0.22300029 17.967001,0.50000024 17.967001,0.77600098 17.743001,1.0000012 17.467001,1.0000012L6.4360008,1.0000012C3.4380004,1.0000012,1.0000002,3.4210042,1.0000002,6.3970079L1.0000002,20.617026C1.0000002,20.893025 0.77600026,21.117026 0.50000048,21.117026 0.22400022,21.117026 2.3841858E-07,20.893025 0,20.617026L0,6.3970079C2.3841858E-07,2.8700035,2.8870004,0,6.4360008,0z"
|
||||
Geometry="M 0.814453 2e-6 C 0.365092 -7.56e-4 3.21e-4 0.36314 0 0.812502 v 23.945313 c 0.788895 1.126154 1.626953 -0.02112 1.626953 -0.02112 V 1.625002 h 16.241843 c 0 0 0.80538 -0.934678 -0.124651 -1.625002 z M 3.750875 3.43624 C 3.301514 3.435482 2.936743 3.799378 2.936422 4.24874 v 23.945313 c -7.6e-4 0.450124 0.364329 0.815213 0.814453 0.814453 h 7.439453 C 11.042745 28.716852 10.90913 28.418337 10.789937 28.113975 10.699431 27.872971 10.617994 27.628659 10.545796 27.381553 H 4.563375 V 5.06124 h 15.304687 v 7.039063 c 0.173002 -0.01023 0.346234 -0.01609 0.519531 -0.01758 0.343731 -2.6e-4 0.68726 0.01669 1.029297 0.05078 0.02606 0.0038 0.0521 0.0077 0.07813 0.01172 V 4.248738 C 21.494699 3.799376 21.129928 3.43548 20.680567 3.436238 Z m 13.332031 6.884766 c -1.226661 0 -2.230469 1.002456 -2.230469 2.228516 v 9.572265 l -0.824219 -0.8125 v 0.002 c -0.991917 -0.9815 -2.60964 -0.982302 -3.603515 0 -0.48293 0.477155 -0.751953 1.119962 -0.751953 1.796875 0 0.67607 0.269215 1.317958 0.751953 1.794922 l 4.841797 4.78711 0.0078 0.0078 c 2.115591 1.851014 4.144077 2.322266 5.615234 2.322266 0.547268 0 1.017683 -0.06414 1.388672 -0.142578 1.701281 -0.360558 3.108561 -1.372782 3.751954 -2.75586 0.419048 -0.9011 0.978455 -2.062137 0.923828 -3.261718 4.09e-4 -0.01025 0.0011 -0.0075 0.002 -0.02344 0.0015 -0.02655 0.0039 -0.01047 0.0039 -0.07813 v -5.113281 c 0 -1.161114 -0.955476 -2.109375 -2.121094 -2.109375 -0.04803 0 -0.09044 0.0088 -0.136719 0.01172 -0.207784 -1.015547 -1.021531 -1.826172 -2.095703 -1.826172 -0.343265 0 -0.63914 0.145124 -0.93164 0.285156 -0.397916 -0.616533 -1.045784 -1.0625 -1.830078 -1.0625 -0.189487 0 -0.354735 0.07615 -0.53125 0.121094 v -3.515625 c 0 -1.22606 -1.003809 -2.228516 -2.230469 -2.228516 z m 0 1.699219 c 0.148476 0 0.278642 0.05997 0.375 0.15625 0.09685 0.09678 0.15625 0.225142 0.15625 0.373047 v 5.625 1.740234 c 0 0.464846 0.384763 0.849609 0.849609 0.849609 0.464527 0 0.84961 -0.383921 0.84961 -0.849609 v -1.740234 c 0 -0.148598 0.05896 -0.275762 0.15625 -0.373047 0.09729 -0.09729 0.228277 -0.158203 0.375 -0.158203 0.146722 0 0.277709 0.06091 0.375 0.158203 0.09729 0.09729 0.15625 0.224449 0.15625 0.373047 v 0.77539 0.4375 c 0 0.465373 0.384236 0.84961 0.849609 0.84961 0.465373 0 0.849609 -0.384239 0.849609 -0.84961 v -0.425781 l 0.0059 -0.06836 c 0.0286 -0.265146 0.249414 -0.472657 0.52539 -0.472657 0.148238 0 0.278481 0.05996 0.375 0.15625 0.09649 0.09627 0.15625 0.225145 0.15625 0.373047 v 1.935547 c 0 0.465371 0.384237 0.84961 0.84961 0.84961 0.465372 0 0.849609 -0.384237 0.849609 -0.84961 v -0.65039 c 0.0016 -9e-6 2.95e-4 0 0.002 0 0.238806 0 0.421875 0.185008 0.421875 0.410156 l 0.002 5.0625 c -4.64e-4 0.0084 -0.0023 0.0401 -0.0039 0.07227 -0.0015 0.03041 -0.0059 0.02687 -0.002 0.101563 0.03253 0.757506 -0.372777 1.677807 -0.765625 2.521484 h -0.002 c -0.194342 0.418116 -0.532821 0.810028 -0.976563 1.126953 -0.443595 0.316821 -0.990203 0.55925 -1.585937 0.685547 -0.515602 0.10823 -1.298166 0.179402 -2.248047 -0.03125 -0.47546 -0.105441 -0.991926 -0.281044 -1.539063 -0.560547 -0.547306 -0.279588 -1.127683 -0.66381 -1.724609 -1.185547 L 11.620061 23.69601 c -0.162198 -0.160763 -0.248047 -0.365899 -0.248047 -0.587891 0 -0.223284 0.08648 -0.426518 0.248047 -0.585937 0.168295 -0.166151 0.386826 -0.249911 0.607422 -0.25 0.220595 -9e-5 0.437432 0.08144 0.605469 0.248047 l 2.240234 2.207031 0.01367 0.02148 0.04687 0.03516 0.03711 0.0332 0.02539 0.01758 0.01563 0.01367 0.01563 0.0098 c 0.114637 0.07747 0.248043 0.126397 0.388672 0.140625 l -0.04883 -0.0078 0.04102 0.0098 0.08594 0.0039 h 0.0078 c 0.06844 0 0.126002 -0.0085 0.169922 -0.01758 l 0.0059 -0.002 0.01953 -0.0039 h 0.02539 l 0.06641 -0.02734 0.02734 -0.0098 0.0098 -0.0039 c 0.102105 -0.04223 0.198238 -0.105586 0.28125 -0.189454 h 0.002 c 0.163006 -0.165519 0.243191 -0.385955 0.242188 -0.599609 v -0.002 -0.01953 -11.580078 c 0 -0.147904 0.0594 -0.276271 0.15625 -0.373047 0.09636 -0.09628 0.226522 -0.15625 0.375 -0.15625 z"
|
||||
/>
|
||||
</DrawingGroup.Children>
|
||||
</DrawingGroup>
|
||||
@@ -1149,10 +1164,10 @@ M0,0L63.999001,0 63.999001,48.792999 0,48.792999z">
|
||||
</DrawingImage>
|
||||
|
||||
|
||||
<!-- Pin
|
||||
<!-- Pin
|
||||
<Path Data="F1M3,11L3,7 0,7 0,6 1,6 1,1 1,0 6,0 6,1 6,6 7,6 7,7 4,7 4,11 3,11z M2,1L2,6 4,6 4,1 2,1z" />
|
||||
Unpin
|
||||
Unpin
|
||||
<Path Data="F1M0,3L4,3 4,0 5,0 5,1 10,1 11,1 11,6 10,6 5,6 5,7 4,7 4,4 0,4 0,3z M10,2L5,2 5,4 10,4 10,2z" />
|
||||
-->
|
||||
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary>
|
||||
@@ -5,7 +5,6 @@ using mbts.co2;
|
||||
using mbts.persist;
|
||||
using mbts.spark;
|
||||
using mbts.ui;
|
||||
using mbts.ui.shell;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.IO;
|
||||
@@ -13,13 +12,11 @@ using System.Threading.Tasks;
|
||||
using System.Windows.Media;
|
||||
using static mbts.ui.shell.ProtoBufSerializationHelper;
|
||||
|
||||
namespace bts.shell
|
||||
{
|
||||
namespace bts.shell {
|
||||
[Export(typeof(IShellModule))]
|
||||
class MarketShellModule : IShellModule
|
||||
{
|
||||
class MarketShellModule : IShellModule {
|
||||
[ImportingConstructor]
|
||||
public MarketShellModule(IBus bus, MDConsumer consumer, UserSettingsHub settings_hub, OrdersModel orders_model, [Import(LoginContainer.Exports.UserName)]string user_name) {
|
||||
public MarketShellModule(IBus bus, MDConsumer consumer, UserSettingsHub settings_hub, OrdersModel orders_model) {
|
||||
_tsf = new TimeAndSalesWindowFactory(this, bus, consumer, settings_hub);
|
||||
_mvf = new MarketViewWindowFactory(this, bus, settings_hub, orders_model);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace mbts.spark {
|
||||
readonly ObservableFilterCollection<OrderRecordImmutable> _working_orders, _working_bids, _working_asks;
|
||||
readonly string _security_text, _security_key_text;
|
||||
readonly Property<double> _bid_price, _ask_price, _last_price, _day_change, _settlement, _session_high, _session_low;
|
||||
readonly Property<bool> _last_price_from_spread;
|
||||
readonly CellProperty<int> _position;
|
||||
readonly CellProperty<uint> _last_size;
|
||||
readonly CellProperty<ulong> _volume;
|
||||
@@ -36,6 +37,7 @@ namespace mbts.spark {
|
||||
readonly MyOrderSummarizer _order_summarizer = new MyOrderSummarizer();
|
||||
readonly MDDisplayHelper.SizeFormatter _size_formatter = MDDisplayHelper.get_formatter(MarketSizeDisplay.get_default());
|
||||
Property<uint> _bid_direct_size, _bid_merged_size, _ask_direct_size, _ask_merged_size;
|
||||
double _raw_day_position;
|
||||
string _bid_merged_size_text, _ask_merged_size_text;
|
||||
ulong _bbo_ref, _last_ref;
|
||||
|
||||
@@ -53,6 +55,7 @@ namespace mbts.spark {
|
||||
_day_change = backing(nameof(day_change), double.NaN);
|
||||
_session_low = backing(nameof(session_low), double.NaN);
|
||||
_session_high = backing(nameof(session_high), double.NaN);
|
||||
_last_price_from_spread = backing(nameof(last_price_from_spread), false);
|
||||
_settlement = backing(nameof(settlement), double.NaN);
|
||||
_volume = new CellProperty<ulong>(this, nameof(volume), 0);
|
||||
_inside_bids = new CellProperty<bool>(this, nameof(inside_bids));
|
||||
@@ -89,6 +92,10 @@ namespace mbts.spark {
|
||||
_dispose = Disposable.Create(
|
||||
_orders_model.on_security_root_orders(security.Id).OnDispatcher().Subscribe(_on_orders),
|
||||
_position.OnDispatcher().Subscribe(v => _animation.animate_position(v.newval > v.oldval)),
|
||||
_orders_model.on_security_positions(security.Id).OnDispatcher().Subscribe(t => {
|
||||
if (Set(ref _raw_day_position, t.state.Values.Sum(p => p.Item2.raw_day_pos()), nameof(raw_day_position)))
|
||||
raise_invalidated();
|
||||
}),
|
||||
_inside_bids.OnDispatcher().Subscribe(v => _animation.animate_working_bids_inside(v.newval)),
|
||||
_inside_asks.OnDispatcher().Subscribe(v => _animation.animate_working_asks_inside(v.newval)),
|
||||
_day_change.OnDispatcher().Subscribe(v => _animation.animate_day_change(v.newval > v.oldval)),
|
||||
@@ -102,7 +109,9 @@ namespace mbts.spark {
|
||||
public bool inside_bids => _inside_bids.value;
|
||||
public bool inside_asks => _inside_asks.value;
|
||||
public int position => _position.value;
|
||||
public double raw_day_position => _raw_day_position;
|
||||
public double last_price => _last_price.Value;
|
||||
public bool last_price_from_spread => _last_price_from_spread.Value;
|
||||
public uint last_size => _last_size.value;
|
||||
public double bid_price => _bid_price.Value;
|
||||
public uint bid_direct_size => _bid_direct_size.Value;
|
||||
@@ -161,15 +170,17 @@ namespace mbts.spark {
|
||||
_inside_bids.on_next_distinct(_bid_price.Value >= _working_best_bid.value, ref dirty);
|
||||
_inside_asks.on_next_distinct(_ask_price.Value <= _working_best_ask.value, ref dirty);
|
||||
}
|
||||
if (md.md.get_last_trade(ref _last_ref, out NativePriceSize ps, out DateTime ts, out ulong v)) {
|
||||
if (md.md.get_last_trade(ref _last_ref, out NativePriceSize ps, out DateTime ts, out ulong v, out bool from_spread)) {
|
||||
_last_price.set(ps.price);
|
||||
_last_price_from_spread.set(from_spread);
|
||||
_last_size.on_next_distinct(ps.size, ref dirty);
|
||||
_volume.on_next_distinct(v, ref dirty);
|
||||
}
|
||||
_settlement.set(md.md.settlement_price);
|
||||
_session_low.set(md.md.session_low);
|
||||
_session_high.set(md.md.session_high);
|
||||
_day_change.set(last_price - settlement);
|
||||
dirty |= _settlement.set_new(md.md.settlement_price);
|
||||
dirty |= _session_low.set_new(md.md.session_low);
|
||||
dirty |= _session_high.set_new(md.md.session_high);
|
||||
dirty |= _day_change.set_new(last_price - settlement);
|
||||
_volume.on_next_distinct(md.md.total_volume, ref dirty);
|
||||
if (dirty)
|
||||
invalidated?.Invoke();
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Reactive.Linq;
|
||||
using System.Reactive.Subjects;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Media;
|
||||
using static bts.shell.MarketViewWindowFactory;
|
||||
@@ -39,15 +38,17 @@ namespace mbts.spark {
|
||||
IMultiValueConverter price_converter = new ui.spark.converters.TickDisplayConverter();
|
||||
add_col(Columns.Security, "Security", r => r.security.ToString(), nameof(Row.security), DefaultColumnWidths.Security, security_filter, DataGridFilterKnownTemplates.Regex);
|
||||
add_col(Columns.Volume, "Volume", r => r.volume.ToString(), nameof(Row.volume), DefaultColumnWidths.Volume, volume_filter, DataGridFilterKnownTemplates.ULongMinMax);
|
||||
add_col(Columns.Last, "Last", r => r.format_price(r.last_price), nameof(Row.last_price), DefaultColumnWidths.Price, last_price_filter, DataGridFilterKnownTemplates.DoubleMinMax);
|
||||
add_col(Columns.LastSpd, "Spd", r => r.last_price_from_spread ? "S" : "", nameof(Row.last_price_from_spread), DefaultColumnWidths.Side, last_price_from_spread_filter, DataGridFilterKnownTemplates.Regex);
|
||||
add_col(Columns.Last, "Last", r => r.format_price(r.last_price), nameof(Row.last_price), DefaultColumnWidths.Price, last_price_filter, DataGridFilterKnownTemplates.DoubleMinMax);
|
||||
add_col(Columns.LastSize, merged_size_col_header, r => r.last_size.ToString(), nameof(Row.last_size), DefaultColumnWidths.Size, last_size_filter, DataGridFilterKnownTemplates.UIntMinMax, h_alignment: System.Windows.HorizontalAlignment.Right);
|
||||
add_col(Columns.Position, "Pos", r => r.position.ToString(), nameof(Row.position), DefaultColumnWidths.Size, position_filter, DataGridFilterKnownTemplates.IntMinMax, true, h_alignment: System.Windows.HorizontalAlignment.Right);
|
||||
add_col(Columns.RawDayPosition, "Raw Day Pos", r => SparkUtils.fmt_position(r.raw_day_position), nameof(Row.raw_day_position), DefaultColumnWidths.Size, raw_day_position_filter, DataGridFilterKnownTemplates.DoubleMinMax, true, h_alignment: System.Windows.HorizontalAlignment.Right);
|
||||
add_hl_working_orders_col(Columns.WorkingBids, working_col_header, nameof(Row.working_bids_text), nameof(Row.working_best_bid), nameof(Row.working_bids_click), working_bid_volume_filter, BTSColors.MarketData.bid, System.Windows.HorizontalAlignment.Right);
|
||||
add_col(Columns.BidImpliedSize, implied_size_col_header, r => r.bid_implied_size.ToString(), nameof(Row.bid_implied_size), DefaultColumnWidths.ImpliedDirectMergedSize, bid_implied_size_filter, DataGridFilterKnownTemplates.UIntMinMax, font_color: BTSColors.MarketData.bid, h_alignment: System.Windows.HorizontalAlignment.Right);
|
||||
add_col(Columns.BidDirectSize, direct_size_col_header, r => r.bid_direct_size.ToString(), nameof(Row.bid_direct_size), DefaultColumnWidths.ImpliedDirectMergedSize, bid_direct_size_filter, DataGridFilterKnownTemplates.UIntMinMax, font_color: BTSColors.MarketData.bid, h_alignment: System.Windows.HorizontalAlignment.Right);
|
||||
add_hl_merged_size_col(Columns.BidMergedSize, merged_size_col_header, nameof(Row.bid_merged_size), nameof(Row.bid_merged_size_text), nameof(Row.bid_merged_size_click), bid_merged_size_filter, BTSColors.MarketData.bid, h_alignment: System.Windows.HorizontalAlignment.Right);
|
||||
add_hl_price_col(Columns.Bid, "Bid", nameof(Row.bid_price), nameof(Row.bid_price_click), bid_price_filter, BTSColors.header_text, BTSColors.MarketData.bid_brush, h_alignment: System.Windows.HorizontalAlignment.Right);
|
||||
add_hl_price_col(Columns.Ask, "Ask", nameof(Row.ask_price), nameof(Row.ask_price_click), ask_price_filter, BTSColors.header_text, BTSColors.MarketData.ask_brush, h_alignment: System.Windows.HorizontalAlignment.Right);
|
||||
add_hl_price_col(Columns.Bid, "Bid", nameof(Row.bid_price), nameof(Row.bid_price_click), bid_price_filter, BTSColors.header_text, BTSColors.MarketData.bid, h_alignment: System.Windows.HorizontalAlignment.Right);
|
||||
add_hl_price_col(Columns.Ask, "Ask", nameof(Row.ask_price), nameof(Row.ask_price_click), ask_price_filter, BTSColors.header_text, BTSColors.MarketData.ask, h_alignment: System.Windows.HorizontalAlignment.Right);
|
||||
add_hl_merged_size_col(Columns.AskMergedSize, merged_size_col_header, nameof(Row.ask_merged_size), nameof(Row.ask_merged_size_text), nameof(Row.ask_merged_size_click), ask_merged_size_filter, BTSColors.MarketData.ask, h_alignment: System.Windows.HorizontalAlignment.Right);
|
||||
add_col(Columns.AskDirectSize, direct_size_col_header, r => r.ask_direct_size.ToString(), nameof(Row.ask_direct_size), DefaultColumnWidths.ImpliedDirectMergedSize, ask_direct_size_filter, DataGridFilterKnownTemplates.UIntMinMax, font_color: BTSColors.MarketData.ask, h_alignment: System.Windows.HorizontalAlignment.Right);
|
||||
add_col(Columns.AskImpliedSize, implied_size_col_header, r => r.ask_implied_size.ToString(), nameof(Row.ask_implied_size), DefaultColumnWidths.ImpliedDirectMergedSize, ask_implied_size_filter, DataGridFilterKnownTemplates.UIntMinMax, font_color: BTSColors.MarketData.ask, h_alignment: System.Windows.HorizontalAlignment.Right);
|
||||
@@ -77,18 +78,18 @@ namespace mbts.spark {
|
||||
horizontal_alignment = h_alignment
|
||||
});
|
||||
|
||||
void add_hl_price_col(Columns col_key, string header, string prop, string command_prop, IDataGridColumnFilter filter, Color foreground, Brush background, System.Windows.HorizontalAlignment h_alignment) =>
|
||||
add_hl_col(col_key, header, price_binding(prop), prop, command_prop, filter, DataGridFilterKnownTemplates.DoubleMinMax, DefaultColumnWidths.MViewPrice, foreground, background, DefaultSelectionHighlight, h_alignment);
|
||||
void add_hl_price_col(Columns col_key, string header, string prop, string command_prop, IDataGridColumnFilter filter, Color foreground, Color? background, System.Windows.HorizontalAlignment h_alignment) =>
|
||||
add_hl_col(col_key, header, price_binding(prop), prop, command_prop, filter, DataGridFilterKnownTemplates.DoubleMinMax, DefaultColumnWidths.MViewPrice, foreground, background, h_alignment);
|
||||
|
||||
void add_hl_merged_size_col(Columns col_key, string header, string sort_prop, string text_prop, string command_prop, IDataGridColumnFilter filter, Color foreground, System.Windows.HorizontalAlignment h_alignment) =>
|
||||
add_hl_col(col_key, header, new Binding(text_prop), sort_prop, command_prop, filter, DataGridFilterKnownTemplates.UIntMinMax, DefaultColumnWidths.ImpliedDirectMergedSize, foreground, null, null, h_alignment);
|
||||
add_hl_col(col_key, header, new Binding(text_prop), sort_prop, command_prop, filter, DataGridFilterKnownTemplates.UIntMinMax, DefaultColumnWidths.ImpliedDirectMergedSize, foreground, null, h_alignment);
|
||||
|
||||
void add_hl_working_orders_col(Columns col_key, string header, string text_prop, string sort_prop, string command_prop, IDataGridColumnFilter filter, Color foreground, System.Windows.HorizontalAlignment h_alignment) =>
|
||||
add_hl_col(col_key, header, new Binding(text_prop), sort_prop, command_prop, filter, DataGridFilterKnownTemplates.IntMinMax, working_orders_col_width, foreground, null, null, h_alignment);
|
||||
add_hl_col(col_key, header, new Binding(text_prop), sort_prop, command_prop, filter, DataGridFilterKnownTemplates.IntMinMax, working_orders_col_width, foreground, null, h_alignment);
|
||||
|
||||
void add_hl_col(
|
||||
Columns col_key, string header, BindingBase binding, string prop, string command_prop,
|
||||
IDataGridColumnFilter filter, string filter_template, double width, Color foreground, Brush background, Brush background_overlay, System.Windows.HorizontalAlignment h_alignment = System.Windows.HorizontalAlignment.Left) =>
|
||||
IDataGridColumnFilter filter, string filter_template, double width, Color foreground, Color? background, System.Windows.HorizontalAlignment h_alignment = System.Windows.HorizontalAlignment.Left) =>
|
||||
columns.Add(new HyperlinkElementColumn<Row, Columns>(
|
||||
col_key, binding, new Binding(command_prop), filter, filter_template) {
|
||||
// it's necessary to have this id populated for grid settings
|
||||
@@ -96,8 +97,7 @@ namespace mbts.spark {
|
||||
Header = header,
|
||||
sort_member_path = prop,
|
||||
font_color_override = foreground,
|
||||
background = background,
|
||||
background_overlay = background_overlay,
|
||||
background_color_override = background,
|
||||
Width = DefaultColumnWidths.Price,
|
||||
horizontal_alignment = h_alignment
|
||||
});
|
||||
@@ -111,14 +111,8 @@ namespace mbts.spark {
|
||||
//
|
||||
// make font-color immutable for Side, Size, (the font-color rule is hard-coded: MarketData.bid for Buy orders, MarketData.ask for Sells)
|
||||
var col_settings_flags = new Dictionary<string, GridColumnSettingsFeatureFlags> {
|
||||
{ Columns.Bid.ToString(), GridColumnSettingsFeatureFlags.ImmutableFontColor },
|
||||
{ Columns.Ask.ToString(), GridColumnSettingsFeatureFlags.ImmutableFontColor },
|
||||
{ Columns.BidImpliedSize.ToString(), GridColumnSettingsFeatureFlags.ImmutableFontColor },
|
||||
{ Columns.BidDirectSize.ToString(), GridColumnSettingsFeatureFlags.ImmutableFontColor },
|
||||
{ Columns.BidMergedSize.ToString(), GridColumnSettingsFeatureFlags.ImmutableFontColor },
|
||||
{ Columns.AskImpliedSize.ToString(), GridColumnSettingsFeatureFlags.ImmutableFontColor },
|
||||
{ Columns.AskDirectSize.ToString(), GridColumnSettingsFeatureFlags.ImmutableFontColor },
|
||||
{ Columns.AskMergedSize.ToString(), GridColumnSettingsFeatureFlags.ImmutableFontColor },
|
||||
{ Columns.Bid.ToString(), GridColumnSettingsFeatureFlags.ImmutableFontColor | GridColumnSettingsFeatureFlags.ImmutableBackgroundColor },
|
||||
{ Columns.Ask.ToString(), GridColumnSettingsFeatureFlags.ImmutableFontColor | GridColumnSettingsFeatureFlags.ImmutableBackgroundColor},
|
||||
{ Columns.WorkingAsks.ToString(), GridColumnSettingsFeatureFlags.ImmutableFontColor },
|
||||
{ Columns.WorkingBids.ToString(), GridColumnSettingsFeatureFlags.ImmutableFontColor }
|
||||
};
|
||||
@@ -145,12 +139,14 @@ namespace mbts.spark {
|
||||
ask_direct_size_filter.load_state(filters.ask_direct_size);
|
||||
ask_implied_size_filter.load_state(filters.ask_implied_size);
|
||||
last_price_filter.load_state(filters.last_price);
|
||||
last_price_from_spread_filter.load_state(filters.last_price_from_spread);
|
||||
last_size_filter.load_state(filters.last_size);
|
||||
day_change_filter.load_state(filters.day_change);
|
||||
settlement_filter.load_state(filters.settlement);
|
||||
session_low_filter.load_state(filters.session_low);
|
||||
session_high_filter.load_state(filters.session_high);
|
||||
position_filter.load_state(filters.position);
|
||||
raw_day_position_filter.load_state(filters.raw_day_position);
|
||||
working_bid_volume_filter.load_state(filters.working_bid_volume);
|
||||
working_ask_volume_filter.load_state(filters.working_ask_volume);
|
||||
volume_filter.load_state(filters.volume);
|
||||
@@ -161,8 +157,8 @@ namespace mbts.spark {
|
||||
}), DataGridFilterHelper.hook_filters(rows_view, security_filter,
|
||||
bid_price_filter, bid_merged_size_filter, bid_direct_size_filter, bid_implied_size_filter,
|
||||
ask_price_filter, ask_merged_size_filter, ask_direct_size_filter, ask_implied_size_filter,
|
||||
last_price_filter, last_size_filter, day_change_filter, settlement_filter,
|
||||
session_low_filter, session_high_filter, position_filter, working_bid_volume_filter, working_ask_volume_filter, volume_filter, security_key_filter),
|
||||
last_price_filter, last_price_from_spread_filter, last_size_filter, day_change_filter, settlement_filter,
|
||||
session_low_filter, session_high_filter, position_filter, raw_day_position_filter, working_bid_volume_filter, working_ask_volume_filter, volume_filter, security_key_filter),
|
||||
settings_manager.subscribe_current().OnDispatcher().Subscribe(grid_settings_manager),
|
||||
WorkLoop.Start("MarketView", _refresh)
|
||||
);
|
||||
@@ -224,12 +220,14 @@ namespace mbts.spark {
|
||||
public IDataGridColumnPersistentFilter<Row, UIntMinMaxState> ask_direct_size_filter { get; } = new UIntMinMax<Row>(r => r.ask_direct_size, nameof(Row.ask_direct_size));
|
||||
public IDataGridColumnPersistentFilter<Row, UIntMinMaxState> ask_implied_size_filter { get; } = new UIntMinMax<Row>(r => r.ask_implied_size, nameof(Row.ask_implied_size));
|
||||
public IDataGridColumnPersistentFilter<Row, DoubleMinMaxState> last_price_filter { get; } = new DoubleMinMax<Row>(r => r.last_price, nameof(Row.last_price));
|
||||
public IDataGridColumnPersistentFilter<Row, string> last_price_from_spread_filter { get; } = new RegexFilterVM<Row>(r => r.last_price_from_spread.ToString(), nameof(Row.last_price_from_spread));
|
||||
public IDataGridColumnPersistentFilter<Row, UIntMinMaxState> last_size_filter { get; } = new UIntMinMax<Row>(r => r.last_size, nameof(Row.last_size));
|
||||
public IDataGridColumnPersistentFilter<Row, DoubleMinMaxState> day_change_filter { get; } = new DoubleMinMax<Row>(r => r.day_change, nameof(Row.day_change));
|
||||
public IDataGridColumnPersistentFilter<Row, DoubleMinMaxState> settlement_filter { get; } = new DoubleMinMax<Row>(r => r.settlement, nameof(Row.settlement));
|
||||
public IDataGridColumnPersistentFilter<Row, DoubleMinMaxState> session_low_filter { get; } = new DoubleMinMax<Row>(r => r.session_low, nameof(Row.session_low));
|
||||
public IDataGridColumnPersistentFilter<Row, DoubleMinMaxState> session_high_filter { get; } = new DoubleMinMax<Row>(r => r.session_high, nameof(Row.session_high));
|
||||
public IDataGridColumnPersistentFilter<Row, IntMinMaxState> position_filter { get; } = new IntMinMax<Row>(r => r.position, nameof(Row.position));
|
||||
public IDataGridColumnPersistentFilter<Row, DoubleMinMaxState> raw_day_position_filter { get; } = new DoubleMinMax<Row>(r => r.raw_day_position, nameof(Row.raw_day_position));
|
||||
public IDataGridColumnPersistentFilter<Row, IntMinMaxState> working_bid_volume_filter { get; } = new IntMinMax<Row>(r => r.working_bid_volume, nameof(Row.working_bid_volume));
|
||||
public IDataGridColumnPersistentFilter<Row, IntMinMaxState> working_ask_volume_filter { get; } = new IntMinMax<Row>(r => r.working_ask_volume, nameof(Row.working_ask_volume));
|
||||
public IDataGridColumnPersistentFilter<Row, ULongMinMaxState> volume_filter { get; } = new ULongMinMax<Row>(r => r.volume, nameof(Row.volume));
|
||||
@@ -255,12 +253,14 @@ namespace mbts.spark {
|
||||
ask_direct_size = ask_direct_size_filter.get_state(),
|
||||
ask_implied_size = ask_implied_size_filter.get_state(),
|
||||
last_price = last_price_filter.get_state(),
|
||||
last_price_from_spread = last_price_from_spread_filter.get_state(),
|
||||
last_size = last_size_filter.get_state(),
|
||||
day_change = day_change_filter.get_state(),
|
||||
settlement = settlement_filter.get_state(),
|
||||
session_low = session_low_filter.get_state(),
|
||||
session_high = session_high_filter.get_state(),
|
||||
position = position_filter.get_state(),
|
||||
raw_day_position = raw_day_position_filter.get_state(),
|
||||
working_bid_volume = working_bid_volume_filter.get_state(),
|
||||
working_ask_volume = working_ask_volume_filter.get_state(),
|
||||
volume = volume_filter.get_state(),
|
||||
|
||||
@@ -8,8 +8,35 @@ namespace mbts.ui.spark {
|
||||
/// Interaction logic for MarketSheetsView.xaml
|
||||
/// </summary>
|
||||
partial class MarketViewView : UserControl {
|
||||
public enum Columns { Security, Volume, Last, LastSize, Position, WorkingBids, Bid, BidMergedSize, BidDirectSize, BidImpliedSize, Ask, AskMergedSize, AskDirectSize, AskImpliedSize, WorkingAsks, Settlement, DayChange, SessionLow, SessionHigh, SecurityKey,
|
||||
MarketDescription, ClearedAlias, ProductDescription, HubAlias, StripName, MicCode
|
||||
public enum Columns {
|
||||
Security,
|
||||
Volume,
|
||||
Last,
|
||||
LastSpd,
|
||||
LastSize,
|
||||
Position,
|
||||
RawDayPosition,
|
||||
WorkingBids,
|
||||
Bid,
|
||||
BidMergedSize,
|
||||
BidDirectSize,
|
||||
BidImpliedSize,
|
||||
Ask,
|
||||
AskMergedSize,
|
||||
AskDirectSize,
|
||||
AskImpliedSize,
|
||||
WorkingAsks,
|
||||
Settlement,
|
||||
DayChange,
|
||||
SessionLow,
|
||||
SessionHigh,
|
||||
SecurityKey,
|
||||
MarketDescription,
|
||||
ClearedAlias,
|
||||
ProductDescription,
|
||||
HubAlias,
|
||||
StripName,
|
||||
MicCode
|
||||
}
|
||||
|
||||
public MarketViewView() {
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace mbts.spark {
|
||||
_selected_security_criteria_backing,
|
||||
_sorted_selected_security_criteria_backing;
|
||||
|
||||
public MarketViewWindow(MarketViewWindowFactory factory, IBus bus, OrdersModel orders_model, MarketViewWindowFactory.StartupData state, WindowSettingsManager<GridSettings> settings_manager)
|
||||
public MarketViewWindow(MarketViewWindowFactory factory, IBus bus, OrdersModel orders_model, MarketViewWindowFactory.StartupData state, IWindowSettingsManager<GridSettings> settings_manager)
|
||||
: base("Market View", bus, factory, SparkCommands.ShowMarketView.icon) {
|
||||
_orders_model = orders_model;
|
||||
_state = state;
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using bts.api;
|
||||
using bts.proto;
|
||||
using bts.settings;
|
||||
using mbts.persist;
|
||||
using mbts.spark;
|
||||
using mbts.spark.filters;
|
||||
@@ -7,6 +9,7 @@ using mbts.ui.settings;
|
||||
using ProtoBuf;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
using System.Threading.Tasks;
|
||||
@@ -35,13 +38,8 @@ namespace bts.shell {
|
||||
void _show(SecurityCriteria criteria) =>
|
||||
_bus.post(SparkTags.ShowWindow, _create(StartupData.Default(criteria)));
|
||||
|
||||
IShellWindow _create(StartupData state) {
|
||||
var settings_manager = new WindowSettingsManager<GridSettings>(_settings_hub,
|
||||
state.grid,
|
||||
get: us => us.market_view_grid,
|
||||
set: (us, gs) => us.with(provided_market_view_gridsettings: gs));
|
||||
return new MarketViewWindow(this, _bus, _orders_model, state, settings_manager);
|
||||
}
|
||||
IShellWindow _create(StartupData state) =>
|
||||
new MarketViewWindow(this, _bus, _orders_model, state, _settings_hub.create_mview_settings_manager(state.grid));
|
||||
|
||||
[ProtoContract]
|
||||
public class StartupData {
|
||||
@@ -68,7 +66,29 @@ namespace bts.shell {
|
||||
_sorting_criteria = sort;
|
||||
}
|
||||
|
||||
public static GridSettings DefaultGridSettings => GridSettings.Default.with(DefaultColumns.all, DefaultColumns.default_sorting_criterion);
|
||||
public static GridSettings sanitize(GridSettings s) {
|
||||
if (s == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// column upgrade
|
||||
var columns = s.columns.ToList();
|
||||
var bid_col_index = columns.FindIndex(x => x.id == col_id(Columns.Bid));
|
||||
var ask_col_index = columns.FindIndex(x => x.id == col_id(Columns.Ask));
|
||||
if (bid_col_index > -1 && ask_col_index > -1) {
|
||||
if (!columns[bid_col_index].background_color_override.HasValue) {
|
||||
columns[bid_col_index] = columns[bid_col_index].with(background_color_override: new NullableColorProto(BTSColors.MarketData.bid.ToUint()));
|
||||
}
|
||||
if (!columns[ask_col_index].background_color_override.HasValue) {
|
||||
columns[ask_col_index] = columns[ask_col_index].with(background_color_override: new NullableColorProto(BTSColors.MarketData.ask.ToUint()));
|
||||
}
|
||||
}
|
||||
// and enable background color upgrade
|
||||
return s.with(columns, enable_background_color: true);
|
||||
}
|
||||
|
||||
|
||||
public static GridSettings DefaultGridSettings => GridSettings.Default.with(DefaultColumns.all, DefaultColumns.default_sorting_criterion, enable_background_color: true);
|
||||
|
||||
public IReadOnlyList<SortingCriteria> sorting_criterion => _sorting_criteria ?? (_sorting_criteria = DefaultColumns.default_sorting_criterion.ToList());
|
||||
|
||||
@@ -80,14 +100,16 @@ namespace bts.shell {
|
||||
public static GridColumnSettings security => new GridColumnSettings(col_id(Columns.Security), DefaultColumnHeaders.Security, width: DefaultColumnWidths.Security);
|
||||
public static GridColumnSettings volume => new GridColumnSettings(col_id(Columns.Volume), DefaultColumnHeaders.Volume, width: DefaultColumnWidths.Volume);
|
||||
public static GridColumnSettings last => new GridColumnSettings(col_id(Columns.Last), DefaultColumnHeaders.Last, width: DefaultColumnWidths.Price);
|
||||
public static GridColumnSettings last_from_spread => new GridColumnSettings(col_id(Columns.LastSpd), DefaultColumnHeaders.S, width: DefaultColumnWidths.Price, is_visible: false);
|
||||
public static GridColumnSettings last_size => new GridColumnSettings(col_id(Columns.LastSize), DefaultColumnHeaders.Size, width: DefaultColumnWidths.Size, horizontal_alignment: System.Windows.HorizontalAlignment.Right);
|
||||
public static GridColumnSettings position => new GridColumnSettings(col_id(Columns.Position), DefaultColumnHeaders.Pos, width: DefaultColumnWidths.Size, horizontal_alignment: System.Windows.HorizontalAlignment.Right);
|
||||
public static GridColumnSettings raw_day_position => new GridColumnSettings(col_id(Columns.RawDayPosition), DefaultColumnHeaders.RawDayPos, width: DefaultColumnWidths.Size, horizontal_alignment: System.Windows.HorizontalAlignment.Right, is_visible: false);
|
||||
public static GridColumnSettings working_bids => new GridColumnSettings(col_id(Columns.WorkingBids), DefaultColumnHeaders.Working, font_color_override: BTSColors.MarketData.bid, width: DefaultColumnWidths.Working, horizontal_alignment: System.Windows.HorizontalAlignment.Right);
|
||||
public static GridColumnSettings bid_implied_size => new GridColumnSettings(col_id(Columns.BidImpliedSize), DefaultColumnHeaders.ImpliedSize, font_color_override: BTSColors.MarketData.bid, width: DefaultColumnWidths.ImpliedDirectMergedSize, horizontal_alignment: System.Windows.HorizontalAlignment.Right);
|
||||
public static GridColumnSettings bid_direct_size => new GridColumnSettings(col_id(Columns.BidDirectSize), DefaultColumnHeaders.DirectSize, font_color_override: BTSColors.MarketData.bid, width: DefaultColumnWidths.ImpliedDirectMergedSize, horizontal_alignment: System.Windows.HorizontalAlignment.Right);
|
||||
public static GridColumnSettings bid_merged_size => new GridColumnSettings(col_id(Columns.BidMergedSize), DefaultColumnHeaders.MergedSize, font_color_override: BTSColors.MarketData.bid, width: DefaultColumnWidths.ImpliedDirectMergedSize, horizontal_alignment: System.Windows.HorizontalAlignment.Right);
|
||||
public static GridColumnSettings bid => new GridColumnSettings(col_id(Columns.Bid), DefaultColumnHeaders.Bid, font_color_override: BTSColors.header_text, width:DefaultColumnWidths.MViewPrice, horizontal_alignment: System.Windows.HorizontalAlignment.Right);
|
||||
public static GridColumnSettings ask => new GridColumnSettings(col_id(Columns.Ask), DefaultColumnHeaders.Ask, font_color_override: BTSColors.header_text, width: DefaultColumnWidths.MViewPrice, horizontal_alignment: System.Windows.HorizontalAlignment.Right);
|
||||
public static GridColumnSettings bid => new GridColumnSettings(col_id(Columns.Bid), DefaultColumnHeaders.Bid, font_color_override: BTSColors.header_text, width:DefaultColumnWidths.MViewPrice, horizontal_alignment: System.Windows.HorizontalAlignment.Right, background_color_override: BTSColors.MarketData.bid);
|
||||
public static GridColumnSettings ask => new GridColumnSettings(col_id(Columns.Ask), DefaultColumnHeaders.Ask, font_color_override: BTSColors.header_text, width: DefaultColumnWidths.MViewPrice, horizontal_alignment: System.Windows.HorizontalAlignment.Right, background_color_override: BTSColors.MarketData.ask);
|
||||
public static GridColumnSettings ask_merged_size => new GridColumnSettings(col_id(Columns.AskMergedSize), DefaultColumnHeaders.MergedSize, font_color_override: BTSColors.MarketData.ask, width: DefaultColumnWidths.ImpliedDirectMergedSize, horizontal_alignment: System.Windows.HorizontalAlignment.Right);
|
||||
public static GridColumnSettings ask_direct_size => new GridColumnSettings(col_id(Columns.AskDirectSize), DefaultColumnHeaders.DirectSize, font_color_override: BTSColors.MarketData.ask, width: DefaultColumnWidths.ImpliedDirectMergedSize, horizontal_alignment: System.Windows.HorizontalAlignment.Right);
|
||||
public static GridColumnSettings ask_implied_size => new GridColumnSettings(col_id(Columns.AskImpliedSize), DefaultColumnHeaders.ImpliedSize, font_color_override: BTSColors.MarketData.ask, width: DefaultColumnWidths.ImpliedDirectMergedSize, horizontal_alignment: System.Windows.HorizontalAlignment.Right);
|
||||
@@ -117,8 +139,10 @@ namespace bts.shell {
|
||||
yield return security;
|
||||
yield return volume;
|
||||
yield return last;
|
||||
yield return last_from_spread;
|
||||
yield return last_size;
|
||||
yield return position;
|
||||
yield return raw_day_position;
|
||||
yield return working_bids;
|
||||
yield return bid_implied_size;
|
||||
yield return bid_direct_size;
|
||||
@@ -173,6 +197,8 @@ namespace bts.shell {
|
||||
public DoubleMinMaxState session_high;
|
||||
[ProtoMember(12)]
|
||||
public IntMinMaxState position;
|
||||
[ProtoMember(27)]
|
||||
public DoubleMinMaxState raw_day_position;
|
||||
[ProtoMember(13)]
|
||||
public IntMinMaxState working_bid_volume;
|
||||
[ProtoMember(14)]
|
||||
@@ -200,7 +226,50 @@ namespace bts.shell {
|
||||
[ProtoMember(25)]
|
||||
public string strip_name;
|
||||
[ProtoMember(26)]
|
||||
public string last_price_from_spread;
|
||||
[ProtoMember(28)]
|
||||
public string mic_code;
|
||||
}
|
||||
|
||||
// migration rules
|
||||
[Export(typeof(IMarketViewGridSettingsMigrationRule))]
|
||||
class AddMissingColumnsMigrationRule : IMarketViewGridSettingsMigrationRule {
|
||||
public bool apply(GridSettings settings, out GridSettings new_settings) =>
|
||||
settings.add_missing_columns(StartupData.DefaultGridSettings.columns, out new_settings);
|
||||
}
|
||||
|
||||
[Export(typeof(IMarketViewGridSettingsMigrationRule))]
|
||||
class InitBidAskBackgroundOverrideMigrationRule : IMarketViewGridSettingsMigrationRule {
|
||||
public bool apply(GridSettings s, out GridSettings new_settings) {
|
||||
var columns = s.columns.ToList();
|
||||
var bid_col_index = columns.FindIndex(x => x.id == col_id(Columns.Bid));
|
||||
var ask_col_index = columns.FindIndex(x => x.id == col_id(Columns.Ask));
|
||||
bool applied = false;
|
||||
if (bid_col_index > -1 && ask_col_index > -1) {
|
||||
if (!columns[bid_col_index].background_color_override.HasValue) {
|
||||
columns[bid_col_index] = columns[bid_col_index].with(background_color_override: new NullableColorProto(BTSColors.MarketData.bid.ToUint()));
|
||||
applied = true;
|
||||
}
|
||||
if (!columns[ask_col_index].background_color_override.HasValue) {
|
||||
columns[ask_col_index] = columns[ask_col_index].with(background_color_override: new NullableColorProto(BTSColors.MarketData.ask.ToUint()));
|
||||
applied = true;
|
||||
}
|
||||
}
|
||||
new_settings = applied ? s.with(columns) : default;
|
||||
return applied;
|
||||
}
|
||||
}
|
||||
|
||||
[Export(typeof(IMarketViewGridSettingsMigrationRule))]
|
||||
class InitBackgroundOverrideMigrationRule : IMarketViewGridSettingsMigrationRule {
|
||||
public bool apply(GridSettings settings, out GridSettings new_settings) {
|
||||
if (!settings.enable_background_color) {
|
||||
new_settings = settings.with(enable_background_color: true);
|
||||
return true;
|
||||
}
|
||||
new_settings = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,16 +7,6 @@ using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
|
||||
namespace mbts.spark {
|
||||
struct TradeInfo {
|
||||
public readonly SecurityImmutable security;
|
||||
public readonly TradeMessageImmutable trade;
|
||||
|
||||
public TradeInfo(SecurityImmutable security, TradeMessageImmutable trade) {
|
||||
this.security = security;
|
||||
this.trade = trade;
|
||||
}
|
||||
}
|
||||
|
||||
class TimeAndSalesModel : IDisposable {
|
||||
internal readonly SecurityCriteria security_criteria;
|
||||
|
||||
|
||||
@@ -137,7 +137,7 @@ namespace mbts.spark {
|
||||
public Row(TimeAndSalesVM parent, SecurityImmutable security, TradeMessageImmutable trade) : base(security) {
|
||||
_trade_key = trade.Key;
|
||||
time = ((ulong)trade.Time).lldatetime().ToLocalTime();
|
||||
price = trade.Mantissa * Math.Pow(10, trade.Exponent);
|
||||
price = trade.price();
|
||||
size = trade.Size;
|
||||
aggressor_side = trade.AggressorSide;
|
||||
show_ladder = new DelegateCommand(() => parent._show_ladder_async(this).ignore());
|
||||
|
||||
@@ -26,7 +26,10 @@ namespace bts.ui {
|
||||
public SettingsShellModule(IBus bus, UserSettingsHub settings_hub, WorkspacesModel ws) {
|
||||
// todo: settings dialog
|
||||
ws_model = ws;
|
||||
var actions_list = new List<SparkCommand>(2) { SparkCommands.ShowWorkspaces };
|
||||
var actions_list = new List<SparkCommand>(2) {
|
||||
SparkCommands.ShowGlobalAlerts,
|
||||
SparkCommands.ShowWorkspaces
|
||||
};
|
||||
if (Configuration.get<bts.config.toggles.ToastNotifications>().enabled) {
|
||||
actions_list.Add(SparkCommands.ShowSettings);
|
||||
}
|
||||
|
||||
@@ -227,7 +227,7 @@ namespace mbts.ui.spark {
|
||||
}
|
||||
|
||||
DataGridColumn _column_factory(LegSpreaderParamsTuple l) {
|
||||
var col = new DataGridColumnInternal(l.leg.Security, ParameterCellTemplateConverter, ParameterCellEditingTemplateConverter) { Width = 75, };
|
||||
var col = new DataGridColumnInternal(l.leg.Security, ParameterCellTemplateConverter, ParameterCellEditingTemplateConverter);
|
||||
col.HeaderTemplate = (DataTemplate)FindResource(IsNew ? RemovableColumnHeaderTemplateKey : NonRemovableColumnHeaderTemplateKey);
|
||||
DataGridEx.SetRightBorder(col, new DataGridExVerticalLine(false, true, Colors.DarkGray, 1));
|
||||
return col;
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using bts.api;
|
||||
using bts;
|
||||
using bts.api;
|
||||
using bts.api.core;
|
||||
using bts.api.synthetic;
|
||||
using bts.collections;
|
||||
using bts.spark;
|
||||
using mbts.ui.shell;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
@@ -18,11 +20,36 @@ namespace mbts.spark {
|
||||
readonly uint _user_id;
|
||||
|
||||
[ImportingConstructor]
|
||||
public SpreaderModel(IBus bus, SyntheticSecurityService service, ErrorReporter error, [Import(LoginContainer.Exports.UserID)]uint user_id) {
|
||||
public SpreaderModel(IBus bus, SyntheticSecurityService service, AdminModel admin_model, ErrorReporter error, UserTuple user) {
|
||||
_bus = bus;
|
||||
_service = service;
|
||||
_error = error;
|
||||
_user_id = user_id;
|
||||
_user_id = user.id;
|
||||
// synthetic tuples
|
||||
var strategy_source = _bus.subscribe(SparkTags.SyntheticstrategiesTag)
|
||||
.Select(map => MappedDictionary.create<uint, ExecutionStrategyImmutable, (uint security_id, ExecutionStrategyImmutable strategy)>(map, (k, v) => (k, v)))
|
||||
.Table(tup => tup.security_id);
|
||||
|
||||
var synthetic_source = _bus.subscribe(SparkTags.SecuritiesTag)
|
||||
.Select(map => new FilteredDictionary<uint, SecurityMD>(map, smd => smd.security.ContractCase == Security.ContractOneofCase.Synthetic))
|
||||
.Table(smd => smd.security.Id);
|
||||
|
||||
var synthetic_user_join = synthetic_source.LeftJoin(
|
||||
admin_model.all_user_tuples,
|
||||
SecurityMD.key_fn,
|
||||
UserTuple.key_fn,
|
||||
smd => smd.security.Synthetic.UserId,
|
||||
(smd, sid, ut, uid) => new SyntheticTuple(smd.security, ut.name, null),
|
||||
(smd, sid, uid) => new SyntheticTuple(smd.security, null, null),
|
||||
SyntheticTuple.key_fn);
|
||||
|
||||
synthetic_tuples = synthetic_user_join.LeftJoin(
|
||||
strategy_source,
|
||||
SyntheticTuple.key_fn,
|
||||
tup => tup.security_id,
|
||||
(synth_tup, id, strat_tup) => new SyntheticTuple(synth_tup.security, synth_tup.user_name, strat_tup.strategy),
|
||||
(synth_tup, id) => synth_tup,
|
||||
SyntheticTuple.key_fn);
|
||||
}
|
||||
|
||||
public IObservable<IReadOnlyDictionary<uint, ExecutionStrategyImmutable>> strategy => _bus.subscribe(SparkTags.SyntheticstrategiesTag);
|
||||
@@ -36,6 +63,8 @@ namespace mbts.spark {
|
||||
.LeftJoin(strategies, (security, strategy) => (new ExecutionStrategyImmutable?(strategy), security), security => (new ExecutionStrategyImmutable?(), security))
|
||||
);
|
||||
|
||||
public IObservable<TableUpdate<SyntheticTuple, uint>> synthetic_tuples { get; }
|
||||
|
||||
public IObservable<ExecutionStrategyImmutable> security_strategy(uint security_key) =>
|
||||
strategy.TrySelect(s => {
|
||||
bool success = s.TryGetValue(security_key, out ExecutionStrategyImmutable result);
|
||||
|
||||
@@ -81,9 +81,9 @@ namespace bts.shell {
|
||||
#region QuoteParams
|
||||
public static QuoteParams QuoteParams => new QuoteParams {
|
||||
LeanQuantityRatio = 1,
|
||||
QuoteInsideMarketDistance = QuoteInsideMarketDistance,
|
||||
//QuoteInsideMarketDistance = QuoteInsideMarketDistance,
|
||||
QuoteMaxOrderMove = QuoteMaxOrderMove,
|
||||
QuoteMuteZone = QuoteMuteZone,
|
||||
//QuoteMuteZone = QuoteMuteZone,
|
||||
QuoteRepriceThrottle = QuoteRepriceThrottle,
|
||||
QuoteInsideMarketDistanceWithTravel = QuoteInsideMarketDistanceWithTravel,
|
||||
};
|
||||
@@ -113,6 +113,7 @@ namespace bts.shell {
|
||||
};
|
||||
public static QuoteInsideMarketDistanceWithTravel QuoteInsideMarketDistanceWithTravel => new QuoteInsideMarketDistanceWithTravel { Priority = RulePriority };
|
||||
public static QuoteInsideMarketDistance QuoteInsideMarketDistance => new QuoteInsideMarketDistance { Priority = RulePriority };
|
||||
public static QuoteInsideMarketDistanceThrottle QuoteInsideMarketDistanceThrottle => new QuoteInsideMarketDistanceThrottle();
|
||||
#endregion
|
||||
|
||||
#region PreHedge
|
||||
|
||||
@@ -7,8 +7,15 @@ namespace mbts.ui.spark {
|
||||
/// Interaction logic for SyntheticManagementView.xaml
|
||||
/// </summary>
|
||||
partial class SyntheticManagementView : UserControl {
|
||||
public enum Columns {
|
||||
Name,
|
||||
Description,
|
||||
n_legs,
|
||||
n_working_orders,
|
||||
SecurityKey,
|
||||
User
|
||||
}
|
||||
|
||||
public enum Columns { Name, Description, n_legs, n_working_orders, SecurityKey}
|
||||
public SyntheticManagementView() =>
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ using mbts.ui.utility;
|
||||
using mbts.utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
using System.Windows;
|
||||
@@ -27,7 +28,7 @@ namespace mbts.spark {
|
||||
readonly IWindowSettingsManager<GridSettings> _settings_manager;
|
||||
|
||||
|
||||
public SyntheticManagementWindow(SyntheticManagementWindowFactory factory, IBus bus, OrdersModel orders_model, StartupData state, WindowSettingsManager<GridSettings> settings_manager)
|
||||
public SyntheticManagementWindow(SyntheticManagementWindowFactory factory, IBus bus, OrdersModel orders_model, StartupData state, IWindowSettingsManager<GridSettings> settings_manager)
|
||||
: base("Synthetic Management", bus, factory, SparkCommands.ShowSyntheticManagement.icon) {
|
||||
_orders_model = orders_model;
|
||||
_state = state;
|
||||
@@ -66,8 +67,8 @@ namespace mbts.spark {
|
||||
), SparkCommand.create("Clone", Icons.CloneSynthetic, SparkTags.ShowSyntheticCloneTag).complete(
|
||||
current_row_connectable_builder.create(observe_row_strategy),
|
||||
rs => rs.HasValue, select_row_strategy_tuple
|
||||
), SparkCommands.ShowLadder(SparkCommands.KeyGestures.ShowLadder).complete(
|
||||
vm_connectable_builder.create(vm => vm.current_security_md), md => md.HasValue, ConvertUtils.ValueOrDefault
|
||||
), SparkCommands.ShowLadderAutoLookup(SparkCommands.KeyGestures.ShowLadder).complete(
|
||||
vm_connectable_builder.create(vm => vm.current_security_observable.Select(s => s.HasValue ? ImmutableHashSet<uint>.Empty.Add(s.Value.Id) : null)), id => id != null
|
||||
), SparkCommands.ShowOrders.complete(() => {
|
||||
var ob_settings = bts.shell.orderbook.OrderBookStartupData.Default;
|
||||
ob_settings.filters = new bts.shell.orderbook.FilterStates {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using bts.api;
|
||||
using bts.settings;
|
||||
using mbts.persist;
|
||||
using mbts.spark;
|
||||
using mbts.spark.filters;
|
||||
@@ -7,6 +8,7 @@ using mbts.ui.settings;
|
||||
using ProtoBuf;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Reactive.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using static mbts.ui.controls.DIYGrid;
|
||||
@@ -33,13 +35,8 @@ namespace bts.shell {
|
||||
public async void show(SparkTags.Nothing nothing) =>
|
||||
_bus.post(SparkTags.ShowWindow, await load(new StartupData()));
|
||||
|
||||
IShellWindow _create(StartupData state) {
|
||||
var settings_manager = new WindowSettingsManager<GridSettings>(_settings_hub,
|
||||
state.grid,
|
||||
get: us => us.synthetic_management_grid,
|
||||
set: (us, gs) => us.with(provided_synthetic_management_gridsettings: gs));
|
||||
return new SyntheticManagementWindow(this, _bus, _orders_model, state, settings_manager);
|
||||
}
|
||||
IShellWindow _create(StartupData state) =>
|
||||
new SyntheticManagementWindow(this, _bus, _orders_model, state, _settings_hub.create_synth_settings_manager(state.grid));
|
||||
|
||||
[ProtoContract]
|
||||
public class StartupData {
|
||||
@@ -67,6 +64,7 @@ namespace bts.shell {
|
||||
public static GridColumnSettings n_legs => new GridColumnSettings(col_id(Columns.n_legs), DefaultColumnHeaders.N_Legs, width: DefaultColumnWidths.N_Legs);
|
||||
public static GridColumnSettings n_working_orders => new GridColumnSettings(col_id(Columns.n_working_orders), DefaultColumnHeaders.N_Working_Orders, width: DefaultColumnWidths.N_Working_Orders);
|
||||
public static GridColumnSettings security_key => new GridColumnSettings(col_id(Columns.SecurityKey), DefaultColumnHeaders.SecurityKey, is_visible: false, width: DefaultColumnWidths.SecurityKey);
|
||||
public static GridColumnSettings user => new GridColumnSettings(col_id(Columns.User), DefaultColumnHeaders.User, is_visible: false, width: DefaultColumnWidths.User);
|
||||
|
||||
public static IEnumerable<SortingCriteria> default_sorting_criterion {
|
||||
get {
|
||||
@@ -81,6 +79,7 @@ namespace bts.shell {
|
||||
yield return n_legs;
|
||||
yield return n_working_orders;
|
||||
yield return security_key;
|
||||
yield return user;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,6 +100,15 @@ namespace bts.shell {
|
||||
public UIntMinMaxState n_working_orders;
|
||||
[ProtoMember(6)]
|
||||
public string security_key;
|
||||
[ProtoMember(7)]
|
||||
public uint[] user;
|
||||
}
|
||||
|
||||
// migration rules
|
||||
[Export(typeof(ISyntheticManagementMigrationRule))]
|
||||
class AddMissingColumnsMigrationRule : ISyntheticManagementMigrationRule {
|
||||
public bool apply(GridSettings settings, out GridSettings new_settings) =>
|
||||
settings.add_missing_columns(StartupData.DefaultGridSettings.columns, out new_settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
using bts.shell;
|
||||
using mbts.ui.spark;
|
||||
|
||||
namespace mbts.spark {
|
||||
partial class SyntheticEditorVM {
|
||||
class QuoteInsideMarketDistanceEnabledModel : RowModelBase<bool> {
|
||||
readonly QuoteInsideMarketDistanceTowardModel _toward;
|
||||
|
||||
public QuoteInsideMarketDistanceEnabledModel(QuoteInsideMarketDistanceTowardModel toward) =>
|
||||
_toward = toward;
|
||||
|
||||
public override string display_name { get; } = string.Empty;
|
||||
public override string help_text { get; } = string.Empty;
|
||||
public override string man_page { get; } = string.Empty;
|
||||
public override ParameterSection[] section_path { get; } = new[] { Sections.Quote, Subsections.InsideMarketDistance };
|
||||
|
||||
public override bool get_value(LegSpreaderParamsTuple leg_tup) =>
|
||||
leg_tup.leg_params.QuoteParams.QuoteInsideMarketDistanceThrottle != null;
|
||||
|
||||
public override void set_value(LegSpreaderParamsTuple leg_tup, bool value) {
|
||||
if (value) {
|
||||
if (leg_tup.leg_params.QuoteParams.QuoteInsideMarketDistanceThrottle == null) {
|
||||
leg_tup.leg_params.QuoteParams.QuoteInsideMarketDistanceThrottle = SyntheticDataHelper.Defaults.QuoteInsideMarketDistanceThrottle;
|
||||
_toward.apply_value(leg_tup);
|
||||
}
|
||||
} else {
|
||||
leg_tup.leg_params.QuoteParams.QuoteInsideMarketDistanceThrottle = null;
|
||||
}
|
||||
_toward.set_enabled(leg_tup, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
using bts.spark;
|
||||
using mbts.ui.spark;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace mbts.spark {
|
||||
partial class SyntheticEditorVM {
|
||||
class QuoteInsideMarketDistanceTowardModel : RowModelBase<uint> {
|
||||
IDictionary<uint, uint> _value_store = new Dictionary<uint, uint>();
|
||||
|
||||
public override string display_name { get; } = "Toward Distance";
|
||||
public override string help_text { get; } = string.Empty;
|
||||
public override string man_page { get; } = string.Empty;
|
||||
public override ParameterSection[] section_path { get; } = new[] { Sections.Quote, Subsections.InsideMarketDistance };
|
||||
|
||||
public void apply_value(LegSpreaderParamsTuple leg_tup) =>
|
||||
_get_inside_market_distance(leg_tup).OnTowardDistance = _value_from_store(leg_tup);
|
||||
|
||||
public override uint get_value(LegSpreaderParamsTuple leg_tup) =>
|
||||
_get_inside_market_distance(leg_tup) is QuoteInsideMarketDistanceThrottle inside_market_distance ?
|
||||
inside_market_distance.OnTowardDistance :
|
||||
_value_from_store(leg_tup);
|
||||
|
||||
public override void set_value(LegSpreaderParamsTuple leg_tup, uint value) {
|
||||
_value_store[leg_tup.SecurityKey] = value;
|
||||
if (_get_inside_market_distance(leg_tup) is QuoteInsideMarketDistanceThrottle inside_market_distance)
|
||||
inside_market_distance.OnTowardDistance = value;
|
||||
}
|
||||
|
||||
protected override bool _get_enabled(LegSpreaderParamsTuple leg_tup) =>
|
||||
_get_inside_market_distance(leg_tup) != null;
|
||||
|
||||
QuoteInsideMarketDistanceThrottle _get_inside_market_distance(LegSpreaderParamsTuple leg_tup) =>
|
||||
leg_tup.leg_params.QuoteParams.QuoteInsideMarketDistanceThrottle;
|
||||
|
||||
uint _value_from_store(LegSpreaderParamsTuple leg_tup) =>
|
||||
_value_store.GetValueOrDefault(leg_tup.SecurityKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -115,6 +115,11 @@ namespace mbts.spark {
|
||||
"dictates if this logic applies to the quoting market or to the synthetic spread " +
|
||||
"market");
|
||||
|
||||
public static ParameterSection InsideMarketDistance =>
|
||||
new ParameterSection("Inside Market Distance", true,
|
||||
"Reduces re-quoting by throttling quotes that are moving toward the inside market " +
|
||||
"but are more than 'Toward Distance' away from the inside market");
|
||||
|
||||
public static ParameterSection InsideMarketThrottleThresholds =>
|
||||
new ParameterSection("Inside Market Throttle Thresholds", true,
|
||||
"Reduces re-quoting for quotes that are moving toward the inside market. " +
|
||||
|
||||
@@ -190,6 +190,8 @@ namespace mbts.spark {
|
||||
var quote_inside_market_throttle_ticks = new QuoteInsideMarketThrottleTicksModel();
|
||||
var quote_inside_market_throttle_min_move = new QuoteInsideMarketThrottleMinMoveModel();
|
||||
|
||||
var quote_inside_market_distance_toward = new QuoteInsideMarketDistanceTowardModel();
|
||||
|
||||
var pre_hedge_payless_threshold = new PreHedgePaylessThresholdModel();
|
||||
var pre_hedge_payless_ticks = new PreHedgePaylessTicksModel();
|
||||
|
||||
@@ -227,6 +229,8 @@ namespace mbts.spark {
|
||||
//quote_inside_market_throttle_ticks,
|
||||
//quote_inside_market_throttle_min_move,
|
||||
//new MaxTicksInsideMarketModel(),
|
||||
new QuoteInsideMarketDistanceEnabledModel(quote_inside_market_distance_toward),
|
||||
quote_inside_market_distance_toward,
|
||||
new PreHedgePaylessEnabledModel(pre_hedge_payless_threshold, pre_hedge_payless_ticks),
|
||||
pre_hedge_payless_threshold,
|
||||
pre_hedge_payless_ticks,
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
using bts.api;
|
||||
using bts;
|
||||
using bts.api;
|
||||
using bts.collections;
|
||||
using bts.spark;
|
||||
using bts.utils;
|
||||
using mbts.persist;
|
||||
using mbts.spark.filters;
|
||||
using mbts.ui;
|
||||
using mbts.ui.settings;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
@@ -17,43 +20,45 @@ using static mbts.ui.controls.DIYGrid;
|
||||
using static mbts.ui.spark.SyntheticManagementView;
|
||||
|
||||
namespace mbts.spark {
|
||||
class SyntheticManagementDialogVM : SecurityMDGrid<SyntheticManagementDialogVM.Row, (ExecutionStrategyImmutable? strategy, SecurityMD md)> {
|
||||
class SyntheticManagementDialogVM : SecurityGrid<SyntheticManagementDialogVM.Row, SyntheticTuple> {
|
||||
readonly IBus _bus;
|
||||
readonly OrdersModel _orders_model;
|
||||
IWindowSettingsManager<GridSettings> _settings_manager;
|
||||
|
||||
readonly IWindowSettingsManager<GridSettings> _settings_manager;
|
||||
|
||||
public SyntheticManagementDialogVM(IBus bus, OrdersModel orders_model, IWindowSettingsManager<GridSettings> settings_manager) : this(bus, orders_model, settings_manager, null, null) { }
|
||||
public SyntheticManagementDialogVM(IBus bus, OrdersModel orders_model, IWindowSettingsManager<GridSettings> settings_manager, IReadOnlyCollection<SortingCriteria> sorting, FilterStates filters)
|
||||
: base(orders_model.spreader.strategy_tuple.Select(map => map.Values), sorting) {
|
||||
: base(orders_model.spreader.synthetic_tuples.Select(t => t.state.Values), sorting) {
|
||||
_bus = bus;
|
||||
_orders_model = orders_model;
|
||||
_settings_manager = settings_manager;
|
||||
// init filters
|
||||
user_filter = DiscreteValuesFilterVM.CreateTableUpdate<Row, UserTuple, uint>(r => r.user_tuple, UserTuple.key_fn, out var user_filter_items_observer, out var user_filter_items_view, nameof(Row.user_tuple));
|
||||
user_filter_items_view.CustomSort = Comparer<string>.Default.wrap<string, UserTuple>(ut => ut.name).to_non_generic();
|
||||
if (filters != null) {
|
||||
create_time_filter.load_state(filters.create_time);
|
||||
name_filter.load_state(filters.name);
|
||||
description_filter.load_state(filters.description);
|
||||
n_legs_filter.load_state(filters.n_legs);
|
||||
n_working_orders_filter.load_state(filters.n_working_orders);
|
||||
security_key_filter.load_state(filters.security_key);
|
||||
security_key_filter.load_state(filters.security_key);
|
||||
user_filter.load_state(filters.user);
|
||||
}
|
||||
_settings_manager = settings_manager;
|
||||
// columns
|
||||
add_col(Columns.Name, DefaultColumnHeaders.Name, r => r.name, nameof(Row.name), name_filter, DataGridFilterKnownTemplates.Regex, DefaultColumnWidths.Security);
|
||||
add_col(Columns.Description, DefaultColumnHeaders.Description, r => r.description, nameof(Row.description), description_filter, DataGridFilterKnownTemplates.Regex, DefaultColumnWidths.Description);
|
||||
add_col(Columns.n_legs, DefaultColumnHeaders.N_Legs, r => r.n_legs.ToString(), nameof(Row.n_legs), n_legs_filter, DataGridFilterKnownTemplates.IntMinMax, DefaultColumnWidths.N_Legs);
|
||||
columns.Add(new HyperlinkElementColumn<Row, Columns>(
|
||||
Columns.n_working_orders,
|
||||
new Binding(nameof(Row.n_working_orders)),
|
||||
Columns.n_working_orders,
|
||||
new Binding(nameof(Row.n_working_orders)),
|
||||
new Binding(nameof(Row.show_order_book)),
|
||||
n_working_orders_filter,
|
||||
DataGridFilterKnownTemplates.UIntMinMax) {
|
||||
id = col_id(Columns.n_working_orders),
|
||||
Header = DefaultColumnHeaders.N_Working_Orders,
|
||||
Width = DefaultColumnWidths.N_Working_Orders
|
||||
}
|
||||
);
|
||||
});
|
||||
add_col(Columns.SecurityKey, DefaultColumnHeaders.SecurityKey, r => r.security_key.ToString(), nameof(Row.security_key), security_key_filter, DataGridFilterKnownTemplates.Regex, DefaultColumnWidths.SecurityKey);
|
||||
|
||||
add_col(Columns.User, DefaultColumnHeaders.User, r => r.user_name, nameof(Row.user_name), user_filter, DataGridFilterKnownTemplates.DiscreteValues, DefaultColumnWidths.User);
|
||||
//
|
||||
void add_col(Columns col_key, string header, Func<Row, string> get_text, string prop, IDataGridColumnFilter filter, string filter_template, double width) =>
|
||||
columns.Add(new RenderTextColumn<Row, Columns>(col_key, get_text, filter, filter_template) {
|
||||
@@ -63,42 +68,39 @@ namespace mbts.spark {
|
||||
Width = width
|
||||
});
|
||||
//
|
||||
grid_settings_manager = new SimpleGridSettingsManager<Row>(columns, new Dictionary<string, GridColumnSettingsFeatureFlags> { }, row_vms);
|
||||
grid_settings_manager = new SimpleGridSettingsManager<Row>(columns, DictionaryHelper.empty<string, GridColumnSettingsFeatureFlags>(), row_vms);
|
||||
// this will initialize the immutable properties that correspond to the col_settings_flags above (e.g. Bid/Ask font_color_override, etc.)
|
||||
grid_settings_manager.load_from(settings_manager.current_settings());
|
||||
|
||||
_resources.AddRange(
|
||||
DataGridFilterHelper.hook_filters(rows_view, create_time_filter, name_filter, description_filter, n_legs_filter, n_working_orders_filter, security_key_filter),
|
||||
orders_model.admin_model.all_user_tuples.OnDispatcher().Subscribe(user_filter_items_observer),
|
||||
DataGridFilterHelper.hook_all<SyntheticManagementDialogVM, Row>(this, rows_view),
|
||||
settings_manager.subscribe_current().OnDispatcher().Subscribe(grid_settings_manager)
|
||||
);
|
||||
}
|
||||
|
||||
protected override Row row_factory((ExecutionStrategyImmutable? strategy, SecurityMD md) row_model) =>
|
||||
new Row(_bus, row_model.md, row_model.strategy, _orders_model);
|
||||
|
||||
protected override void on_row_removed(Row row) => row.Dispose();
|
||||
|
||||
public ObservableCollection<ColumnBase> columns { get; } = new ObservableCollection<ColumnBase>();
|
||||
public ObservableCollection<ColumnBase> columns { get; } = new ObservableCollection<ColumnBase>();
|
||||
public SimpleGridSettingsManager<Row> grid_settings_manager { get; }
|
||||
|
||||
public GridSettings get_grid_save_state() {
|
||||
if (_settings_manager.instance_settings == null)
|
||||
return null;
|
||||
else
|
||||
return grid_settings_manager.create();
|
||||
}
|
||||
|
||||
public StartupData create() =>
|
||||
new StartupData(rows_view.get_sorting_criteria(columns), _get_filter_states(), get_grid_save_state());
|
||||
|
||||
|
||||
#region Filters
|
||||
public IDataGridColumnPersistentFilter<Row, TimeFilterTuple> create_time_filter { get; } = new TimeFilterVM<Row>(r => r.create_time, nameof(Row.create_time));
|
||||
public IDataGridColumnPersistentFilter<Row, string> name_filter { get; } = new RegexFilterVM<Row>(r => r.name, nameof(Row.name));
|
||||
public IDataGridColumnPersistentFilter<Row, string> description_filter { get; } = new RegexFilterVM<Row>(r => r.description, nameof(Row.description));
|
||||
public IDataGridColumnPersistentFilter<Row, IntMinMaxState> n_legs_filter { get; } = new IntMinMax<Row>(r => r.n_legs, nameof(Row.n_legs));
|
||||
public IDataGridColumnPersistentFilter<Row, UIntMinMaxState> n_working_orders_filter { get; } = new UIntMinMax<Row>(r => r.n_working_orders, nameof(Row.n_legs));
|
||||
public IDataGridColumnPersistentFilter<Row, string> security_key_filter { get; } = new RegexFilterVM<Row>(r => r.security_key.ToString(), nameof(Row.security_key));
|
||||
public IDataGridColumnPersistentFilter<Row, uint[]> user_filter { get; }
|
||||
|
||||
public GridSettings get_grid_save_state() =>
|
||||
_settings_manager.instance_settings == null ? null : grid_settings_manager.create();
|
||||
|
||||
public StartupData create() =>
|
||||
new StartupData(rows_view.get_sorting_criteria(columns), _get_filter_states(), get_grid_save_state());
|
||||
|
||||
protected override Row row_factory(SyntheticTuple row_model) =>
|
||||
new Row(_bus, row_model, _orders_model);
|
||||
|
||||
protected override void on_row_removed(Row row) =>
|
||||
row.Dispose();
|
||||
|
||||
FilterStates _get_filter_states() =>
|
||||
new FilterStates {
|
||||
@@ -107,19 +109,19 @@ namespace mbts.spark {
|
||||
name = name_filter.get_state(),
|
||||
n_legs = n_legs_filter.get_state(),
|
||||
n_working_orders = n_working_orders_filter.get_state(),
|
||||
security_key = security_key_filter.get_state()
|
||||
security_key = security_key_filter.get_state(),
|
||||
user = user_filter.get_state()
|
||||
};
|
||||
#endregion
|
||||
|
||||
public class Row : SecurityMDRow, IEquatable<Row>, IRowVM, IActionableRowVM {
|
||||
public readonly ExecutionStrategyImmutable? strategy;
|
||||
public class Row : SecurityRow, IEquatable<Row>, IRowVM, IActionableRowVM {
|
||||
public readonly SyntheticTuple synthetic_tuple;
|
||||
|
||||
readonly IBus _bus;
|
||||
readonly Property<uint> _n_working_orders;
|
||||
|
||||
public Row(IBus bus, SecurityMD security_md, ExecutionStrategyImmutable? strategy, OrdersModel orders_model) : base(security_md) {
|
||||
public Row(IBus bus, SyntheticTuple synthetic_tuple, OrdersModel orders_model) : base(synthetic_tuple.security) {
|
||||
_bus = bus;
|
||||
this.strategy = strategy;
|
||||
this.synthetic_tuple = synthetic_tuple;
|
||||
_n_working_orders = backing(nameof(n_working_orders),
|
||||
orders_model.on_security_orders(security_key)
|
||||
.Select(t => (uint)(t.state
|
||||
@@ -133,25 +135,23 @@ namespace mbts.spark {
|
||||
show_order_book = new DelegateCommand(_show_order_book);
|
||||
}
|
||||
|
||||
public event Action invalidated;
|
||||
|
||||
public DateTime create_time => DateTime.MinValue; //TODO
|
||||
public string name { get; }
|
||||
public string user_name => synthetic_tuple.user_name;
|
||||
public UserTuple user_tuple => new UserTuple(synthetic_tuple.security.Synthetic.UserId, user_name);
|
||||
public int n_legs { get; }
|
||||
public string description { get; }
|
||||
public ExecutionStrategyImmutable? strategy => synthetic_tuple.strategy;
|
||||
public bool strategy_present => strategy.HasValue;
|
||||
public uint n_working_orders => _n_working_orders.Value;
|
||||
public ICommand show_ladder { get; }
|
||||
public ICommand show_order_book { get; }
|
||||
public ICommand default_command => show_ladder;
|
||||
|
||||
|
||||
public ObservableCollection<RowAnimation> row_animations => new ObservableCollection<RowAnimation>();
|
||||
|
||||
public IReadOnlyList<IGridCellStore> cell_stores => new IGridCellStore[0];
|
||||
|
||||
|
||||
public event Action invalidated;
|
||||
|
||||
public void raise_invalidated() => invalidated?.Invoke();
|
||||
public void raise_invalidated() =>
|
||||
invalidated?.Invoke();
|
||||
|
||||
public bool Equals(Row other) =>
|
||||
other != null &&
|
||||
@@ -163,10 +163,8 @@ namespace mbts.spark {
|
||||
public override int GetHashCode() =>
|
||||
security_key.GetHashCode();
|
||||
|
||||
|
||||
|
||||
void _show_ladder() =>
|
||||
_bus.post(SparkTags.ShowLadderTag, md);
|
||||
_bus.post(SparkTags.ShowLadderAutoLookupTag, ImmutableHashSet<uint>.Empty.Add(security.Id));
|
||||
|
||||
void _show_order_book() {
|
||||
var ob_settings = bts.shell.orderbook.OrderBookStartupData.Default;
|
||||
@@ -177,4 +175,4 @@ namespace mbts.spark {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -62,7 +62,10 @@ namespace mbts.spark {
|
||||
_vm = new AlgoStudioVM(_model);
|
||||
_vm.load_from(_state);
|
||||
_view = new AlgoStudioView { DataContext = _vm };
|
||||
_resources = new CompositeDisposable();
|
||||
_resources = new CompositeDisposable(
|
||||
_bus.subscribe(SparkTags.SecuritiesTag)
|
||||
.OnDispatcher()
|
||||
.Subscribe(sec_map => _view.Resources[ResourceKeys.Securities] = sec_map));
|
||||
// add definition
|
||||
_commands.Add(new SparkCommandCommand("Add Algo", Icons.AddBoxes, _vm.add_definition_cmd));
|
||||
// clone definition
|
||||
|
||||
@@ -19,6 +19,8 @@ namespace mbts.spark {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public static AlgoData empty => from_custom_def(new CustomOrderDefinitionImmutable(new CustomOrderDefinition()));
|
||||
|
||||
/// <summary>
|
||||
/// This is the only <see cref="AlgoData"/> factory method that allows callers to explicitly specify a name.
|
||||
/// It should only be used within the context of creating, or renaming, studio algos.
|
||||
@@ -65,6 +67,8 @@ namespace mbts.spark {
|
||||
}
|
||||
|
||||
struct AlgoDataVM : IEquatable<AlgoDataVM> {
|
||||
public static readonly Func<AlgoDataVM, AlgoID> id_fn = vm => AlgoID.from_algo_key(vm.data.key);
|
||||
|
||||
public readonly AlgoData data;
|
||||
public readonly AlgoDefinitionMetadata? meta;
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace mbts.spark {
|
||||
_error_reporter = error_reporter;
|
||||
definitions =
|
||||
service.subscribei_algo_definitions()
|
||||
.Filter(r => r.Metadata.IsActive && r.Metadata.CreatorUserId == _admin_model.user.id)
|
||||
.Filter(r => r.Metadata.IsActive && _admin_model.user.can_access_user_data(r.Metadata.CreatorUserId))
|
||||
.SelectKeyValue(_definition_data, d => d.key)
|
||||
.Table()
|
||||
.Cache();
|
||||
|
||||
@@ -13,6 +13,9 @@ namespace mbts.spark {
|
||||
string _template_key;
|
||||
ICommand _set_value_cmd;
|
||||
|
||||
public AlgoParamRowVM(IAlgoVM algo, IAlgoParamVM param, AlgoParamRowVM parent)
|
||||
: this(algo, param, parent, (param as ITemplateSelectorKey)?.key) { }
|
||||
|
||||
public AlgoParamRowVM(IAlgoVM algo, IAlgoParamVM param, AlgoParamRowVM parent, string template_key = null) {
|
||||
this.param = param;
|
||||
this.algo = algo;
|
||||
|
||||
+40
@@ -247,6 +247,31 @@
|
||||
</TextBlock>
|
||||
</DataTemplate>
|
||||
</u:TemplateSelectorKeyValue>
|
||||
<u:TemplateSelectorKeyValue Key="{x:Static u:TemplateKeys.SecurityKey}">
|
||||
<DataTemplate>
|
||||
<Grid>
|
||||
<!--Note: Ideally, this 'securities BindingProxy' would be a static resource, but it only seems to detect the dynamic securities when it is in the visual tree.-->
|
||||
<!--<Grid.Resources>
|
||||
<u:BindingProxy x:Key="SecuritiesBindingProxy" x:Shared="False" Value="{DynamicResource {x:Static u:ResourceKeys.Securities}}"/>
|
||||
</Grid.Resources>-->
|
||||
<u:BindingProxy x:Name="SecuritiesBindingProxy" Value="{DynamicResource {x:Static u:ResourceKeys.Securities}}"/>
|
||||
<TextBlock>
|
||||
<TextBlock.Text>
|
||||
<MultiBinding>
|
||||
<MultiBinding.Converter>
|
||||
<cv:MultiValueConverterPipe>
|
||||
<cv:DictionaryLookupConverter/>
|
||||
<x:Static MemberType="cv:ValueConverters" Member="SecuritySelectorText"/>
|
||||
</cv:MultiValueConverterPipe>
|
||||
</MultiBinding.Converter>
|
||||
<Binding Path="Value" ElementName="SecuritiesBindingProxy"/>
|
||||
<Binding Path="param.value"/>
|
||||
</MultiBinding>
|
||||
</TextBlock.Text>
|
||||
</TextBlock>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</u:TemplateSelectorKeyValue>
|
||||
</usp:AlgoParamTemplateSelector.KeyedTemplates>
|
||||
<!--Bool-->
|
||||
<usp:AlgoParamTemplateSelector.BoolTemplate>
|
||||
@@ -320,6 +345,21 @@
|
||||
</usp:PriceEntryControl>
|
||||
</DataTemplate>
|
||||
</u:TemplateSelectorKeyValue>
|
||||
<u:TemplateSelectorKeyValue Key="{x:Static u:TemplateKeys.SecurityKey}">
|
||||
<DataTemplate>
|
||||
<c:ContractPickerPopup
|
||||
CloseOnCancel="True"
|
||||
CloseOnOK="True"
|
||||
Header="{Binding SelectedSecurity, RelativeSource={RelativeSource Self}, Converter={x:Static cv:ValueConverters.SecuritySelectorText}}"
|
||||
IsEditMode="False"
|
||||
IsLazy="True"
|
||||
SecurityMap="{DynamicResource {x:Static u:ResourceKeys.Securities}}"
|
||||
SelectedSecurityKey="{Binding param.value}"
|
||||
ShowDialogSkirt="True"
|
||||
OKClick="{x:Static c:ContractPickerPopup.FlushSelectedSecurityKeyHandler}"
|
||||
/>
|
||||
</DataTemplate>
|
||||
</u:TemplateSelectorKeyValue>
|
||||
</usp:AlgoParamTemplateSelector.KeyedTemplates>
|
||||
<!--Bool-->
|
||||
<usp:AlgoParamTemplateSelector.BoolTemplate>
|
||||
|
||||
+2
-2
@@ -10,7 +10,7 @@ using System.Reactive.Disposables;
|
||||
namespace mbts.spark {
|
||||
static class AlgoParamRowsHelper {
|
||||
public static IDisposable connect(AlgoDefinitionVM algo, ObservableAggregateCollection<AlgoParamRowVM> rows, bool include_algo_type_rows) =>
|
||||
algo == null ? null : new CompositeDisposable(algo.observe_algo_root().SubscribeEach(a => {
|
||||
algo == null ? null : new CompositeDisposable(algo.observe_algo_root().OnDispatcher().SubscribeEach(a => {
|
||||
rows.clear_collections();
|
||||
if (a == null)
|
||||
return Disposable.empty;
|
||||
@@ -77,7 +77,7 @@ namespace mbts.spark {
|
||||
include_algo_type_rows ?
|
||||
(ObservableCollection<AlgoParamRowVM>)new ObservableAppendCollection<AlgoParamRowVM>(child_rows, selector_wrapper) :
|
||||
child_rows,
|
||||
s.subscribe_selected_algo().SubscribeEach(a => {
|
||||
s.subscribe_selected_algo().OnDispatcher().SubscribeEach(a => {
|
||||
s.value = a;
|
||||
child_rows.clear_collections();
|
||||
return _wrap_rows(a, selector_wrapper, child_rows, include_algo_type_rows);
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ namespace mbts.ui.spark {
|
||||
class AlgoParamTemplateSelector : DataTemplateSelector {
|
||||
public static readonly Type generic_algo_param_itype = typeof(IAlgoParamVM<>);
|
||||
|
||||
KeyedCollection<TemplateSelectorKeyValue, string> _keyed_templates = new KeyedCollection<TemplateSelectorKeyValue, string>(tsk => tsk.Key);
|
||||
KeyedCollection<TemplateSelectorKeyValue, string> _keyed_templates = new KeyedCollection<TemplateSelectorKeyValue, string>(tsk => tsk.Key.ToString());
|
||||
|
||||
public DataTemplate BoolTemplate { get; set; }
|
||||
public DataTemplate NullableBoolTemplate { get; set; }
|
||||
|
||||
@@ -68,25 +68,64 @@ namespace mbts.spark {
|
||||
nameof(OrderBookRowVM.symbol)),
|
||||
DataGridFilterKnownTemplates.DiscreteValues,
|
||||
DefaultColumnWidths.Symbol);
|
||||
// algo items view (common resources)
|
||||
var algo_items_comp = AlgoCollectionHelper.algo_data_vm_comparer.to_non_generic();
|
||||
var algo_items_group_desc = new PropertyGroupDescription(nameof(AlgoDataVM.group));
|
||||
// order type
|
||||
var order_type_filter = dv_filter(OrderDataHelper.all_order_types, r => r.order?.order_type() ?? OrderType.None);
|
||||
var order_type_filter = DiscreteValuesFilterVM.CreateTableUpdate<FillTuple, AlgoDataVM, AlgoID, OrderType[]>(
|
||||
ft => new AlgoDataVM(ft.algo ?? AlgoData.empty),
|
||||
AlgoDataVM.id_fn,
|
||||
ots => Array.ConvertAll(ots ?? Array.Empty<OrderType>(), ot => AlgoID.from_algo_key(AlgoKey.from_known_type(ot))),
|
||||
ids => ids.empty_if_null().Select(AlgoID.to_algo_key).Where(k => k.mode == AlgoKey.Mode.Factory).Select(k => k.factory).ToArray(),
|
||||
out var order_type_observer,
|
||||
out var order_type_items_view);
|
||||
|
||||
order_type_items_view.CustomSort = algo_items_comp;
|
||||
order_type_items_view.GroupDescriptions.Add(algo_items_group_desc);
|
||||
order_type_observer.OnNext(TableUpdate<AlgoDataVM, AlgoID>.mk_empty(AlgoDataVM.id_fn)
|
||||
.with_added(OrderDataHelper.all_order_types
|
||||
.Select(OrderDataHelper.Defaults.CustomOrderDefinitionImmutable)
|
||||
.Select(AlgoData.from_custom_def)
|
||||
.Select(d => new AlgoDataVM(d))));
|
||||
|
||||
add_col_expl(Columns.OrderType,
|
||||
new OrderTypeColumn<Columns>(Columns.OrderType, new Binding(nameof(Row.badge_fill)), new Binding(nameof(Row.display_name)), order_type_filter) {
|
||||
id = col_id(Columns.OrderType),
|
||||
sort_member_path = nameof(Row.order_type)
|
||||
}, order_type_filter);
|
||||
// root algo type
|
||||
var root_algo_type_filter = DiscreteValuesFilterVM.CreateTableUpdate<FillTuple, AlgoDataVM, AlgoID>(
|
||||
ft => new AlgoDataVM(ft.root_algo ?? AlgoData.empty),
|
||||
AlgoDataVM.id_fn,
|
||||
out var root_algo_type_observer,
|
||||
out var root_algo_type_items_view);
|
||||
|
||||
root_algo_type_items_view.CustomSort = algo_items_comp;
|
||||
root_algo_type_items_view.GroupDescriptions.Add(algo_items_group_desc);
|
||||
|
||||
add_col_expl(Columns.RootAlgoType,
|
||||
new OrderTypeColumn<Columns>(
|
||||
Columns.RootAlgoType,
|
||||
new Binding(nameof(Row.root_algo_badge_color)) { Converter = new ui.converters.ColorToBrushConverter() },
|
||||
new Binding(nameof(Row.root_algo_display_name)),
|
||||
root_algo_type_filter,
|
||||
DefaultColumnHeaders.RootAlgoType) {
|
||||
id = col_id(Columns.RootAlgoType),
|
||||
sort_member_path = nameof(Row.root_algo_order_type)
|
||||
}, root_algo_type_filter);
|
||||
// side
|
||||
var side_filter = dv_filter(new[] { Side.Buy, Side.Sell }, r => r.fill.Side);
|
||||
add_col_expl(Columns.Side, new SideColumn<Row, Columns>(Columns.Side, r => r.side, side_filter) { id = col_id(Columns.Side) }, side_filter);
|
||||
// all others (easily identified by the enum 'Columns.Foo')
|
||||
add_col(Columns.FillTime, DefaultColumnHeaders.FillTime, r => r.fill_time.ToString("M/d h:mm:ss tt"), new TimeFilterVM<FillTuple>(r => r.fill.Timestamp.ToDateTimeOffset().LocalDateTime), DataGridFilterKnownTemplates.TimeFilter, DefaultColumnWidths.Time);
|
||||
add_col(Columns.User, DefaultColumnHeaders.User, r => r.user, dv_filter_rx(_model.factory.subscribe_users().Select(d => d.Values), r => r.order?.user() ?? string.Empty), DataGridFilterKnownTemplates.DiscreteValues, DefaultColumnWidths.User);
|
||||
add_col(Columns.Account, DefaultColumnHeaders.Account, r => r.account, dv_filter_rx(_model.factory.subscribe_accounts().Select(d => d.Values), r => r.account), DataGridFilterKnownTemplates.DiscreteValues, DefaultColumnWidths.Account);
|
||||
add_col(Columns.User, DefaultColumnHeaders.User, r => r.user, dv_filter_rx(_model.factory.subscribe_users().Select(d => d.Values.Ordered()), r => r.order?.user() ?? string.Empty), DataGridFilterKnownTemplates.DiscreteValues, DefaultColumnWidths.User);
|
||||
add_col(Columns.Account, DefaultColumnHeaders.Account, r => r.account, dv_filter_rx(_model.factory.subscribe_accounts().Select(d => d.Values.Ordered()), r => r.account), DataGridFilterKnownTemplates.DiscreteValues, DefaultColumnWidths.Account);
|
||||
add_col(Columns.Exchange, DefaultColumnHeaders.Exchange, r => r.exchange.ToString(), dv_filter(EnumHelper.get_values<Venue>().ToArray(), r => r.security.exchange_or_default()), DataGridFilterKnownTemplates.DiscreteValues, DefaultColumnWidths.Exchange);
|
||||
add_col(Columns.TimeInForce, DefaultColumnHeaders.TimeInForce, r => r.time_in_force.ToString(), dv_filter(EnumHelper.get_values<TimeInForce>().ToArray(), r => r.order?.time_in_force() ?? TimeInForce.Undefined), DataGridFilterKnownTemplates.DiscreteValues, DefaultColumnWidths.TimeInForce);
|
||||
add_col(Columns.Size, DefaultColumnHeaders.Size, r => r.size.ToString(), new DoubleMinMax<FillTuple>(r => r.fill.LastShares), DataGridFilterKnownTemplates.UIntMinMax, DefaultColumnWidths.Size);
|
||||
add_col(Columns.Price, DefaultColumnHeaders.Price, r => r.format_price(r.price), new DoubleMinMax<FillTuple>(r => r.fill.LastPrice), DataGridFilterKnownTemplates.DoubleMinMax, DefaultColumnWidths.Price);
|
||||
add_col(Columns.FillKind, DefaultColumnHeaders.FillKind, r => r.fill_kind.ToString(), dv_filter(EnumHelper.get_values<FillKind>().ToArray(), r => r.fill.FillKind), DataGridFilterKnownTemplates.DiscreteValues, DefaultColumnWidths.FillKind);
|
||||
add_col(Columns.FillStatus, DefaultColumnHeaders.FillStatus, r => r.fill_status.ToString(), dv_filter(EnumHelper.get_values<FillStatus>().ToArray(), r => r.fill.FillStatus), DataGridFilterKnownTemplates.DiscreteValues, DefaultColumnWidths.FillKind);
|
||||
add_col(Columns.FillKey, DefaultColumnHeaders.FillKey, r => r.fill_key.ToString(), new RegexFilterVM<FillTuple>(r => r.fill.FillKey), DataGridFilterKnownTemplates.Regex, DefaultColumnWidths.FillKey);
|
||||
add_col(Columns.OrderKey, DefaultColumnHeaders.OrderKey, r => r.order_key.ToString(), new RegexFilterVM<FillTuple>(r => r.fill.OrderKey.ToString()), DataGridFilterKnownTemplates.Regex, DefaultColumnWidths.OrderKey);
|
||||
add_col(Columns.SecurityKey, DefaultColumnHeaders.SecurityKey, r => r.security_key.ToString(), new RegexFilterVM<FillTuple>(r => r.fill.SecurityKey.ToString()), DataGridFilterKnownTemplates.Regex, DefaultColumnWidths.SecurityKey);
|
||||
@@ -108,6 +147,7 @@ namespace mbts.spark {
|
||||
});
|
||||
_dispose = new CompositeDisposable(
|
||||
ObservableAutoWrapper.connect(col_tups, columns, ct => ct.col),
|
||||
ObservableAutoWrapper.connect_item_hooks(col_tups, ct => ct.filter as IDisposable),
|
||||
RXCollection.connect(rows, fills_buffer.Filter(filter_src, FillTuple.key_fn), comp_src, ft => new Row(ft, model), r => r.fill_tuple),
|
||||
fills_source.OnDispatcher().Subscribe(t => {
|
||||
last_unfiltered_fills = t;
|
||||
@@ -128,6 +168,7 @@ namespace mbts.spark {
|
||||
};
|
||||
_rows_manager.on_settings(fs, s.sorting_criterion);
|
||||
}),
|
||||
model.subscribe_all_algos().SelectKeyValue(AlgoDataVM.from_data, d => AlgoID.from_algo_key(d.data.key)).OnDispatcher().Subscribe(root_algo_type_observer),
|
||||
settings_manager == null ? Disposable.empty : settings_manager.subscribe_current().OnDispatcher().Subscribe(grid_settings_manager)
|
||||
);
|
||||
// local methods
|
||||
@@ -175,8 +216,8 @@ namespace mbts.spark {
|
||||
static IObservable<TableUpdate<FillTuple, string>> _get_observable(IBus bus, OrdersModel model, FillsSettings state) {
|
||||
if (!state.orders.is_null_or_empty()) {
|
||||
var orders_hash = new HashSet<uint>(state.orders);
|
||||
return model.on_fill_tuples.Filter(f => orders_hash.Contains(f.fill.OrderKey));
|
||||
} else return model.on_fill_tuples;
|
||||
return model.on_fill_tuples_with_root.Filter(f => orders_hash.Contains(f.fill.OrderKey));
|
||||
} else return model.on_fill_tuples_with_root;
|
||||
}
|
||||
|
||||
static IObservable<TableUpdate<FillTuple, string>> _get_observable(IBus bus, OrdersModel model, IObservable<FillsSettings> state) =>
|
||||
@@ -188,9 +229,11 @@ namespace mbts.spark {
|
||||
case Columns.Exchange: return wrap_default(ft => ft.security.exchange_or_default());
|
||||
case Columns.FillKey: return wrap(ft => ft.fill.FillKey);
|
||||
case Columns.FillKind: return wrap_default(ft => ft.fill.FillKind);
|
||||
case Columns.FillStatus: return wrap_default(ft => ft.fill.FillStatus);
|
||||
case Columns.FillTime: return wrap(ft => ft.fill.Timestamp.to_local_time());
|
||||
case Columns.OrderKey: return wrap(ft => ft.fill.OrderKey);
|
||||
case Columns.OrderType: return wrap_default(ft => ft.order?.order_type() ?? OrderType.None);
|
||||
case Columns.RootAlgoType: return wrap_default(ft => ft.root_algo.HasValue ? ft.root_algo.Value.value.CustomCase : OrderType.None);
|
||||
case Columns.Price: return wrap(ft => ft.fill.LastPrice);
|
||||
case Columns.Security: return wrap(ft => ft.security ?? SecurityDataHelper.Defaults.SecurityImmutable);
|
||||
case Columns.SecurityKey: return wrap(ft => ft.fill.SecurityKey);
|
||||
@@ -224,7 +267,10 @@ namespace mbts.spark {
|
||||
readonly OrdersModel _model;
|
||||
readonly FillImmutable _fill;
|
||||
readonly OrderRecordImmutable _order;
|
||||
AlgoData? _root_algo => fill_tuple.root_algo;
|
||||
AlgoDefinitionMetadata? _root_algo_meta => fill_tuple.root_algo_meta;
|
||||
Brush _badge_fill;
|
||||
Color? _root_algo_badge_color;
|
||||
OrderMetadata _order_metadata;
|
||||
|
||||
public Row(FillTuple fill_tuple, OrdersModel model) :
|
||||
@@ -249,9 +295,16 @@ namespace mbts.spark {
|
||||
public double price => _fill.LastPrice;
|
||||
public double size => _fill.LastShares;
|
||||
public FillKind fill_kind => _fill.FillKind;
|
||||
public FillStatus fill_status => _fill.FillStatus;
|
||||
public string fill_key => _fill.FillKey;
|
||||
public string order_key => _order.Key.ToString();
|
||||
|
||||
// Root Algo
|
||||
public OrderType root_algo_order_type => _root_algo.HasValue ? _root_algo.Value.value.CustomCase : OrderType.None;
|
||||
public OrderMetadata root_algo_order_metadata => _model.factory.get_metadata(root_algo_order_type);
|
||||
public Color root_algo_badge_color => _root_algo_badge_color ?? (_root_algo_badge_color = OrderUtils.badge_color(_root_algo_meta, root_algo_order_metadata)).Value;
|
||||
public string root_algo_display_name => fill_tuple.root_order_security?.display_name() ?? OrderType.None.display_name();
|
||||
|
||||
public bool Equals(Row other) => other != null && other._fill.Equals(_fill) && other._order.Equals(_order);
|
||||
public override bool Equals(object obj) => Equals(obj as Row);
|
||||
public override int GetHashCode() => _fill.FillKey.GetHashCode() ^ _order.Key.GetHashCode();
|
||||
|
||||
@@ -16,10 +16,12 @@ namespace mbts.ui.spark {
|
||||
Symbol,
|
||||
TimeInForce,
|
||||
OrderType,
|
||||
RootAlgoType,
|
||||
Side,
|
||||
Price,
|
||||
Size,
|
||||
FillKind,
|
||||
FillStatus,
|
||||
FillKey,
|
||||
OrderKey,
|
||||
SecurityKey
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
using bts.api;
|
||||
using bts.api.orderman;
|
||||
using bts.settings;
|
||||
using bts.shell.fills;
|
||||
using mbts.persist;
|
||||
using mbts.spark;
|
||||
using mbts.spark.filters;
|
||||
using mbts.ui;
|
||||
using mbts.ui.controls;
|
||||
using mbts.ui.settings;
|
||||
using ProtoBuf;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Reactive.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using static mbts.ui.controls.DIYGrid;
|
||||
using static mbts.ui.spark.FillsView;
|
||||
|
||||
namespace bts.shell {
|
||||
@@ -34,13 +30,15 @@ namespace bts.shell {
|
||||
{ nameof(FillsVM.Row.fill_time), Columns.FillTime },
|
||||
{ nameof(FillsVM.Row.order_key), Columns.OrderKey },
|
||||
{ nameof(FillsVM.Row.order_type), Columns.OrderType },
|
||||
{ nameof(FillsVM.Row.root_algo_order_type), Columns.RootAlgoType },
|
||||
{ nameof(FillsVM.Row.price), Columns.Price },
|
||||
{ nameof(FillsVM.Row.security), Columns.Security },
|
||||
{ nameof(FillsVM.Row.security_key), Columns.SecurityKey },
|
||||
{ nameof(FillsVM.Row.side), Columns.Side },
|
||||
{ nameof(FillsVM.Row.size), Columns.Size },
|
||||
{ nameof(FillsVM.Row.time_in_force), Columns.TimeInForce },
|
||||
{ nameof(FillsVM.Row.user), Columns.User }
|
||||
{ nameof(FillsVM.Row.user), Columns.User },
|
||||
{ nameof(FillsVM.Row.fill_status ), Columns.FillStatus },
|
||||
};
|
||||
|
||||
public FillsWindowFactory(TradingShellModule module, IBus bus, UserSettingsHub settings_hub, OrdersModel orders_model)
|
||||
@@ -67,5 +65,12 @@ namespace bts.shell {
|
||||
set: (us, gs) => us.with(provided_fills_gridsettings: gs));
|
||||
return new FillsWindow(this, _bus, _orders_model, state, settings_manager);
|
||||
}
|
||||
|
||||
// migration rules
|
||||
[Export(typeof(IFillsGridSettingsMigrationRule))]
|
||||
class AddMissingColumnsMigrationRule : IFillsGridSettingsMigrationRule {
|
||||
public bool apply(GridSettings settings, out GridSettings new_settings) =>
|
||||
settings.add_missing_columns(FillsSettings.DefaultGridSettings.columns, out new_settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,10 @@ namespace bts.shell.fills {
|
||||
[DIYGridColumnID(nameof(Columns.OrderType))]
|
||||
public CustomOrderDefinition.CustomOneofCase[] order_type { get; set; }
|
||||
|
||||
[ProtoMember(16)]
|
||||
[DIYGridColumnID(nameof(Columns.RootAlgoType))]
|
||||
public AlgoID[] root_algo_type { get; set; }
|
||||
|
||||
[ProtoMember(4)]
|
||||
[DIYGridColumnID(nameof(Columns.Account))]
|
||||
public string[] account { get; set; }
|
||||
@@ -70,6 +74,10 @@ namespace bts.shell.fills {
|
||||
[ProtoMember(15)]
|
||||
[DIYGridColumnID(nameof(Columns.Symbol))]
|
||||
public string[] symbol { get; set; }
|
||||
|
||||
[ProtoMember(17)]
|
||||
[DIYGridColumnID(nameof(Columns.FillStatus))]
|
||||
public Fill.Types.FillStatus[] fill_status { get; set; }
|
||||
}
|
||||
|
||||
static class FillsFilterStatesExtensions {
|
||||
@@ -88,9 +96,11 @@ namespace bts.shell.fills {
|
||||
pb.add_discrete_values(fs.exchange, ft => ft.exchange());
|
||||
pb.add_discrete_values(fs.time_in_force, ft => ft.time_in_force());
|
||||
pb.add_discrete_values(fs.order_type, ft => ft.order_type());
|
||||
pb.add_discrete_values(fs.root_algo_type, ft => AlgoID.from_algo_key((ft.root_algo ?? AlgoData.empty).key));
|
||||
pb.add_discrete_values(fs.side, ft => ft.fill.Side);
|
||||
pb.add_discrete_values(fs.fill_kind, ft => ft.fill.FillKind);
|
||||
pb.add_discrete_values(fs.symbol, ft => ft.security?.Symbol ?? string.Empty);
|
||||
pb.add_discrete_values(fs.fill_status, ft => ft.fill.FillStatus);
|
||||
// numeric
|
||||
pb.add_numeric(fs.size, ft => ft.fill.LastShares);
|
||||
pb.add_numeric(fs.price, ft => ft.fill.LastPrice);
|
||||
|
||||
@@ -47,6 +47,7 @@ namespace bts.shell.fills {
|
||||
public static GridColumnSettings exchange => new GridColumnSettings(col_id(Columns.Exchange), DefaultColumnHeaders.Exchange, width: DefaultColumnWidths.Exchange);
|
||||
public static GridColumnSettings time_in_force => new GridColumnSettings(col_id(Columns.TimeInForce), DefaultColumnHeaders.TimeInForce, width: DefaultColumnWidths.TimeInForce);
|
||||
public static GridColumnSettings order_type => new GridColumnSettings(col_id(Columns.OrderType), DefaultColumnHeaders.OrderType, width: DefaultColumnWidths.OrderType);
|
||||
public static GridColumnSettings root_algo_type => new GridColumnSettings(col_id(Columns.RootAlgoType), DefaultColumnHeaders.RootAlgoType, width: DefaultColumnWidths.OrderType);
|
||||
public static GridColumnSettings side => new GridColumnSettings(col_id(Columns.Side), DefaultColumnHeaders.Side, width: DefaultColumnWidths.Side);
|
||||
public static GridColumnSettings quantity => new GridColumnSettings(col_id(Columns.Size), DefaultColumnHeaders.Size, width: DefaultColumnWidths.Size, horizontal_alignment: System.Windows.HorizontalAlignment.Right);
|
||||
public static GridColumnSettings price => new GridColumnSettings(col_id(Columns.Price), DefaultColumnHeaders.Price, width: DefaultColumnWidths.Price, horizontal_alignment: System.Windows.HorizontalAlignment.Right);
|
||||
@@ -70,6 +71,7 @@ namespace bts.shell.fills {
|
||||
yield return exchange;
|
||||
yield return time_in_force;
|
||||
yield return order_type;
|
||||
yield return root_algo_type;
|
||||
yield return side;
|
||||
yield return quantity;
|
||||
yield return price;
|
||||
|
||||
@@ -23,6 +23,10 @@ namespace mbts.spark {
|
||||
// TODO: somehow allow windows that are using the default settings to still have individual column widths.
|
||||
[ProtoContract]
|
||||
class LadderColumnSettings : IEquatable<LadderColumnSettings> {
|
||||
// this class is 100% mutable (there are literally 0 readonly members),
|
||||
// so GetHashCode must return the same hash for every instance.
|
||||
static readonly int _type_hash = typeof(LadderColumnSettings).GetHashCode();
|
||||
|
||||
public static LadderColumnSettings Default => new LadderColumnSettings {
|
||||
show = true,
|
||||
width = 50,
|
||||
@@ -74,14 +78,7 @@ namespace mbts.spark {
|
||||
other.show == show;
|
||||
|
||||
public override bool Equals(object obj) => Equals(obj as LadderColumnSettings);
|
||||
|
||||
public override int GetHashCode() =>
|
||||
width.GetHashCode() +
|
||||
background.GetHashCode() +
|
||||
foreground.GetHashCode() +
|
||||
font_family.GetHashCode() +
|
||||
font_size.GetHashCode() +
|
||||
font_weight.GetHashCode();
|
||||
public override int GetHashCode() => _type_hash;
|
||||
|
||||
public static bool operator ==(LadderColumnSettings x, LadderColumnSettings y) => x.safe_equals(y);
|
||||
public static bool operator !=(LadderColumnSettings x, LadderColumnSettings y) => !(x == y);
|
||||
@@ -89,6 +86,9 @@ namespace mbts.spark {
|
||||
|
||||
[ProtoContract]
|
||||
class HistogramBarAnimation : IEquatable<HistogramBarAnimation> {
|
||||
// this class is 100% mutable (there are literally 0 readonly members),
|
||||
// so GetHashCode must return the same hash for every instance.
|
||||
static readonly int _type_hash = typeof(HistogramBarAnimation).GetHashCode();
|
||||
[ProtoMember(1)]
|
||||
public ColorShowProto bars { get; set; }
|
||||
[ProtoMember(2)]
|
||||
@@ -102,14 +102,14 @@ namespace mbts.spark {
|
||||
show_numbers == other.show_numbers;
|
||||
|
||||
public override bool Equals(object obj) => Equals(obj as HistogramBarAnimation);
|
||||
public override int GetHashCode() =>
|
||||
EqualityComparer.aggregate_hash(
|
||||
bars.GetHashCode(),
|
||||
show_numbers.GetHashCode());
|
||||
public override int GetHashCode() => _type_hash;
|
||||
}
|
||||
|
||||
[ProtoContract]
|
||||
class VolumeColumnSettings : IEquatable<VolumeColumnSettings> {
|
||||
// this class is 100% mutable (there are literally 0 readonly members),
|
||||
// so GetHashCode must return the same hash for every instance.
|
||||
static readonly int _type_hash = typeof(VolumeColumnSettings).GetHashCode();
|
||||
public static VolumeColumnSettings Default {
|
||||
get {
|
||||
var gen = LadderColumnSettings.Default;
|
||||
@@ -149,19 +149,14 @@ namespace mbts.spark {
|
||||
show_ltq.Equals(other.show_ltq);
|
||||
|
||||
public override bool Equals(object obj) => Equals(obj as VolumeColumnSettings);
|
||||
|
||||
public override int GetHashCode() =>
|
||||
EqualityComparer.aggregate_hash(
|
||||
general.GetHashCode(),
|
||||
buy.GetHashCode(),
|
||||
sell.GetHashCode(),
|
||||
passive.GetHashCode(),
|
||||
total.GetHashCode(),
|
||||
show_ltq.GetHashCode());
|
||||
public override int GetHashCode() => _type_hash;
|
||||
}
|
||||
|
||||
[ProtoContract]
|
||||
class LadderMarketBreakLine : IEquatable<LadderMarketBreakLine> {
|
||||
// this class is 100% mutable (there are literally 0 readonly members),
|
||||
// so GetHashCode must return the same hash for every instance.
|
||||
static readonly int _type_hash = typeof(LadderMarketBreakLine).GetHashCode();
|
||||
[ProtoMember(1)]
|
||||
public bool show { get; set; }
|
||||
[ProtoMember(2)]
|
||||
@@ -184,8 +179,7 @@ namespace mbts.spark {
|
||||
Equals(obj as LadderMarketBreakLine);
|
||||
|
||||
public override int GetHashCode() =>
|
||||
show.GetHashCode() +
|
||||
(int)color;
|
||||
_type_hash;
|
||||
}
|
||||
|
||||
[ProtoContract]
|
||||
@@ -194,20 +188,27 @@ namespace mbts.spark {
|
||||
readonly bts.persist.algo.AlgoPersistedKey[] _favorite_algos;
|
||||
[ProtoMember(2)]
|
||||
public readonly int column_count;
|
||||
[ProtoMember(3)]
|
||||
readonly bts.persist.algo.AlgoPersistedKey[] _stickied_algos;
|
||||
|
||||
public LadderFavoriteAlgosSettings(AlgoKey[] favorite_algos, int column_count)
|
||||
: this(ArrayHelper.safe_convert(favorite_algos, k => new bts.persist.algo.AlgoPersistedKey(k.persisted)), column_count) { }
|
||||
public LadderFavoriteAlgosSettings(AlgoKey[] favorite_algos, int column_count, AlgoKey[] stickied_algos)
|
||||
: this(ArrayHelper.safe_convert(favorite_algos, k => new bts.persist.algo.AlgoPersistedKey(k.persisted)),
|
||||
column_count,
|
||||
ArrayHelper.safe_convert(stickied_algos, k => new bts.persist.algo.AlgoPersistedKey(k.persisted))) { }
|
||||
|
||||
LadderFavoriteAlgosSettings(bts.persist.algo.AlgoPersistedKey[] favorite_algos, int column_count) {
|
||||
LadderFavoriteAlgosSettings(bts.persist.algo.AlgoPersistedKey[] favorite_algos, int column_count, bts.persist.algo.AlgoPersistedKey[] stickied_algos) {
|
||||
_favorite_algos = favorite_algos;
|
||||
this.column_count = column_count;
|
||||
_stickied_algos = stickied_algos;
|
||||
}
|
||||
|
||||
public IReadOnlyList<AlgoKey> favorite_algos => ArrayHelper.safe_convert(_favorite_algos, k => k.to_algo_key());
|
||||
public IReadOnlyList<AlgoKey> stickied_algos => ArrayHelper.safe_convert(_stickied_algos, k => k.to_algo_key());
|
||||
|
||||
public bool Equals(LadderFavoriteAlgosSettings other) =>
|
||||
column_count == other.column_count &&
|
||||
favorite_algos.SequenceEqual(other.favorite_algos);
|
||||
favorite_algos.SequenceEqual(other.favorite_algos) &&
|
||||
stickied_algos.SequenceEqual(other.stickied_algos);
|
||||
|
||||
public override bool Equals(object obj) =>
|
||||
EqualityComparer.equals_obj(this, obj);
|
||||
@@ -215,7 +216,8 @@ namespace mbts.spark {
|
||||
public override int GetHashCode() =>
|
||||
EqualityComparer.aggregate_hash(
|
||||
column_count,
|
||||
EqualityComparer.aggregate_hash_limited(favorite_algos));
|
||||
EqualityComparer.aggregate_hash_limited(favorite_algos),
|
||||
EqualityComparer.aggregate_hash_limited(stickied_algos));
|
||||
|
||||
public static bool operator ==(LadderFavoriteAlgosSettings a, LadderFavoriteAlgosSettings b) => a.Equals(b);
|
||||
public static bool operator !=(LadderFavoriteAlgosSettings a, LadderFavoriteAlgosSettings b) => !a.Equals(b);
|
||||
@@ -247,6 +249,11 @@ namespace mbts.spark {
|
||||
const double _default_order_entry_panel_width = 110.0;
|
||||
const double _default_zoom_factor = 1.0;
|
||||
const bool _default_show_warn_on_cross = true;
|
||||
public static readonly IEqualityComparer<LadderSettings> profile_equality_comparer =
|
||||
EqualityComparer.Create<LadderSettings>(profile_equals);
|
||||
// this class is 100% mutable (there are literally 0 readonly members),
|
||||
// so GetHashCode must return the same hash for every instance.
|
||||
static readonly int _type_hash = typeof(LadderSettings).GetHashCode();
|
||||
|
||||
// Default proto constructor
|
||||
// Added this so that when clients upgrade to a version with new settings,
|
||||
@@ -273,7 +280,7 @@ namespace mbts.spark {
|
||||
order_entry_panel_initial_width = _default_order_entry_panel_width;
|
||||
zoom_factor = _default_zoom_factor;
|
||||
use_defaults = true;
|
||||
favorite_algos = new LadderFavoriteAlgosSettings(null, 2);
|
||||
favorite_algos = new LadderFavoriteAlgosSettings(null, 2, null);
|
||||
show_warn_on_cross = _default_show_warn_on_cross;
|
||||
}
|
||||
|
||||
@@ -442,6 +449,8 @@ namespace mbts.spark {
|
||||
public bool account_position_visible { get; set; }
|
||||
[ProtoMember(50), DefaultValue(true)]
|
||||
public bool day_position_visible { get; set; }
|
||||
[ProtoMember(56)]
|
||||
public bool raw_day_position_visible { get; set; }
|
||||
[ProtoMember(37), DefaultValue(true)]
|
||||
public bool size_presets_visible { get; set; }
|
||||
[ProtoMember(38), DefaultValue(true)]
|
||||
@@ -487,6 +496,9 @@ namespace mbts.spark {
|
||||
[ProtoMember(55)]
|
||||
public LadderMiniOrderBookSettings mini_ob { get; set; }
|
||||
|
||||
[ProtoMember(57)]
|
||||
public double left_panel_scroll_position { get; set; }
|
||||
|
||||
public void sanitize() =>
|
||||
sanitize(this);
|
||||
|
||||
@@ -523,111 +535,81 @@ namespace mbts.spark {
|
||||
return s;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether or not the specified LadderSettings are 'profile equivalent.'
|
||||
/// This means that 2 ladders, each with a different one of the specified settings, could share the same profile.
|
||||
/// </summary>
|
||||
///
|
||||
/// Note: the impetus for this version of equality is to avoid disconnecting a ladder from its profile due to 'trivial' settings changes.
|
||||
/// Consider the '<see cref="default_algo"/>' property:
|
||||
/// If a ladder is using a settings profile with Limit as the default algo, and the user decides to send a 'Market' order,
|
||||
/// the ladder would suddenly be disconnected from the profile, because it's settings state would no longer be equal to the profile's settings,
|
||||
/// since they changed the selected algo type to 'Market.'
|
||||
/// To avoid such travesties, a separate equals logic is needed: this is called 'profile-equivalent' and is implemented in <see cref="profile_equals)"/>.
|
||||
/// Devs: be sure to account for properties that are excluded in the 'profile-equals' logic in the [regular]'equals' logic.
|
||||
public static bool profile_equals(LadderSettings a, LadderSettings b) =>
|
||||
a == null ? b == null :
|
||||
b != null &&
|
||||
a.row_height == b.row_height &&
|
||||
a.grid_line_color == b.grid_line_color &&
|
||||
a.orders_column.safe_equals(b.orders_column) &&
|
||||
a.bid_column.safe_equals(b.bid_column) &&
|
||||
a.ask_column.safe_equals(b.ask_column) &&
|
||||
a.price_column.safe_equals(b.price_column) &&
|
||||
a.last_column.safe_equals(b.last_column) &&
|
||||
a.piq_column.safe_equals(b.piq_column) &&
|
||||
a.calculator_buttons.safe_equals(b.calculator_buttons, Enumerable.SequenceEqual) &&
|
||||
a.scroll_bar_visible == b.scroll_bar_visible &&
|
||||
a.default_account == b.default_account &&
|
||||
a.default_time_in_force == b.default_time_in_force &&
|
||||
a.size == b.size &&
|
||||
a.animate_recenter == b.animate_recenter &&
|
||||
a.badge_style == b.badge_style &&
|
||||
a.auto_clear == b.auto_clear &&
|
||||
a.bid_break_line.safe_equals(b.bid_break_line) &&
|
||||
a.ask_break_line.safe_equals(b.ask_break_line) &&
|
||||
a.mid_break_line.safe_equals(b.mid_break_line) &&
|
||||
a.alternate_order_size == b.alternate_order_size &&
|
||||
a.session_low_line.safe_equals(b.session_low_line) &&
|
||||
a.session_high_line.safe_equals(b.session_high_line) &&
|
||||
a.session_range_fill.safe_equals(b.session_range_fill) &&
|
||||
a.volume_column.safe_equals(b.volume_column) &&
|
||||
a.size_display.safe_equals(b.size_display) &&
|
||||
a.day_visible == b.day_visible &&
|
||||
a.high_visible == b.high_visible &&
|
||||
a.low_visible == b.low_visible &&
|
||||
a.open_visible == b.open_visible &&
|
||||
a.settle_visible == b.settle_visible &&
|
||||
a.volume_visible == b.volume_visible &&
|
||||
a.account_visible == b.account_visible &&
|
||||
a.tif_visible == b.tif_visible &&
|
||||
a.order_type_visible == b.order_type_visible &&
|
||||
a.account_position_visible == b.account_position_visible &&
|
||||
a.day_position_visible == b.day_position_visible &&
|
||||
a.raw_day_position_visible == b.raw_day_position_visible &&
|
||||
a.size_presets_visible == b.size_presets_visible &&
|
||||
a.cancel_buys_visible == b.cancel_buys_visible &&
|
||||
a.cancel_sells_visible == b.cancel_sells_visible &&
|
||||
a.cancel_all_visible == b.cancel_all_visible &&
|
||||
a.auto_clear_visible == b.auto_clear_visible &&
|
||||
a.clear_visible == b.clear_visible &&
|
||||
a.order_entry_panel_initial_width == b.order_entry_panel_initial_width &&
|
||||
a.zoom_slider_visible == b.zoom_slider_visible &&
|
||||
a.zoom_factor == b.zoom_factor &&
|
||||
a.use_defaults == b.use_defaults &&
|
||||
a.favorite_algos == b.favorite_algos &&
|
||||
a.net_change == b.net_change &&
|
||||
a.show_warn_on_cross == b.show_warn_on_cross &&
|
||||
a.mini_ob == b.mini_ob;
|
||||
|
||||
public bool Equals(LadderSettings other) =>
|
||||
other != null &&
|
||||
row_height == other.row_height &&
|
||||
grid_line_color == other.grid_line_color &&
|
||||
orders_column.safe_equals(other.orders_column) &&
|
||||
bid_column.safe_equals(other.bid_column) &&
|
||||
ask_column.safe_equals(other.ask_column) &&
|
||||
price_column.safe_equals(other.price_column) &&
|
||||
last_column.safe_equals(other.last_column) &&
|
||||
piq_column.safe_equals(other.piq_column) &&
|
||||
calculator_buttons.safe_equals(other.calculator_buttons, (a, b) => a.SequenceEqual(b)) &&
|
||||
scroll_bar_visible == other.scroll_bar_visible &&
|
||||
default_account == other.default_account &&
|
||||
profile_equals(this, other) &&
|
||||
default_algo == other.default_algo &&
|
||||
default_time_in_force == other.default_time_in_force &&
|
||||
size == other.size &&
|
||||
animate_recenter == other.animate_recenter &&
|
||||
badge_style == other.badge_style &&
|
||||
auto_clear == other.auto_clear &&
|
||||
bid_break_line.safe_equals(other.bid_break_line) &&
|
||||
ask_break_line.safe_equals(other.ask_break_line) &&
|
||||
mid_break_line.safe_equals(other.mid_break_line) &&
|
||||
alternate_order_size == other.alternate_order_size &&
|
||||
session_low_line.safe_equals(other.session_low_line) &&
|
||||
session_high_line.safe_equals(other.session_high_line) &&
|
||||
session_range_fill.safe_equals(other.session_range_fill) &&
|
||||
volume_column.safe_equals(other.volume_column) &&
|
||||
size_display.safe_equals(other.size_display) &&
|
||||
day_visible == other.day_visible &&
|
||||
high_visible == other.high_visible &&
|
||||
low_visible == other.low_visible &&
|
||||
open_visible == other.open_visible &&
|
||||
settle_visible == other.settle_visible &&
|
||||
volume_visible == other.volume_visible &&
|
||||
account_visible == other.account_visible &&
|
||||
tif_visible == other.tif_visible &&
|
||||
order_type_visible == other.order_type_visible &&
|
||||
account_position_visible == other.account_position_visible &&
|
||||
day_position_visible == other.day_position_visible &&
|
||||
size_presets_visible == other.size_presets_visible &&
|
||||
cancel_buys_visible == other.cancel_buys_visible &&
|
||||
cancel_sells_visible == other.cancel_sells_visible &&
|
||||
cancel_all_visible == other.cancel_all_visible &&
|
||||
auto_clear_visible == other.auto_clear_visible &&
|
||||
clear_visible == other.clear_visible &&
|
||||
order_entry_panel_initial_width == other.order_entry_panel_initial_width &&
|
||||
zoom_slider_visible == other.zoom_slider_visible &&
|
||||
zoom_factor == other.zoom_factor &&
|
||||
use_defaults == other.use_defaults &&
|
||||
favorite_algos == other.favorite_algos &&
|
||||
net_change == other.net_change &&
|
||||
show_warn_on_cross == other.show_warn_on_cross &&
|
||||
mini_ob == other.mini_ob;
|
||||
left_panel_scroll_position == other.left_panel_scroll_position;
|
||||
|
||||
public override bool Equals(object obj) => Equals(obj as LadderSettings);
|
||||
|
||||
// TODO: remove mutable props from hash logic (or conversely, make them immutable).
|
||||
public override int GetHashCode() =>
|
||||
EqualityComparer.aggregate_hash(
|
||||
row_height.GetHashCode(),
|
||||
grid_line_color.GetHashCode(),
|
||||
EqualityComparer.safe_get_hash_code(orders_column),
|
||||
EqualityComparer.safe_get_hash_code(bid_column),
|
||||
EqualityComparer.safe_get_hash_code(ask_column),
|
||||
EqualityComparer.safe_get_hash_code(price_column),
|
||||
EqualityComparer.safe_get_hash_code(last_column),
|
||||
EqualityComparer.safe_get_hash_code(piq_column),
|
||||
EqualityComparer.safe_get_hash_code(calculator_buttons),
|
||||
scroll_bar_visible.GetHashCode(),
|
||||
default_time_in_force.GetHashCode(),
|
||||
size.GetHashCode(),
|
||||
animate_recenter.GetHashCode(),
|
||||
badge_style.GetHashCode(),
|
||||
EqualityComparer.safe_get_hash_code(bid_break_line),
|
||||
EqualityComparer.safe_get_hash_code(ask_break_line),
|
||||
EqualityComparer.safe_get_hash_code(mid_break_line),
|
||||
alternate_order_size.GetHashCode(),
|
||||
EqualityComparer.safe_get_hash_code(session_low_line),
|
||||
EqualityComparer.safe_get_hash_code(session_high_line),
|
||||
EqualityComparer.safe_get_hash_code(session_range_fill),
|
||||
EqualityComparer.safe_get_hash_code(volume_column),
|
||||
EqualityComparer.safe_get_hash_code(size_display),
|
||||
day_visible.GetHashCode(),
|
||||
high_visible.GetHashCode(),
|
||||
low_visible.GetHashCode(),
|
||||
open_visible.GetHashCode(),
|
||||
settle_visible.GetHashCode(),
|
||||
volume_visible.GetHashCode(),
|
||||
account_visible.GetHashCode(),
|
||||
tif_visible.GetHashCode(),
|
||||
order_type_visible.GetHashCode(),
|
||||
account_position_visible.GetHashCode(),
|
||||
size_presets_visible.GetHashCode(),
|
||||
cancel_buys_visible.GetHashCode(),
|
||||
cancel_sells_visible.GetHashCode(),
|
||||
cancel_all_visible.GetHashCode(),
|
||||
auto_clear_visible.GetHashCode(),
|
||||
clear_visible.GetHashCode(),
|
||||
order_entry_panel_initial_width.GetHashCode(),
|
||||
zoom_slider_visible.GetHashCode(),
|
||||
zoom_factor.GetHashCode(),
|
||||
use_defaults.GetHashCode(),
|
||||
favorite_algos.GetHashCode(),
|
||||
net_change.GetHashCode(),
|
||||
show_warn_on_cross.GetHashCode());
|
||||
public override int GetHashCode() => _type_hash;
|
||||
|
||||
public struct WindowSpecifics {
|
||||
public readonly double order_entry_panel_width, zoom_factor;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using bts.api;
|
||||
using bts.collections;
|
||||
using bts.md;
|
||||
using mbts;
|
||||
using mbts.config;
|
||||
@@ -11,10 +12,10 @@ using ProtoBuf;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
using System.Reactive.Subjects;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using LadderSettings = mbts.spark.LadderSettings;
|
||||
@@ -22,31 +23,35 @@ using LadderSettings = mbts.spark.LadderSettings;
|
||||
namespace bts.shell {
|
||||
class LadderWindowFactory : ShellWindowFactory<LadderSaveState> {
|
||||
const string _window_type = "ladder";
|
||||
const int _version_where_stickied_algos_introduced = 2;
|
||||
readonly LadderConfig _ladder_conf;
|
||||
readonly IBus _bus;
|
||||
readonly IWindowManager _wm;
|
||||
readonly MBOService _mbo;
|
||||
readonly UserSettingsHub _settings_hub;
|
||||
readonly OrdersModel _orders_model;
|
||||
readonly IShellWindowThreadIDProvider _thread_id_provider;
|
||||
IReadOnlyDictionary<uint, SecurityMD> _securities = new Dictionary<uint, SecurityMD>();
|
||||
|
||||
public LadderWindowFactory(
|
||||
IShellModule owner,
|
||||
IBus bus,
|
||||
IWindowManager wm,
|
||||
UserSettingsHub settings_hub,
|
||||
IShellModule owner,
|
||||
IBus bus,
|
||||
IWindowManager wm,
|
||||
UserSettingsHub settings_hub,
|
||||
OrdersModel orders_model,
|
||||
MBOService mbo)
|
||||
|
||||
: base(owner, "SparkLadder") {
|
||||
: base(owner, "SparkLadder", 2) {
|
||||
_bus = bus;
|
||||
_wm = wm;
|
||||
_settings_hub = settings_hub;
|
||||
_orders_model = orders_model;
|
||||
_ladder_conf = new LadderConfig(Configuration.get<bts.config.LadderKnobs>(), Configuration.get<bts.config.MultiThreadedWindows>().ladder);
|
||||
_thread_id_provider = ShellWindowThreadIDFactory.create("Ladder", _ladder_conf.ladders_on_threads);
|
||||
_mbo = mbo;
|
||||
_dispose = Disposable.Create(
|
||||
bus.subscribe(SparkTags.SecuritiesTag).Subscribe(s => _securities = s),
|
||||
bus.subscribe(SparkTags.ShowLadderAutoLookupTag).Subscribe(_show_windows),
|
||||
bus.subscribe(SparkTags.ShowLadderTag).OnDispatcher().Subscribe(s => show_windows(new[] { s })),
|
||||
bus.subscribe(SparkTags.ShowLaddersTag).OnDispatcher().Subscribe(show_windows)
|
||||
);
|
||||
@@ -60,26 +65,32 @@ namespace bts.shell {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected override Task<IShellWindow> try_upgrade_state(Stream load_stream, int version) {
|
||||
var state = ProtoBuf.Serializer.DeserializeWithLengthPrefix<LadderSaveState>(load_stream, ProtoBuf.PrefixStyle.Fixed32);
|
||||
if (version < _version_where_stickied_algos_introduced) {
|
||||
// We want to assign any existing favorite algos to stickied algos upon setting upgrade
|
||||
var favorite_algos_array = state.settings.favorite_algos.favorite_algos.ToArray();
|
||||
state.settings.favorite_algos = new LadderFavoriteAlgosSettings(favorite_algos_array, state.settings.favorite_algos.column_count, favorite_algos_array);
|
||||
}
|
||||
return load(state);
|
||||
}
|
||||
|
||||
LadderSaveState _get_state(LadderVM vm, uint id) {
|
||||
LadderSettings s = vm.get_save_state();
|
||||
if (id != 0) {
|
||||
if (!_settings_hub.current.ladder_profiles.TryGetFirst(lp => lp.id == id, out var result)) {
|
||||
// profile was deleted
|
||||
id = 0;
|
||||
} else {
|
||||
if (!s.Equals(result.value)) {
|
||||
// ladder's settings diverged from the profile (this happens when the user changes settings outside of the settings dialog, such as column widths, left panel width, etc.)
|
||||
id = 0;
|
||||
}
|
||||
} else if (!LadderSettings.profile_equals(s, result.value)) {
|
||||
// ladder's settings diverged from the profile (this happens when the user changes settings outside of the settings dialog, such as column widths, left panel width, etc.)
|
||||
id = 0;
|
||||
}
|
||||
}
|
||||
return new LadderSaveState { security_key = vm.security.Id, settings = s, settings_id = id };
|
||||
}
|
||||
|
||||
int _ladder_count = 0;
|
||||
IShellWindow create_ladder_window(SecurityMD md, LadderSettings last_value, uint settings_id = 0) {
|
||||
IDisposable active_settings_dialog = null;
|
||||
var thread_id = Interlocked.Increment(ref _ladder_count) % Environment.ProcessorCount;
|
||||
// on_shell_window_vm should behave like an event (do not set to null)
|
||||
Action<ShellWindowVM> on_shell_window_vm = _ => { };
|
||||
ShellWindowVM shell_window_vm = null;
|
||||
@@ -136,7 +147,7 @@ namespace bts.shell {
|
||||
var curr = vm.get_save_state();
|
||||
if (settings_id == 0) {
|
||||
last_value = curr;
|
||||
} else if (!curr.Equals(last_value)) {
|
||||
} else if (!LadderSettings.profile_equals(curr, last_value)) {
|
||||
settings_id = 0;
|
||||
last_value = curr;
|
||||
}
|
||||
@@ -150,7 +161,7 @@ namespace bts.shell {
|
||||
// not on a profile, don't respond to default settings changes
|
||||
return;
|
||||
} else if (us.ladder_profiles.TryGetFirst(p => p.id == settings_id, out var profile)) {
|
||||
if (!last_value.Equals(vm.get_save_state())) {
|
||||
if (!LadderSettings.profile_equals(last_value, vm.get_save_state())) {
|
||||
settings_id = 0;
|
||||
} else {
|
||||
settings_subject.OnNext(last_value = profile.value);
|
||||
@@ -198,6 +209,7 @@ namespace bts.shell {
|
||||
_ => _,
|
||||
vm.get_save_state(),
|
||||
UserSettings.FileExtensions.LADDER,
|
||||
LadderSettings.profile_equals,
|
||||
settings_id);
|
||||
dialog_vm.applied += apply;
|
||||
// dialog
|
||||
@@ -251,19 +263,32 @@ namespace bts.shell {
|
||||
Log.Ui.warn($"LadderSettingsDialog error {action_desc}: {error}.");
|
||||
}
|
||||
});
|
||||
string thread = _ladder_conf.ladders_on_threads ? $"Ladder{thread_id:00}" : "";
|
||||
return shell_window = ShellWindow.create(
|
||||
module, md.security.ToString(), _window_type, view,
|
||||
(v, s) => save(_get_state(((LadderView)v).vm, settings_id), s),
|
||||
icon: Icons.Ladder,
|
||||
thread_id: thread,
|
||||
thread_id: _thread_id_provider.next_id(),
|
||||
vm => {
|
||||
shell_window_vm = vm;
|
||||
title_source.connect();
|
||||
});
|
||||
}
|
||||
|
||||
void show_windows(IReadOnlyCollection<SecurityMD> securities) {
|
||||
async void _show_windows(IImmutableSet<uint> securities) {
|
||||
if (securities == null)
|
||||
return;
|
||||
var start_time = DateTime.Now;
|
||||
do {
|
||||
var found = securities.KeyJoin(_securities).ToList();
|
||||
securities = securities.RemoveRange(found.Select(SecurityMD.key_fn));
|
||||
show_windows(found);
|
||||
if (securities.Count == 0)
|
||||
break;
|
||||
await Task.Delay(500);
|
||||
} while ((DateTime.Now - start_time) < _ladder_conf.security_timeout);
|
||||
}
|
||||
|
||||
void show_windows(IEnumerable<SecurityMD> securities) {
|
||||
int n_allowed = (int)_ladder_conf.max_open_ladders - _wm.list_windows().Where(w => w.window_type == _window_type).Count();
|
||||
int n_opened = 0;
|
||||
foreach (var s in securities) {
|
||||
@@ -301,4 +326,4 @@ namespace bts.shell {
|
||||
[ProtoMember(3)]
|
||||
public uint settings_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
using bts.api;
|
||||
using bts.api.orderman;
|
||||
using bts.collections;
|
||||
using bts.persist.algo;
|
||||
using bts.shell.orderbook;
|
||||
using bts.utils;
|
||||
using mbts.collections;
|
||||
@@ -71,6 +72,7 @@ namespace mbts.spark {
|
||||
_order_type_visibility = new OrderEntryPanelItemVisibilityVM("Order Type"),
|
||||
_account_position_visibility = new OrderEntryPanelItemVisibilityVM("Account Position"),
|
||||
_day_position_visibility = new OrderEntryPanelItemVisibilityVM("Day Position"),
|
||||
_raw_day_position_visibility = new OrderEntryPanelItemVisibilityVM("Raw Day Position"),
|
||||
_size_preset_visibility = new OrderEntryPanelItemVisibilityVM("Size Presets"),
|
||||
_auto_clear_visibility = new OrderEntryPanelItemVisibilityVM("Auto Clear"),
|
||||
_clear_visibility = new OrderEntryPanelItemVisibilityVM("Clear"),
|
||||
@@ -135,8 +137,8 @@ namespace mbts.spark {
|
||||
foreach (var c in _observable_components)
|
||||
c.PropertyChanged -= on_prop_changed;
|
||||
}
|
||||
AccountTuple? account_factory(KeyValuePair<uint, string> kv) => new AccountTuple(kv.Key, kv.Value);
|
||||
AlgoDefinitionVM algo_factory(AlgoData data) => AlgoDefinitionVM.create(_model, data);
|
||||
AccountTuple? account_factory(uint key, string name) => new AccountTuple(key, name);
|
||||
AlgoDefinitionVM algo_factory(AlgoData data) => AlgoDefinitionVM.create(_model, data, is_synthetic ? AlgoFormats.Spreader : AlgoFormats.Exchange);
|
||||
}
|
||||
|
||||
public event Action result_changed;
|
||||
@@ -238,6 +240,7 @@ namespace mbts.spark {
|
||||
yield return _order_type_visibility;
|
||||
yield return _account_position_visibility;
|
||||
yield return _day_position_visibility;
|
||||
yield return _raw_day_position_visibility;
|
||||
yield return _size_preset_visibility;
|
||||
yield return _clear_visibility;
|
||||
yield return _auto_clear_visibility;
|
||||
@@ -280,6 +283,7 @@ namespace mbts.spark {
|
||||
yield return _order_type_visibility;
|
||||
yield return _account_position_visibility;
|
||||
yield return _day_position_visibility;
|
||||
yield return _raw_day_position_visibility;
|
||||
yield return _size_preset_visibility;
|
||||
yield return _auto_clear_visibility;
|
||||
yield return _clear_visibility;
|
||||
@@ -342,6 +346,7 @@ namespace mbts.spark {
|
||||
_order_type_visibility.show = settings.order_type_visible;
|
||||
_account_position_visibility.show = settings.account_position_visible;
|
||||
_day_position_visibility.show = settings.day_position_visible;
|
||||
_raw_day_position_visibility.show = settings.raw_day_position_visible;
|
||||
_size_preset_visibility.show = settings.size_presets_visible;
|
||||
_clear_visibility.show = settings.clear_visible;
|
||||
_auto_clear_visibility.show = settings.auto_clear_visible;
|
||||
@@ -414,6 +419,7 @@ namespace mbts.spark {
|
||||
clone.order_type_visible = _order_type_visibility.show;
|
||||
clone.account_position_visible = _account_position_visibility.show;
|
||||
clone.day_position_visible = _day_position_visibility.show;
|
||||
clone.raw_day_position_visible = _raw_day_position_visibility.show;
|
||||
clone.size_presets_visible = _size_preset_visibility.show;
|
||||
clone.auto_clear_visible = _auto_clear_visibility.show;
|
||||
clone.clear_visible = _clear_visibility.show;
|
||||
@@ -723,12 +729,15 @@ namespace mbts.spark {
|
||||
readonly IObservableCollection<AlgoDefinitionVM> _algo_definitions;
|
||||
readonly ObservableCollection<FavoriteAlgoItem> _raw_items = new ObservableCollection<FavoriteAlgoItem>();
|
||||
int _column_count = 2;
|
||||
HashSet<AlgoPersistedKey> _sticky_algo_keys;
|
||||
IDisposable _sticky_algos_hook;
|
||||
|
||||
public FavoriteAlgosVM(IObservableCollection<AlgoDefinitionVM> algo_definitions) {
|
||||
_algo_definitions = algo_definitions;
|
||||
items = new ObservableAggregateCollection<FavoriteAlgoItem>(_raw_items, new ObservableCollection<FavoriteAlgoItem> { FavoriteAlgoItem.AddButtonPlaceholderItem });
|
||||
add_item_cmd = new DelegateCommand(() => _raw_items.Add(_item_factory()));
|
||||
remove_item_cmd = new DelegateCommand<FavoriteAlgoItem>(fai => _raw_items.Remove(fai));
|
||||
_dispose = Disposable.Create(() => Disposable.dispose(ref _sticky_algos_hook));
|
||||
}
|
||||
|
||||
public ObservableCollection<FavoriteAlgoItem> items { get; }
|
||||
@@ -745,6 +754,17 @@ namespace mbts.spark {
|
||||
fai.selector.try_select(k);
|
||||
return fai;
|
||||
}));
|
||||
_sticky_algo_keys = new HashSet<AlgoPersistedKey>(value.stickied_algos.Where(k => k.is_persisted).Select(x => new AlgoPersistedKey(x.persisted)));
|
||||
Disposable.replace(ref _sticky_algos_hook,
|
||||
ObservableAutoWrapper.connect_item_hooks(_raw_items, x =>
|
||||
x.selector.subscribe_value().Subscribe(algo => {
|
||||
if (algo != null &&
|
||||
algo.key.is_persisted &&
|
||||
(x.is_sticky = _sticky_algo_keys.Remove(new AlgoPersistedKey(algo.key.persisted))) &&
|
||||
_sticky_algo_keys.Count == 0)
|
||||
//
|
||||
Disposable.dispose(ref _sticky_algos_hook);
|
||||
})));
|
||||
}
|
||||
|
||||
public LadderFavoriteAlgosSettings create() =>
|
||||
@@ -753,7 +773,13 @@ namespace mbts.spark {
|
||||
.Where(k => k.HasValue && k.Value.is_persisted)
|
||||
.Select(k => k.Value)
|
||||
.ToArray(),
|
||||
column_count);
|
||||
column_count,
|
||||
_raw_items
|
||||
.Where(fai => fai.is_sticky)
|
||||
.Select(fai => fai.algo_definition?.key ?? fai.selector.desired_key)
|
||||
.Where(k => k.HasValue && k.Value.is_persisted)
|
||||
.Select(k => k.Value)
|
||||
.ToArray());
|
||||
|
||||
FavoriteAlgoItem _item_factory() =>
|
||||
new FavoriteAlgoItem(_algo_definitions, new ListCollectionView<AlgoDefinitionVM>(_algo_definitions) {
|
||||
@@ -766,6 +792,7 @@ namespace mbts.spark {
|
||||
public static readonly FavoriteAlgoItem AddButtonPlaceholderItem = new _AddButtonPlaceholderItem();
|
||||
|
||||
internal readonly KeyedItemSelector<AlgoDefinitionVM, AlgoKey> selector;
|
||||
bool _is_sticky;
|
||||
|
||||
protected FavoriteAlgoItem() { }
|
||||
|
||||
@@ -776,6 +803,7 @@ namespace mbts.spark {
|
||||
|
||||
public ICollectionView<AlgoDefinitionVM> algo_definitions_view { get; }
|
||||
public AlgoDefinitionVM algo_definition { get => selector.value; set => selector.value = value; }
|
||||
public bool is_sticky { get => _is_sticky; set => Set(ref _is_sticky, value); }
|
||||
|
||||
class _AddButtonPlaceholderItem : FavoriteAlgoItem, ITemplateSelectorKey {
|
||||
public string key => LadderSettingsView.FavoriteAlgoAddButtonTemplateKey;
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
using bts.api;
|
||||
using bts.api.orderman;
|
||||
using bts.collections;
|
||||
using bts.shell;
|
||||
using bts.spark;
|
||||
using bts.utils;
|
||||
using mbts.co2;
|
||||
using mbts.spark.utilities;
|
||||
using mbts.ui;
|
||||
using mbts.ui.shell;
|
||||
using mbts.utils;
|
||||
@@ -32,8 +34,16 @@ namespace mbts.spark {
|
||||
_show_tif, _show_order_type, _show_size_preset, _show_auto_clear, _show_clear, _show_cancel_buys,
|
||||
_show_cancel_sells, _show_cancel_all, _show_zoom;
|
||||
readonly PropertyAutoWrapper<LadderSettings, Brush> _bid_background, _bid_foreground, _ask_background, _ask_foreground;
|
||||
double _position, _day_position;
|
||||
bool _show_account_position, _show_day_position;
|
||||
readonly HashSet<AlgoKey> _sticky_algos = new HashSet<AlgoKey>();
|
||||
double
|
||||
_position,
|
||||
_day_position,
|
||||
_raw_day_position,
|
||||
_left_panel_extent_height,
|
||||
_left_panel_view_port_height,
|
||||
_left_panel_scroll_position,
|
||||
_left_panel_scroll_position_target;
|
||||
bool _show_account_position, _show_day_position, _show_raw_day_position;
|
||||
ulong _misc_time = 0;
|
||||
ulong _last_trade_time = 0;
|
||||
IEqualityComparer<double> _equality;
|
||||
@@ -73,6 +83,7 @@ namespace mbts.spark {
|
||||
_volume_column_width = backing(nameof(volume_column_width), ws.volume_column_width);
|
||||
_left_panel_width = backing(nameof(left_panel_width), ws.order_entry_panel_width);
|
||||
_zoom_factor = backing(nameof(zoom_factor), ws.zoom_factor);
|
||||
_left_panel_scroll_position_target = init.left_panel_scroll_position;
|
||||
// remember: account_positions needs to subscribe to selected_account; both the sub and account_positions need to be disposed
|
||||
_volume = backing(nameof(volume), 0ul);
|
||||
_auto_clear = backing(nameof(auto_clear), init.auto_clear);
|
||||
@@ -106,7 +117,10 @@ namespace mbts.spark {
|
||||
(_show_cancel_all = bool_prop(nameof(show_cancel_all), s => s.cancel_all_visible)).set,
|
||||
(_show_zoom = bool_prop(nameof(show_zoom), s => s.zoom_slider_visible)).set,
|
||||
s => {
|
||||
if (Set(ref _show_account_position, s.account_position_visible, nameof(show_account_position)) | Set(ref _show_day_position, s.day_position_visible, nameof(show_day_position))) {
|
||||
if (
|
||||
Set(ref _show_account_position, s.account_position_visible, nameof(show_account_position)) |
|
||||
Set(ref _show_day_position, s.day_position_visible, nameof(show_day_position)) |
|
||||
Set(ref _show_raw_day_position, s.raw_day_position_visible, nameof(show_raw_day_position))) {
|
||||
RaisePropertyChanged(nameof(position_display_text));
|
||||
}
|
||||
size_calculator.buttons = s.calculator_buttons;
|
||||
@@ -132,8 +146,8 @@ namespace mbts.spark {
|
||||
//
|
||||
//_window_height = backing(nameof(window_height), settings_manager.subscribe_current().OnDispatcher().Select(s => s.zoom_factor), (scale) => scale * 600);
|
||||
//_window_width = backing(nameof(window_width), settings_manager.subscribe_current().OnDispatcher().Select(s => s.zoom_factor), (scale) => scale * 420);
|
||||
position_click_command = new DelegateCommand(() => size_calculator.value = DoubleHelper.safe_convert_to_uint(Math.Abs(_show_day_position ? day_position : position)));
|
||||
send_order_command = new DelegateCommand<(double price, Side? side, MouseButton button)>(send_order);
|
||||
position_click_command = new DelegateCommand(() => size_calculator.value = DoubleHelper.safe_convert_to_uint(Math.Abs(_show_day_position ? day_position : (_show_raw_day_position ? _raw_day_position : position))));
|
||||
send_order_command = new AsyncCommand<(double price, Side? side, MouseButton button)>(send_order_async);
|
||||
cancel_command = new AsyncCommand<LadderModel.CancelType>(_model.cancel_orders, true);
|
||||
show_book_command = new DelegateCommand(_show_book);
|
||||
show_ticket_command = new DelegateCommand(_show_ticket);
|
||||
@@ -223,17 +237,25 @@ namespace mbts.spark {
|
||||
.SelectManyInSeries(a => _model.order_gateway.on_security_positions(security.Id)
|
||||
.Select(table => table.state.Values.FirstOrDefault(pos => pos.Item2.Account == a, tup => tup.Item2, (bts.api.position.PositionUnitImmutable?)null)));
|
||||
return Disposable.Create(
|
||||
settings.OnDispatcher().Subscribe(s => order_properties_vm.on_favorite_algos(s.favorite_algos)),
|
||||
settings.OnDispatcher().Subscribe(s => {
|
||||
_sticky_algos.SetItems(s.favorite_algos.stickied_algos);
|
||||
order_properties_vm.on_favorite_algos(s.favorite_algos);
|
||||
}),
|
||||
order_properties_vm,
|
||||
position_src.OnDispatcher().Subscribe(pos => {
|
||||
double total, day;
|
||||
double total, day, raw_day;
|
||||
if (pos.HasValue) {
|
||||
total = pos.Value.total_pos();
|
||||
day = pos.Value.day_pos();
|
||||
raw_day = pos.Value.raw_day_pos();
|
||||
} else {
|
||||
total = day = double.NaN;
|
||||
total = day = raw_day = double.NaN;
|
||||
}
|
||||
if ((Set(ref _position, total, nameof(position)) | Set(ref _day_position, day, nameof(day_position))) && (show_day_position || show_account_position))
|
||||
if ((
|
||||
Set(ref _position, total, nameof(position)) |
|
||||
Set(ref _day_position, day, nameof(day_position)) |
|
||||
Set(ref _raw_day_position, raw_day, nameof(raw_day_position))
|
||||
) && (show_day_position || show_account_position || show_raw_day_position))
|
||||
RaisePropertyChanged(nameof(position_display_text));
|
||||
}));
|
||||
}
|
||||
@@ -284,6 +306,7 @@ namespace mbts.spark {
|
||||
public double settlement => _settlement.Value;
|
||||
public double position => _position;
|
||||
public double day_position => _day_position;
|
||||
public double raw_day_position => _raw_day_position;
|
||||
public ulong volume => _volume.Value;
|
||||
public bool auto_clear { get => _auto_clear.Value; set => _auto_clear.set(value); }
|
||||
public CalculatorLogic size_calculator { get; } = new CalculatorLogic(0);
|
||||
@@ -310,6 +333,7 @@ namespace mbts.spark {
|
||||
public bool show_order_type => _show_order_type.view;
|
||||
public bool show_account_position => _show_account_position;
|
||||
public bool show_day_position => _show_day_position;
|
||||
public bool show_raw_day_position => _show_raw_day_position;
|
||||
public bool show_size_preset => _show_size_preset.view;
|
||||
public bool show_auto_clear => _show_auto_clear.view;
|
||||
public bool show_clear => _show_clear.view;
|
||||
@@ -317,16 +341,49 @@ namespace mbts.spark {
|
||||
public bool show_cancel_sells => _show_cancel_sells.view;
|
||||
public bool show_cancel_all => _show_cancel_all.view;
|
||||
public bool show_zoom => _show_zoom.view;
|
||||
// left panel scroll props
|
||||
public double left_panel_view_port_height {
|
||||
get => _left_panel_view_port_height;
|
||||
set {
|
||||
using (detect_property_changes(nameof(left_panel_scroll_position)))
|
||||
_left_panel_view_port_height = value;
|
||||
}
|
||||
}
|
||||
public double left_panel_scroll_position {
|
||||
get {
|
||||
if (!_left_panel_scroll_position_target.is_nan()) {
|
||||
if (_left_panel_scroll_position_target < _max_left_panel_scroll_position) {
|
||||
_left_panel_scroll_position = _left_panel_scroll_position_target;
|
||||
_left_panel_scroll_position_target = double.NaN;
|
||||
}
|
||||
}
|
||||
return Math.Min(_left_panel_scroll_position, _left_panel_extent_height);
|
||||
}
|
||||
set => Set(ref _left_panel_scroll_position, value);
|
||||
}
|
||||
public double left_panel_extent_height {
|
||||
get => _left_panel_extent_height;
|
||||
set {
|
||||
using (detect_property_changes(nameof(left_panel_scroll_position)))
|
||||
Set(ref _left_panel_extent_height, value);
|
||||
}
|
||||
}
|
||||
public double left_panel_width { get => _left_panel_width.Value; set => _left_panel_width.set(value); }
|
||||
public double zoom_factor { get => _zoom_factor.Value; set => _zoom_factor.set(value); }
|
||||
public string position_display_text {
|
||||
get {
|
||||
if (show_day_position) {
|
||||
string day_pos_text = SparkUtils.fmt_position(day_position);
|
||||
return show_account_position ? $"{day_pos_text} ({SparkUtils.fmt_position(position)})" : day_pos_text;
|
||||
} else if (show_account_position) {
|
||||
return SparkUtils.fmt_position(position);
|
||||
} else return string.Empty;
|
||||
string rv = null;
|
||||
if (show_day_position)
|
||||
rv = SparkUtils.fmt_position(day_position);
|
||||
if (show_raw_day_position) {
|
||||
var raw_day_text = SparkUtils.fmt_position(raw_day_position);
|
||||
rv = rv == null ? raw_day_text : $"{rv} / {raw_day_text}";
|
||||
}
|
||||
if (show_account_position) {
|
||||
var acc_text = SparkUtils.fmt_position(position);
|
||||
rv = rv == null ? SparkUtils.fmt_position(position) : $"{rv} ({acc_text})";
|
||||
}
|
||||
return rv ?? "";
|
||||
}
|
||||
}
|
||||
//public double window_height { get => _window_height.Value; set => _window_height.set(value); }
|
||||
@@ -342,6 +399,10 @@ namespace mbts.spark {
|
||||
public bool show_warn_on_cross_from_settings => current_settings.show_warn_on_cross;
|
||||
internal LadderModel model => _model;
|
||||
internal IObservable<LadderSettings> settings { get; }
|
||||
|
||||
double _max_left_panel_scroll_position =>
|
||||
Math.Max(0, _left_panel_extent_height - _left_panel_view_port_height);
|
||||
|
||||
internal OrderRecordImmutable get_root_at_price((OrderRecordImmutable order, uint? _, AlgoData? __, AlgoDefinitionMetadata? meta) op) {
|
||||
var order = op.order;
|
||||
double p = order.price();
|
||||
@@ -372,6 +433,7 @@ namespace mbts.spark {
|
||||
zoom_factor,
|
||||
piq_column_width));
|
||||
rv.auto_clear = auto_clear;
|
||||
rv.left_panel_scroll_position = left_panel_scroll_position;
|
||||
if (order_properties_vm != null) {
|
||||
rv.default_time_in_force = order_properties_vm.selected_time_in_force;
|
||||
if (order_properties_vm.selected_account.HasValue)
|
||||
@@ -400,20 +462,19 @@ namespace mbts.spark {
|
||||
settings_invalidated?.Invoke();
|
||||
}
|
||||
|
||||
public void send_order((double price, Side? side, MouseButton button) args) {
|
||||
if (order_properties_vm == null || args.button == MouseButton.Middle)
|
||||
return;
|
||||
var size_from_alternate = args.button == MouseButton.Right;
|
||||
if (DoubleHelper.IsNaNOrInfinity(args.price) || !args.side.HasValue || HasErrors || order_properties_vm.HasErrors || (size_from_alternate && current_settings.alternate_order_size == 0)) {
|
||||
return;
|
||||
}
|
||||
if (!size_from_alternate && (!size_calculator.value.HasValue || size_calculator.value.Value == 0)) {
|
||||
size_calculator.flash_error();
|
||||
}
|
||||
else {
|
||||
uint size = size_from_alternate ? current_settings.alternate_order_size : (uint)Math.Abs(size_calculator.value ?? 0);
|
||||
send_order_async(args.side.Value, size, args.price).ignore();
|
||||
public Task send_order_async((double price, Side? side, MouseButton button) args) {
|
||||
if (order_properties_vm != null && args.button != MouseButton.Middle) {
|
||||
var size_from_alternate = args.button == MouseButton.Right;
|
||||
if (!DoubleHelper.IsNaNOrInfinity(args.price) && args.side.HasValue && !HasErrors && !order_properties_vm.HasErrors && (!size_from_alternate || current_settings.alternate_order_size > 0)) {
|
||||
if (!size_from_alternate && (!size_calculator.value.HasValue || size_calculator.value.Value == 0)) {
|
||||
size_calculator.flash_error();
|
||||
} else {
|
||||
uint size = size_from_alternate ? current_settings.alternate_order_size : (uint)Math.Abs(size_calculator.value ?? 0);
|
||||
return send_order_async(args.side.Value, size, args.price);
|
||||
}
|
||||
}
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public async Task send_order_async(Side side, uint size, double price) {
|
||||
@@ -430,9 +491,16 @@ namespace mbts.spark {
|
||||
price = temp_price;
|
||||
}
|
||||
}
|
||||
await _model.order_gateway.send_order(order, price, size);
|
||||
await _model.order_gateway.send_order(security, order, price, size);
|
||||
if (auto_clear)
|
||||
size_calculator.value = 0;
|
||||
var fav_algo = order_properties_vm.selected_favorite_algo_definition;
|
||||
if (fav_algo != null && !_sticky_algos.Contains(fav_algo.key) && !order_properties_vm.try_pop_selected_algo_definition()) {
|
||||
var key = new AlgoKey(OrderDataHelper.get_default_algo(OrderDataHelper.get_algo_format(security.ContractCase)));
|
||||
if (order_properties_vm.try_get_algo_definition(key, out var r)) {
|
||||
order_properties_vm.selected_algo_definition = r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _update_header() {
|
||||
|
||||
@@ -805,6 +805,7 @@
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="c0"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="c1"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Button Command="{Binding DataContext.remove_item_cmd, RelativeSource={RelativeSource AncestorType=ItemsControl}}" CommandParameter="{Binding}" Style="{StaticResource RoundCloseButton}"/>
|
||||
<ComboBox Grid.Column="1" ItemsSource="{Binding algo_definitions_view}" SelectedItem="{Binding algo_definition}">
|
||||
@@ -814,6 +815,7 @@
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
<CheckBox Grid.Column="2" VerticalAlignment="Center" VerticalContentAlignment="Center" IsChecked="{Binding is_sticky}"> Stay Enabled?</CheckBox>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</u:KeyedTemplateSelector.Default>
|
||||
@@ -823,6 +825,7 @@
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="c0"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="c1"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Button Grid.Column="1" HorizontalAlignment="Stretch" Command="{Binding DataContext.add_item_cmd, RelativeSource={RelativeSource AncestorType=ItemsControl}}">Add</Button>
|
||||
</Grid>
|
||||
|
||||
@@ -301,7 +301,14 @@
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<ScrollViewer Grid.Row="0" Grid.RowSpan="2" VerticalScrollBarVisibility="Hidden">
|
||||
<ScrollViewer
|
||||
x:Name="_left_panel_scroll"
|
||||
Grid.Row="0"
|
||||
Grid.RowSpan="2"
|
||||
mbts:ScrollViewerBehavior.VerticalOffset="{Binding left_panel_scroll_position, Mode=TwoWay}"
|
||||
mbts:ScrollViewerBehavior.EnableTwoWayVerticalOffsetBinding="True"
|
||||
VerticalScrollBarVisibility="Hidden"
|
||||
>
|
||||
<Grid RowSpan="2" Background="{mbts:BTSColor UI.spark_menu_background}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"/>
|
||||
@@ -476,6 +483,7 @@
|
||||
</converters:MultiValueConverterPipe>
|
||||
</MultiBinding.Converter>
|
||||
<Binding Path="show_day_position"/>
|
||||
<Binding Path="show_raw_day_position"/>
|
||||
<Binding Path="show_account_position"/>
|
||||
</MultiBinding>
|
||||
</Button.Visibility>
|
||||
@@ -486,6 +494,7 @@
|
||||
<MultiBinding Converter="{x:Static spark:LadderView.PositionToolTipConverter}">
|
||||
<Binding Path="order_properties_vm.selected_account"/>
|
||||
<Binding Path="show_day_position"/>
|
||||
<Binding Path="show_raw_day_position"/>
|
||||
<Binding Path="show_account_position"/>
|
||||
</MultiBinding>
|
||||
</TextBlock.Text>
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
using bts;
|
||||
using bts.collections;
|
||||
using bts.utils;
|
||||
using mbts.ui;
|
||||
using mbts.ui.converters;
|
||||
using mbts.ui.extensions;
|
||||
using mbts.utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Input;
|
||||
|
||||
@@ -18,32 +24,60 @@ namespace mbts.spark {
|
||||
MaxZoomFactor = 1.5;
|
||||
|
||||
public static IMultiValueConverter PositionToolTipConverter =
|
||||
ValueConverter.create<AccountTuple?, bool, bool, string>((account, show_day_pos, show_total_pos) => {
|
||||
const string day_pos_text = "day", total_pos_text = "total";
|
||||
ValueConverter.create<AccountTuple?, bool, bool, bool, string>((account, show_day_pos, show_raw_day_pos, show_total_pos) => {
|
||||
const string day_pos_text = "day", raw_day_pos_text = "raw day", total_pos_text = "total";
|
||||
if (!account.HasValue)
|
||||
return string.Empty;
|
||||
var sb = new StringBuilderEx(account.Value.name);
|
||||
string primary_pos;
|
||||
if (show_day_pos) {
|
||||
primary_pos = day_pos_text;
|
||||
if (show_total_pos) {
|
||||
sb.Add(" '", primary_pos, " ");
|
||||
sb.Add("(", total_pos_text, ")' ");
|
||||
} else {
|
||||
sb.Add(" ", primary_pos, " ");
|
||||
}
|
||||
} else if (show_total_pos) {
|
||||
primary_pos = total_pos_text;
|
||||
sb.Add(" ", primary_pos, " ");
|
||||
/// Note: 'day,' and 'raw day,' are interchangeable wrt the string format, 'total' however is treated differently.
|
||||
/// Different Formats:
|
||||
// No parts are visible:
|
||||
// null
|
||||
//
|
||||
// 1 part 'foo' is visible:
|
||||
// "<account> foo position
|
||||
// click to copy to size"
|
||||
//
|
||||
// 2 parts 'day' and 'raw day' are visible:
|
||||
// "<account> 'day / raw day' position
|
||||
// click to copy day to size"
|
||||
//
|
||||
// 2 parts 'day' and 'total' are visible:
|
||||
// "<account> 'day (total)' position
|
||||
// click to copy day to size"
|
||||
//
|
||||
|
||||
string primary_pos = null;
|
||||
// part count is incremented in the 'add_part' method
|
||||
int part_count = 0;
|
||||
var sb = new StringBuilderEx();
|
||||
|
||||
if (show_day_pos) add_part(day_pos_text, " / ");
|
||||
if (show_raw_day_pos) add_part(raw_day_pos_text, " / ");
|
||||
if (show_total_pos) add_part(total_pos_text, " (", ")");
|
||||
//
|
||||
if (part_count > 1) {
|
||||
// This is a complex expression (showing more than 1 value) - wrap it in single quotes.
|
||||
// Explicitly state which value will be copied to the size input.
|
||||
sb.Insert(0, "'");
|
||||
sb.Add("'");
|
||||
sb.Add(" position\n(click to copy ", primary_pos, " to size)");
|
||||
} else {
|
||||
// unexpected code path (the button for which this tooltip is destined should be invisible in this case), but no need to throw an exception.
|
||||
return string.Empty;
|
||||
// Only showing 1 value, no need for single quotes,
|
||||
// nor an explicit statement that indicates which value will be copied to the size input.
|
||||
sb.Add(" position\n(click to copy to size)");
|
||||
}
|
||||
sb.Add("position\n(click to copy ");
|
||||
if (show_day_pos && show_total_pos)
|
||||
sb.Add(primary_pos, " position ");
|
||||
sb.Add("to size)");
|
||||
return sb.ToString();
|
||||
|
||||
void add_part(string part_name, string separator = null, string separator_suffix = null) {
|
||||
if (part_count++ > 0) {
|
||||
sb.Add(separator);
|
||||
sb.Add(part_name);
|
||||
sb.Add(separator_suffix);
|
||||
} else {
|
||||
primary_pos = part_name;
|
||||
sb.Add($"{account.Value.name} {part_name}");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
internal LadderView(LadderVM vm) {
|
||||
@@ -52,6 +86,8 @@ namespace mbts.spark {
|
||||
_ladder.visible_columns_changed += () => _column_headers_presenter.Columns.SetItems(
|
||||
_ladder.visible_column_types.Select(t => ColumnFactory.create(_ladder, t)));
|
||||
this.vm = vm;
|
||||
this.ConnectDataContext<LadderVM>(lvm => lvm.bus.subscribe(SparkTags.SecuritiesTag).OnDispatcher().Subscribe(sec_map => Resources[ResourceKeys.Securities] = sec_map));
|
||||
vm.SubscribeDisposed(_connect_left_panel_scroll());
|
||||
DataContext = vm;
|
||||
DataContextChanged += datacontext_changed;
|
||||
_ui_scaler.MouseDoubleClick += _ui_scaler_MouseDoubleClick;
|
||||
@@ -59,7 +95,39 @@ namespace mbts.spark {
|
||||
this.PreviewMouseDown += LadderView_PreviewMouseDown;
|
||||
}
|
||||
|
||||
|
||||
IDisposable _connect_left_panel_scroll() {
|
||||
// extent height
|
||||
bool busy = false;
|
||||
var extent_height_hook = _left_panel_scroll.ObserveProperty(ScrollViewer.ExtentHeightProperty, (s, e) => {
|
||||
if (!busy) {
|
||||
double scroll_pos = vm.left_panel_scroll_position;
|
||||
busy = true;
|
||||
Dispatcher.InvokeAsync(() => {
|
||||
vm.left_panel_extent_height = _left_panel_scroll.ExtentHeight;
|
||||
if (_left_panel_scroll.VerticalOffset != scroll_pos)
|
||||
_left_panel_scroll.TryScrollToVerticalOffset(scroll_pos);
|
||||
busy = false;
|
||||
}, System.Windows.Threading.DispatcherPriority.ApplicationIdle);
|
||||
}
|
||||
});
|
||||
// view port height
|
||||
_left_panel_scroll.Loaded += on_loaded;
|
||||
var dispose = Disposable.CreateDisposeOnce(dispose_impl);
|
||||
return Disposable.Create(dispose, vm.SubscribeDisposed(dispose));
|
||||
// local methods
|
||||
void on_loaded(object sender, RoutedEventArgs e) {
|
||||
if (_left_panel_scroll.descendants_of_type<ScrollBar>().TryGetFirst(sb => sb.Orientation == Orientation.Vertical, out var vscroll)) {
|
||||
vscroll.SetBinding(ScrollBar.ViewportSizeProperty, new Binding(nameof(LadderVM.left_panel_view_port_height)) {
|
||||
Converter = ValueConverter.create<double, Size>(d => new Size(0, d), sz => sz.Height),
|
||||
Mode = BindingMode.OneWayToSource
|
||||
});
|
||||
}
|
||||
}
|
||||
void dispose_impl() {
|
||||
Disposable.dispose(ref extent_height_hook);
|
||||
_left_panel_scroll.Loaded -= on_loaded;
|
||||
}
|
||||
}
|
||||
|
||||
// (Left|Right) CTRL + Wheel to zoom
|
||||
// This is neat b/c the user doesn't even need to have the slider visible to zoom
|
||||
|
||||
@@ -62,15 +62,15 @@
|
||||
Header="{Binding security}"
|
||||
IsEditMode="False"
|
||||
IsLazy="True"
|
||||
SecurityMap="{DynamicResource ResourceKey={x:Static usp:ManualFillRowEditor.SecuritiesKey}}"
|
||||
SecurityMap="{DynamicResource ResourceKey={x:Static u:ResourceKeys.Securities}}"
|
||||
SelectedSecurity="{Binding security, UpdateSourceTrigger=Explicit}"
|
||||
ShowDialogSkirt="True"
|
||||
ToolTip="{Binding SelectedCriteria, RelativeSource={RelativeSource Self}, Converter={x:Static c:ContractPickerPopup.SecurityCriteriaTextConverter}, Mode=OneWay}"
|
||||
OKClick="{x:Static c:ContractPickerPopup.FlushSelectedSecurityHandler}"
|
||||
/>
|
||||
<ComboBox Grid.Row="2" Grid.Column="2" ItemsSource="{DynamicResource ResourceKey={x:Static usp:ManualFillRowEditor.AccountsKey}}" SelectedItem="{Binding account}"/>
|
||||
<ComboBox Grid.Row="2" Grid.Column="4" ItemsSource="{DynamicResource ResourceKey={x:Static usp:ManualFillRowEditor.UsersKey}}" SelectedItem="{Binding user}"/>
|
||||
<ComboBox Grid.Row="2" Grid.Column="6" ItemsSource="{DynamicResource ResourceKey={x:Static usp:ManualFillRowEditor.SidesKey}}" SelectedItem="{Binding side}" Width="48"/>
|
||||
<ComboBox Grid.Row="2" Grid.Column="2" ItemsSource="{DynamicResource ResourceKey={x:Static u:ResourceKeys.Accounts}}" SelectedItem="{Binding account}"/>
|
||||
<ComboBox Grid.Row="2" Grid.Column="4" ItemsSource="{DynamicResource ResourceKey={x:Static u:ResourceKeys.Users}}" SelectedItem="{Binding user}"/>
|
||||
<ComboBox Grid.Row="2" Grid.Column="6" ItemsSource="{DynamicResource ResourceKey={x:Static u:ResourceKeys.Sides}}" SelectedItem="{Binding side}" Width="48"/>
|
||||
<c:TickUpDownUInt Grid.Row="2" Grid.Column="8" MinWidth="40" Value="{Binding size}"/>
|
||||
<usp:PriceEntryControl Grid.Row="2" Grid.Column="10" MinWidth="55" Value="{Binding price}" ContractSpec="{Binding spec}"/>
|
||||
</Grid>
|
||||
|
||||
@@ -6,12 +6,6 @@ namespace mbts.ui.spark {
|
||||
/// Interaction logic for ManualFillRowEditor.xaml
|
||||
/// </summary>
|
||||
partial class ManualFillRowEditor : UserControl {
|
||||
public const string
|
||||
SecuritiesKey = nameof(SecuritiesKey),
|
||||
AccountsKey = nameof(AccountsKey),
|
||||
UsersKey = nameof(UsersKey),
|
||||
SidesKey = nameof(SidesKey);
|
||||
|
||||
public static readonly RoutedCommand
|
||||
CommitCommand = new RoutedCommand(),
|
||||
CancelCommand = new RoutedCommand();
|
||||
|
||||
@@ -79,8 +79,8 @@ namespace bts.shell.manual_fills {
|
||||
|
||||
public ManualFillsModel(OrdersModel model)
|
||||
: this(model, model.on_manual_fill_tuples,
|
||||
model.factory.subscribe_accounts().Select(d => MappedDictionary.create(d, kv => new AccountTuple(kv.Key, kv.Value))).Table(u => u.id),
|
||||
model.factory.subscribe_users().Select(d => MappedDictionary.create(d, kv => new UserTuple(kv.Key, kv.Value))).Table(a => a.id)) { }
|
||||
model.factory.subscribe_accounts().Select(d => MappedDictionary.create(d, (k, v) => new AccountTuple(k, v))).Table(u => u.id),
|
||||
model.factory.subscribe_users().Select(d => MappedDictionary.create(d, (k, v) => new UserTuple(k, v))).Table(a => a.id)) { }
|
||||
|
||||
public ManualFillsModel(OrdersModel model, IObservable<TableUpdate<ManualFillTuple, int>> manual_fills, IObservable<TableUpdate<AccountTuple, uint>> accounts, IObservable<TableUpdate<UserTuple, uint>> users) {
|
||||
_model = model;
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace bts.shell.manual_fills {
|
||||
// The security desc lookup could be better optimized, but the speed at which fills are imported is probably not a paramount concern.
|
||||
public static IEnumerable<ParsedManualFill> parse_rows(IEnumerable<string> rows, IReadOnlyDictionary<uint, SecurityImmutable> security_map, IReadOnlyDictionary<uint, string> account_map, IReadOnlyDictionary<uint, string> user_map) =>
|
||||
parse_rows(rows,
|
||||
reverse_lookup(MappedDictionary.create(security_map, kv => kv.Value.ToString())),
|
||||
reverse_lookup(MappedDictionary.create(security_map, s => s.ToString())),
|
||||
reverse_lookup(account_map),
|
||||
reverse_lookup(user_map));
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace bts.shell.manual_fills {
|
||||
mfd => new ManualFillRow(mfd),
|
||||
mfr => mfr.data),
|
||||
_bus.subscribe(SparkTags.SecuritiesTag).OnDispatcher().Subscribe(m => {
|
||||
security_map = m;
|
||||
security_map = new FilteredDictionary<uint, SecurityMD>(m, smd => smd.security.ContractCase == Security.ContractOneofCase.Future);
|
||||
RaisePropertyChanged(nameof(security_map));
|
||||
}),
|
||||
ObservableAutoWrapper.connect_item_hooks(_persisted_rows, r => Disposable.Create(dirty_mon.join(r), selection_mon.join(r))),
|
||||
@@ -157,7 +157,7 @@ namespace bts.shell.manual_fills {
|
||||
var lines = File.ReadAllLines(file_name);
|
||||
var parsed_fills = ManualFillsParser.parse_rows(
|
||||
lines,
|
||||
MappedDictionary.create(security_map, kv => kv.Value.security),
|
||||
MappedDictionary.create(security_map, smd => smd.security),
|
||||
accounts.ToDictionary(a => a.Value.id, a => a.Value.name),
|
||||
users.ToDictionary(u => u.Value.id, u => u.Value.name)
|
||||
).ToList();
|
||||
|
||||
@@ -50,11 +50,11 @@ namespace mbts.ui.spark {
|
||||
row_editor.CommandBindings.Add(new CommandBinding(ManualFillRowEditor.CommitCommand, commit_executed));
|
||||
row_editor.CommandBindings.Add(new CommandBinding(ManualFillRowEditor.CancelCommand, cancel_executed));
|
||||
// dynamic resources
|
||||
row_editor.Resources[ManualFillRowEditor.AccountsKey] = vm.accounts;
|
||||
row_editor.Resources[ManualFillRowEditor.UsersKey] = vm.users;
|
||||
row_editor.Resources[ManualFillRowEditor.SidesKey] = vm.sides;
|
||||
row_editor.Resources[ResourceKeys.Accounts] = vm.accounts;
|
||||
row_editor.Resources[ResourceKeys.Users] = vm.users;
|
||||
row_editor.Resources[ResourceKeys.Sides] = vm.sides;
|
||||
FocusManager.SetIsFocusScope(row_editor, true);
|
||||
var sec_hook = vm.as_demuxer().subscribe(nameof(ManualFillsVM.security_map)).OnDispatcher().Subscribe(v => row_editor.Resources[ManualFillRowEditor.SecuritiesKey] = v);
|
||||
var sec_hook = vm.as_demuxer().subscribe(nameof(ManualFillsVM.security_map)).OnDispatcher().Subscribe(v => row_editor.Resources[ResourceKeys.Securities] = v);
|
||||
// popup adorner
|
||||
var popup_adorner = new PopupAdorner(
|
||||
data_grid, data_grid,
|
||||
|
||||
@@ -15,10 +15,11 @@ namespace mbts.spark {
|
||||
CVRowStyleKey = "CVRowStyle",
|
||||
CVRowTemplateKey = "CVRowTemplateKey";
|
||||
|
||||
public MiniOrderBookView(OrderBookVM vm) {
|
||||
public MiniOrderBookView() =>
|
||||
InitializeComponent();
|
||||
|
||||
public MiniOrderBookView(OrderBookVM vm) : this() =>
|
||||
DataContext = vm;
|
||||
}
|
||||
}
|
||||
|
||||
class MiniOrderBookRowView : DIYGrid.HighPerformanceRow<OrderBookRowVM, OrderBookGridView.ColumnKeys> {
|
||||
|
||||
@@ -121,7 +121,7 @@ namespace mbts.spark {
|
||||
r => r.user,
|
||||
DefaultColumnWidths.User,
|
||||
DiscreteValuesFilterVM.Create<OrderSecurityRootPair, string>(
|
||||
model.factory.subscribe_users().Select(d => d.Values),
|
||||
model.factory.subscribe_users().Select(d => d.Values.Ordered()),
|
||||
ort => ort.order.order.user(),
|
||||
nameof(OrderBookRowVM.user)),
|
||||
DataGridFilterKnownTemplates.DiscreteValues,
|
||||
@@ -133,7 +133,7 @@ namespace mbts.spark {
|
||||
r => r.account,
|
||||
DefaultColumnWidths.Account,
|
||||
DiscreteValuesFilterVM.Create<OrderSecurityRootPair, string, string[]>(
|
||||
model.factory.subscribe_accounts().Select(d => d.Values),
|
||||
model.factory.subscribe_accounts().Select(d => d.Values.Ordered()),
|
||||
ort => ort.order.order.account(),
|
||||
vals => vals.ToArray(),
|
||||
vals => Observable.Return(vals),
|
||||
@@ -327,6 +327,18 @@ namespace mbts.spark {
|
||||
|
||||
public event Action filter_changed;
|
||||
|
||||
public static IEnumerable<ColumnBase> editable_columns {
|
||||
get {
|
||||
yield return new AttachDetachColumn(typeof(MiniOrderBookView));
|
||||
yield return new CommitColumn();
|
||||
yield return new EditablePriceColumn();
|
||||
yield return new EditableQtyColumn();
|
||||
yield return new UpdateColumn(typeof(MiniOrderBookView));
|
||||
yield return new CancelColumn(nameof(OrderBookRowVM.cancel_command));
|
||||
yield return new CheckColumn(nameof(OrderBookRowVM.is_selected));
|
||||
}
|
||||
}
|
||||
|
||||
public SecurityColumn security_column { get; }
|
||||
public SimpleTextColumn<string[]> symbol_column { get; }
|
||||
public SimpleTextColumn<TimeFilterTuple> time_created_column { get; }
|
||||
@@ -731,10 +743,14 @@ namespace mbts.spark {
|
||||
Width = 30;
|
||||
_checked_binding = new Binding(checked_property);
|
||||
|
||||
var header_cb = new CheckBox();
|
||||
header_cb.ToolTip = "Select / Unselect All";
|
||||
var header_cb = new CheckBox {
|
||||
HorizontalAlignment = HorizontalAlignment.Center,
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
ToolTip = "Select / Unselect All"
|
||||
};
|
||||
header_cb.SetBinding(CheckBox.IsCheckedProperty, new Binding(nameof(OrderBookVM.all_rows_selected)));
|
||||
this.Header = header_cb;
|
||||
is_visible = true;
|
||||
}
|
||||
|
||||
public override FrameworkElement view_factory() {
|
||||
@@ -1164,6 +1180,7 @@ namespace mbts.spark {
|
||||
|
||||
public override FrameworkElement view_factory() {
|
||||
var price_up_down = new PriceEntryCommitControl();
|
||||
price_up_down.SetBinding(PriceEntryCommitControl.RealPriceProperty, new Binding(nameof(OrderBookRowVM.price)));
|
||||
price_up_down.SetBinding(PriceEntryCommitControl.SourceValueProperty, nameof(OrderBookRowVM.prospective_price));
|
||||
price_up_down.SetBinding(PriceEntryCommitControl.SourceContractSpecProperty, nameof(OrderBookRowVM.contract_spec));
|
||||
price_up_down.SetBinding(PriceEntryCommitControl.OnCommitProperty, nameof(OrderBookRowVM.modify_order_quantity_andor_price));
|
||||
|
||||
@@ -108,7 +108,7 @@ namespace mbts.spark {
|
||||
public CustomOrderDefinition.CustomOneofCase root_algo_order_type => order_tuple.root.algo.value.CustomCase;
|
||||
public OrderMetadata root_algo_order_metadata => _owner.get_metadata(root_algo_order_type);
|
||||
public Brush root_algo_badge_fill => _root_algo_badge_fill ?? (_root_algo_badge_fill = new SolidColorBrush(_root_algo_badge_color));
|
||||
public string root_algo_display_name => order_tuple.root.algo.name;
|
||||
public string root_algo_display_name => order_tuple.root.display_name();
|
||||
|
||||
// Tree
|
||||
public bool is_parent { get => _is_parent; set => Set(ref _is_parent, value); }
|
||||
|
||||
Loaded 100 of 672 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user