Compare commits
12
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9d1b03d1e2 | ||
|
|
9a677cf980 | ||
|
|
25445d58d0 | ||
|
|
0b313a8aa8 | ||
|
|
54f954fd4b | ||
|
|
980f38ba03 | ||
|
|
9eada2724b | ||
|
|
b5f53ee918 | ||
|
|
efc175f654 | ||
|
|
6074afd999 | ||
|
|
219dff4055 | ||
|
|
9a3b07b622 |
No files matched your search
@@ -1,6 +1,7 @@
|
|||||||
using bts.api;
|
using bts.api;
|
||||||
using bts.co2;
|
using bts.co2;
|
||||||
using bts.utils;
|
using bts.utils;
|
||||||
|
using bts.utils.csv;
|
||||||
using mbts;
|
using mbts;
|
||||||
using mbts.spark;
|
using mbts.spark;
|
||||||
using mbts.ui.controls;
|
using mbts.ui.controls;
|
||||||
@@ -44,6 +45,18 @@ namespace bts.shell.time_and_sales {
|
|||||||
public void raise_invalidated() =>
|
public void raise_invalidated() =>
|
||||||
invalidated?.Invoke();
|
invalidated?.Invoke();
|
||||||
|
|
||||||
|
public static System.Collections.Specialized.OrderedDictionary csv_ordered_properties =>
|
||||||
|
CsvHelper.create_ordering_maintainer(
|
||||||
|
typeof(TimeAndSalesRowVM),
|
||||||
|
new string[] {
|
||||||
|
nameof(security),
|
||||||
|
nameof(time),
|
||||||
|
nameof(price),
|
||||||
|
nameof(size),
|
||||||
|
nameof(aggressor_side),
|
||||||
|
nameof(security_key),
|
||||||
|
});
|
||||||
|
|
||||||
public bool Equals(TimeAndSalesRowVM other) =>
|
public bool Equals(TimeAndSalesRowVM other) =>
|
||||||
other != null &&
|
other != null &&
|
||||||
row_key == other.row_key;
|
row_key == other.row_key;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using bts.shell.fills;
|
using bts.shell.fills;
|
||||||
using bts.spark;
|
using bts.spark;
|
||||||
using bts.view;
|
using bts.view;
|
||||||
|
using bts.utils.csv;
|
||||||
using mbts;
|
using mbts;
|
||||||
using mbts.co2;
|
using mbts.co2;
|
||||||
using mbts.persist;
|
using mbts.persist;
|
||||||
@@ -114,6 +115,8 @@ namespace bts.shell.time_and_sales {
|
|||||||
show_in_context_menu = _can_pause_updates
|
show_in_context_menu = _can_pause_updates
|
||||||
};
|
};
|
||||||
_commands = new SparkCommand[] {
|
_commands = new SparkCommand[] {
|
||||||
|
// csv export
|
||||||
|
new SparkCommandCommand("Export to csv", Icons.Export, FileDialogCommand.export_csv(() => _vm.rows.ToCsv(TimeAndSalesRowVM.csv_ordered_properties), "TaS")),
|
||||||
// ladder
|
// ladder
|
||||||
SparkCommands.ShowLadderAutoLookup(SparkCommands.KeyGestures.ShowLadder)
|
SparkCommands.ShowLadderAutoLookup(SparkCommands.KeyGestures.ShowLadder)
|
||||||
.complete(current_sec_key_src, sec_keys => sec_keys.Count > 0),
|
.complete(current_sec_key_src, sec_keys => sec_keys.Count > 0),
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using bts.collections;
|
|||||||
using bts.shell.fills;
|
using bts.shell.fills;
|
||||||
using bts.spark;
|
using bts.spark;
|
||||||
using bts.utils;
|
using bts.utils;
|
||||||
|
using bts.utils.csv;
|
||||||
using mbts.collections;
|
using mbts.collections;
|
||||||
using mbts.persist;
|
using mbts.persist;
|
||||||
using mbts.spark.filters;
|
using mbts.spark.filters;
|
||||||
@@ -330,6 +331,27 @@ namespace mbts.spark {
|
|||||||
public override bool Equals(object obj) => Equals(obj as Row);
|
public override bool Equals(object obj) => Equals(obj as Row);
|
||||||
public override int GetHashCode() => _fill.FillKey.GetHashCode() ^ _order.Key.GetHashCode();
|
public override int GetHashCode() => _fill.FillKey.GetHashCode() ^ _order.Key.GetHashCode();
|
||||||
|
|
||||||
|
public static System.Collections.Specialized.OrderedDictionary csv_ordered_properties =>
|
||||||
|
CsvHelper.create_ordering_maintainer(typeof(Row),
|
||||||
|
new string[] {
|
||||||
|
nameof(security),
|
||||||
|
nameof(order_type),
|
||||||
|
nameof(root_algo_display_name),
|
||||||
|
nameof(side),
|
||||||
|
nameof(fill_time),
|
||||||
|
nameof(user),
|
||||||
|
nameof(account),
|
||||||
|
nameof(exchange),
|
||||||
|
nameof(time_in_force),
|
||||||
|
nameof(size),
|
||||||
|
nameof(price),
|
||||||
|
nameof(fill_kind),
|
||||||
|
nameof(fill_status),
|
||||||
|
nameof(fill_key),
|
||||||
|
nameof(order_key),
|
||||||
|
nameof(security_key)
|
||||||
|
});
|
||||||
|
|
||||||
public event Action invalidated;
|
public event Action invalidated;
|
||||||
void IRowVM.raise_invalidated() => invalidated?.Invoke();
|
void IRowVM.raise_invalidated() => invalidated?.Invoke();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using bts.shell;
|
|||||||
using bts.shell.fills;
|
using bts.shell.fills;
|
||||||
using bts.spark;
|
using bts.spark;
|
||||||
using bts.view;
|
using bts.view;
|
||||||
|
using bts.utils.csv;
|
||||||
using mbts.persist;
|
using mbts.persist;
|
||||||
using mbts.ui;
|
using mbts.ui;
|
||||||
using mbts.ui.settings;
|
using mbts.ui.settings;
|
||||||
@@ -61,6 +62,7 @@ namespace mbts.spark {
|
|||||||
_view = new FillsView { DataContext = _vm };
|
_view = new FillsView { DataContext = _vm };
|
||||||
|
|
||||||
_commands = new List<SparkCommand> {
|
_commands = new List<SparkCommand> {
|
||||||
|
new SparkCommandCommand("Export to csv", Icons.Export, FileDialogCommand.export_csv(() => _vm.rows.ToCsv(FillsVM.Row.csv_ordered_properties), "Fills")),
|
||||||
// wrap the grid settings view factory in a dialogCommand here since the vm is destroyed/recreated when the security criteria changes
|
// wrap the grid settings view factory in a dialogCommand here since the vm is destroyed/recreated when the security criteria changes
|
||||||
SparkCommands.window_settings_command(new DialogCommand(() => {
|
SparkCommands.window_settings_command(new DialogCommand(() => {
|
||||||
var vm = new ShellSettingsDialogVM<GridSettings, SimpleGridSettingsVM>(
|
var vm = new ShellSettingsDialogVM<GridSettings, SimpleGridSettingsVM>(
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using bts.api.orderman;
|
|||||||
using bts.collections;
|
using bts.collections;
|
||||||
using bts.spark;
|
using bts.spark;
|
||||||
using bts.utils;
|
using bts.utils;
|
||||||
|
using bts.utils.csv;
|
||||||
using mbts.ui;
|
using mbts.ui;
|
||||||
using mbts.ui.controls;
|
using mbts.ui.controls;
|
||||||
using System;
|
using System;
|
||||||
@@ -11,6 +12,7 @@ using System.Collections.Generic;
|
|||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Reactive.Linq;
|
using System.Reactive.Linq;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Linq;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using Columns = mbts.spark.OrderBookGridView.ColumnKeys;
|
using Columns = mbts.spark.OrderBookGridView.ColumnKeys;
|
||||||
@@ -60,6 +62,35 @@ namespace mbts.spark {
|
|||||||
public event Action<(OrderSecurityRootPair oldval, OrderSecurityRootPair newval)> updated;
|
public event Action<(OrderSecurityRootPair oldval, OrderSecurityRootPair newval)> updated;
|
||||||
public event PropertyChangedEventHandler PropertyChanged;
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
|
public static System.Collections.Specialized.OrderedDictionary csv_ordered_properties =>
|
||||||
|
CsvHelper.create_ordering_maintainer(
|
||||||
|
typeof(OrderBookRowVM),
|
||||||
|
new string[] {
|
||||||
|
nameof(security_text),
|
||||||
|
nameof(symbol),
|
||||||
|
nameof(time_created),
|
||||||
|
nameof(last_change),
|
||||||
|
nameof(user),
|
||||||
|
nameof(account),
|
||||||
|
nameof(exchange),
|
||||||
|
nameof(time_in_force),
|
||||||
|
nameof(order_type),
|
||||||
|
nameof(root_algo_display_name),
|
||||||
|
nameof(order_sub_type),
|
||||||
|
nameof(side),
|
||||||
|
nameof(quantity),
|
||||||
|
nameof(filled_quantity),
|
||||||
|
nameof(price),
|
||||||
|
nameof(avg_price),
|
||||||
|
nameof(last_price),
|
||||||
|
nameof(piq),
|
||||||
|
nameof(status),
|
||||||
|
// last message (could contains commas, so skipping)
|
||||||
|
nameof(security_key),
|
||||||
|
nameof(order_key),
|
||||||
|
nameof(parent_order_key),
|
||||||
|
});
|
||||||
|
|
||||||
// Core
|
// Core
|
||||||
public OrderSecurityRootPair order_tuple { get; private set; }
|
public OrderSecurityRootPair order_tuple { get; private set; }
|
||||||
public OrderRecordImmutable order => order_tuple.order.order;
|
public OrderRecordImmutable order => order_tuple.order.order;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using bts.shell;
|
|||||||
using bts.shell.fills;
|
using bts.shell.fills;
|
||||||
using bts.shell.orderbook;
|
using bts.shell.orderbook;
|
||||||
using bts.spark;
|
using bts.spark;
|
||||||
|
using bts.utils.csv;
|
||||||
using bts.view;
|
using bts.view;
|
||||||
using mbts.persist;
|
using mbts.persist;
|
||||||
using mbts.ui;
|
using mbts.ui;
|
||||||
@@ -194,6 +195,7 @@ namespace mbts.spark {
|
|||||||
show_grid_settings_command.group = CommandGroups.Auxiliary;
|
show_grid_settings_command.group = CommandGroups.Auxiliary;
|
||||||
|
|
||||||
_commands = new SparkCommand[] {
|
_commands = new SparkCommand[] {
|
||||||
|
new SparkCommandCommand("Export to csv", Icons.Export, FileDialogCommand.export_csv(() => _vm.rows.ToCsv(OrderBookRowVM.csv_ordered_properties), "OrderBook")),
|
||||||
toggle_show_right_panel_command,
|
toggle_show_right_panel_command,
|
||||||
attach_selected_orders_command,
|
attach_selected_orders_command,
|
||||||
detach_selected_orders_command,
|
detach_selected_orders_command,
|
||||||
|
|||||||
@@ -64,6 +64,25 @@ namespace mbts.ui {
|
|||||||
}
|
}
|
||||||
}, can_execute == null ? null : new Func<object, bool>(_ => can_execute()));
|
}, can_execute == null ? null : new Func<object, bool>(_ => can_execute()));
|
||||||
|
|
||||||
|
public static IDialogCommand export_csv(
|
||||||
|
Func<string> get_file_content,
|
||||||
|
string source_window_name) =>
|
||||||
|
new AnonymousFileDialogCommand<object>(_ =>
|
||||||
|
_create_save_file_dialog(
|
||||||
|
Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
|
||||||
|
$"BTS_Spark_{source_window_name}_{DateTime.Now.ToString("yyyyMMdd_HHmm")}.csv",
|
||||||
|
new[] { ("CSV (comma delimited)", new string[] { "csv" }) }
|
||||||
|
),
|
||||||
|
(_, file) => {
|
||||||
|
try {
|
||||||
|
File.WriteAllText(file, get_file_content.Invoke());
|
||||||
|
} catch (Exception ex) {
|
||||||
|
BTSMessageBox.Show($"Error exporting data to csv: {ex}.", "CSV Export Error", BTSMessageBoxButtons.OK, System.Windows.MessageBoxImage.Error, true, false, true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// we are always able to perform an export, even when no rows (it will just be a header)
|
||||||
|
(_) => true);
|
||||||
|
|
||||||
static TDialog _create_file_dialog<TDialog>(string initial_dir = null, IReadOnlyList<(string name, string[] extensions)> filter_items = null) where TDialog : FileDialog, new() {
|
static TDialog _create_file_dialog<TDialog>(string initial_dir = null, IReadOnlyList<(string name, string[] extensions)> filter_items = null) where TDialog : FileDialog, new() {
|
||||||
var rv = new TDialog();
|
var rv = new TDialog();
|
||||||
if (!string.IsNullOrEmpty(initial_dir))
|
if (!string.IsNullOrEmpty(initial_dir))
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace bts.utils.csv {
|
||||||
|
public static class CsvHelper {
|
||||||
|
|
||||||
|
public static string ToCsv<T>(this IEnumerable<T> items, OrderedDictionary properties = null) where T : class {
|
||||||
|
var output = "";
|
||||||
|
var delimiter = ",";
|
||||||
|
if (properties == null) {
|
||||||
|
properties = new OrderedDictionary();
|
||||||
|
foreach (var pi in typeof(T).GetProperties()) {
|
||||||
|
properties.Add(pi.Name, pi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var sw = new StringWriter()) {
|
||||||
|
var dict_values = properties.Values.OfType<PropertyInfo>();
|
||||||
|
var header = dict_values.Select(n => n.Name).Aggregate((first, second) => first + delimiter + second);
|
||||||
|
sw.WriteLine(header);
|
||||||
|
foreach (var i in items) {
|
||||||
|
var row = dict_values.Select(x => x.GetValue(i, null))
|
||||||
|
.Select(x => x == null ? "null" : x.ToString())
|
||||||
|
.Aggregate((first, second) => first + delimiter + second);
|
||||||
|
sw.WriteLine(row);
|
||||||
|
}
|
||||||
|
output = sw.ToString();
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static OrderedDictionary create_ordering_maintainer(Type t, string[] property_names_in_order) {
|
||||||
|
OrderedDictionary od = new OrderedDictionary();
|
||||||
|
var props = t.GetProperties();
|
||||||
|
foreach (var n in property_names_in_order) {
|
||||||
|
var query = props.Where(pi => pi.Name == n);
|
||||||
|
if (query.Any()) {
|
||||||
|
var property_info = query.First();
|
||||||
|
if (!od.Contains(property_info)) {
|
||||||
|
od.Add(n, property_info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return od;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user