private async void DeleteStrategy(Strategy strategy) { if (strategy == null) { return; } int tradesCount = Context.Trades.Count(x => x.StrategyID == strategy.ID); if (tradesCount > 0) { await DialogService.ShowMessageAsync("Cannot delete", string.Format("Can't delete this strategy, it still has {0} trades in it.", tradesCount)); return; } MessageDialogResult result = await DialogService.ShowMessageAsync( "Delete strategy", String.Format("Are you sure you want to delete {0}?", strategy.Name), MessageDialogStyle.AffirmativeAndNegative); if (result == MessageDialogResult.Affirmative) { Context.Strategies.Remove(strategy); Context.SaveChanges(); } }
private async void DeleteTrades(IList trades) { if (trades == null || trades.Count == 0) { return; } MessageDialogResult res = await DialogService.ShowMessageAsync( "Delete Trade", string.Format("Are you sure you want to delete {0} trades?", trades.Count), MessageDialogStyle.AffirmativeAndNegative); if (res != MessageDialogResult.Affirmative) { return; } var selectedTrades = trades.Cast <Trade>().ToList(); //reset the trades foreach (Trade trade in selectedTrades) { Context.Trades.Remove(trade); } Context.SaveChanges(); }
private async Task RunUserScripts(IList orders) { if (orders == null || orders.Count == 0) { return; } List <UserScript> scripts; using (var dbContext = _contextFactory.Get()) { scripts = dbContext.UserScripts.Where(x => x.Type == UserScriptType.OrderScript).ToList(); } foreach (var script in scripts) { try { await _scriptRunner.RunOrderScript(script, orders.Cast <Order>().ToList()).ConfigureAwait(false); } catch (Exception ex) { _logger.Log(LogLevel.Error, "User script {0} generated an exception: ", script.Name); _logger.Log(LogLevel.Error, ex); await DialogService.ShowMessageAsync(Parent, "Error", $"User script {script.Name} generated an exception: {ex.Message}. See log for more details."); } } }
private async Task DeleteCashTransactions(IList cts) { if (cts == null || cts.Count == 0) { return; } var res = await DialogService.ShowMessageAsync(_mainVm, "Delete Order(s)", string.Format("Are you sure you want to delete {0} cash transaction(s)?", cts.Count), MessageDialogStyle.AffirmativeAndNegative); if (res != MessageDialogResult.Affirmative) { return; } using (var context = contextFactory.Get()) { foreach (CashTransaction ct in cts) { if (ct.Trade != null) { //only delete those that are not assigned to a trade continue; //await TradesRepository.RemoveCashTransaction(ct.Trade, ct); } context.CashTransactions.Remove(ct); } context.SaveChanges(); } }
private async Task DeleteFxTransactions(IList fxts) { if (fxts == null || fxts.Count == 0) { return; } var res = await DialogService.ShowMessageAsync(_mainVm, "Delete Order(s)", string.Format("Are you sure you want to delete {0} FX transaction(s)?", fxts.Count), MessageDialogStyle.AffirmativeAndNegative); if (res != MessageDialogResult.Affirmative) { return; } using (var dbContext = _contextFactory.Get()) { foreach (FXTransaction fxt in fxts) { if (fxt.Trade != null) { await TradesRepository.RemoveFXTransaction(fxt.Trade, fxt); } dbContext.FXTransactions.Remove(fxt); } dbContext.SaveChanges(); } }
private async void DeleteOrders(IList orders) { if (orders == null || orders.Count == 0) { return; } var selectedOrders = orders.Cast <Order>().ToList(); var res = await DialogService.ShowMessageAsync( "Delete Order(s)", string.Format("Are you sure you want to delete {0} order(s)?", selectedOrders.Count), MessageDialogStyle.AffirmativeAndNegative); if (res == MessageDialogResult.Affirmative) { foreach (Order o in selectedOrders) { if (o.Trade != null) { TradesRepository.RemoveOrder(o.Trade, o); } Context.Orders.Remove(o); } Context.SaveChanges(); } }
private async void GenerateReport(List <Trade> tradeIDs) { if (tradeIDs == null) { throw new NullReferenceException("tradeIDs"); } if (tradeIDs.Count == 0) { await DialogService.ShowMessageAsync(this, "Error", "No trades meet the given criteria"); return; } var gen = new ReportGenerator(); ProgressDialogController progressDialog = await DialogService.ShowProgressAsync(this, "Generating Report", "Generating Report"); var ds = await Task.Run(() => gen.TradeStats( tradeIDs, PerformanceReportPageViewModel.ReportSettings, Settings, Datasourcer, _contextFactory, backtestData: PerformanceReportPageViewModel.BacktestData, progressDialog: progressDialog)); progressDialog.CloseAsync().Forget(); //don't await it! var window = new PerformanceReportWindow(ds, PerformanceReportPageViewModel.ReportSettings); window.Show(); }
private async Task DeleteTag(Tag tag) { MessageDialogResult res = await DialogService.ShowMessageAsync(Parent, "Delete Tag", string.Format("Are you sure you want to delete {0}?", tag.Name), MessageDialogStyle.AffirmativeAndNegative); if (res != MessageDialogResult.Affirmative) { return; } //keep track of the trades with this tag, we need to update their tagstrings var trades = data.Trades.ToList().Where(x => x.Tags.Contains(tag)).ToList(); foreach (var trade in trades) { trade.Tags.Remove(tag); await Parent.TradesPageViewModel.TradesRepository.UpdateTrade(trade).ConfigureAwait(false); trade.TagStringUpdated(); } using (var dbContext = contextFactory.Get()) { dbContext.Tags.Remove(tag); dbContext.SaveChanges(); data.Tags.Remove(tag); } }
private async Task DeleteStrategy(Strategy strategy) { if (strategy == null) { return; } int tradesCount = data.Trades.Count(x => x.StrategyID == strategy.ID); if (tradesCount > 0) { await DialogService.ShowMessageAsync(Parent, "Cannot delete", string.Format("Can't delete this strategy, it still has {0} trades in it.", tradesCount)); return; } MessageDialogResult result = await DialogService.ShowMessageAsync(Parent, "Delete strategy", String.Format("Are you sure you want to delete {0}?", strategy.Name), MessageDialogStyle.AffirmativeAndNegative); if (result != MessageDialogResult.Affirmative) { return; } using (var dbContext = contextFactory.Get()) { dbContext.Strategies.Remove(strategy); dbContext.SaveChanges(); data.Strategies.Remove(strategy); } }
private async Task DeleteCashTransactions(IList cts) { if (cts == null || cts.Count == 0) { return; } var res = await DialogService.ShowMessageAsync(_mainVm, "Delete Order(s)", string.Format("Are you sure you want to delete {0} cash transaction(s)?", cts.Count), MessageDialogStyle.AffirmativeAndNegative); if (res == MessageDialogResult.Affirmative) { foreach (CashTransaction ct in cts) { if (ct.Trade != null) { await TradesRepository.RemoveCashTransaction(ct.Trade, ct).ConfigureAwait(true); } Context.CashTransactions.Remove(ct); } Context.SaveChanges(); } }
private async Task RunTradeScripts(ProgressDialogController progressDialog) { List <UserScript> scripts; using (var dbContext = _contextFactory.Get()) { scripts = dbContext.UserScripts.Where(x => x.Type == UserScriptType.TradeScript).ToList(); } for (int i = 0; i < scripts.Count; i++) { progressDialog.SetProgress((double)i / scripts.Count); progressDialog.SetMessage("Running script: " + scripts[i].Name); try { await ScriptRunner.RunTradeScript(scripts[i]).ConfigureAwait(false); } catch (Exception ex) { _logger.Error(ex, "User script {0} generated an exception: ", scripts[i].Name); await DialogService.ShowMessageAsync(this, "Error", $"User script {scripts[i].Name} generated an exception. See log for more details."); } } }
private async Task RunOrderScripts(List <Order> orders, ProgressDialogController progressDialog) { List <UserScript> scripts; using (var dbContext = _contextFactory.Get()) { scripts = dbContext.UserScripts.Where(x => x.Type == UserScriptType.OrderScript).ToList(); } for (int i = 0; i < scripts.Count; i++) { progressDialog.SetProgress((double)i / scripts.Count); progressDialog.SetMessage("Running script: " + scripts[i].Name); try { await ScriptRunner.RunOrderScript(scripts[i], orders);//todo: this will run subsequent scripts with orders set to a trade... orders = orders.Where(y => y.Trade == null).ToList(); } catch (Exception ex) { _logger.Error(ex, "User script {0} generated an exception: ", scripts[i].Name); await DialogService.ShowMessageAsync(this, "Error", $"User script {scripts[i].Name} generated an exception. See log for more details."); } } }
/// <summary> /// warn if there are missing business days between the last data in the db and first data in the import /// </summary> /// <param name="newData"></param> /// <param name="progressDialog"></param> /// <returns>false to abort import</returns> private async Task <bool> ImportDateCheck(Dictionary <string, DataContainer> newData, ProgressDialogController progressDialog) { DateTime?lastDateInDb; using (var dbContext = _contextFactory.Get()) { lastDateInDb = dbContext.FXRates.OrderByDescending(x => x.Date).FirstOrDefault()?.Date; } var fxRateDateEarliestDates = newData.Select(x => x.Value.FXRates.OrderBy(x => x.Date).FirstOrDefault()).Where(x => x != null).ToList(); DateTime?firstDateInImport = fxRateDateEarliestDates.Count > 0 ? fxRateDateEarliestDates.OrderBy(x => x.Date).First().Date : (DateTime?)null; if (lastDateInDb.HasValue && firstDateInImport.HasValue && lastDateInDb.Value < firstDateInImport.Value && Utils.CountBusinessDaysBetween(lastDateInDb.Value, firstDateInImport.Value) > 0) { var firstMissingBusinessDay = Utils.AddBusinessDays(lastDateInDb.Value, 1); var result = await DialogService.ShowMessageAsync(this, "Potential Import Mistake Warning", "There are missing business days between the last data in the db and the first data in the file you are importing. " + $"It is recommended you Cancel the import and load a flex statement starting from {firstMissingBusinessDay:d}.\n\nDo you want to proceed anyway?", MessageDialogStyle.AffirmativeAndNegative); if (result == MessageDialogResult.Negative) { await progressDialog.CloseAsync(); return(false); } } return(true); }
private async Task DeleteTrades(IList trades) { if (trades == null || trades.Count == 0) { return; } MessageDialogResult res = await DialogService.ShowMessageAsync(Parent, "Delete Trade", string.Format("Are you sure you want to delete {0} trades?", trades.Count), MessageDialogStyle.AffirmativeAndNegative); if (res != MessageDialogResult.Affirmative) { return; } var selectedTrades = trades.Cast <Trade>().ToList(); //delete the trades using (var dbContext = _contextFactory.Get()) { foreach (Trade trade in selectedTrades) { _data.Trades.Remove(trade); dbContext.Trades.Remove(trade); } await dbContext.SaveChangesAsync(); } }
private async void Run() { string error = ""; try { //If the user has selected a fixed reference time, we use tha //otherwise just pass null, which uses the QDMS instruments TimeSpan?referenceTime = (UseSessionsTime || !ReferenceTime.HasValue) ? null : (TimeSpan?)ReferenceTime.Value.TimeOfDay; StatsGenerator.GenerateExecutionStats(Benchmark, referenceTime); SetStats(); } catch (Exception ex) { error = ex.Message; } if (!string.IsNullOrEmpty(error)) { await DialogService.ShowMessageAsync(this, "Error", error); } }
private void UpdateChart() { if (SelectedInstrument == null) { return; } if (Datasourcer.ExternalDataSource == null || !Datasourcer.ExternalDataSource.Connected) { return; } PlotModel newModel = InstrumentChartModel ?? InstrumentChartCreator.InitializePlotModel(); newModel.Title = SelectedInstrument.Symbol; //if there's more than 3 series, here we delete any trade line series while (newModel.Series.Count > 3) { newModel.Series.RemoveAt(3); } //grab data List <OHLCBar> data; try { data = Datasourcer.GetAllExternalData(SelectedInstrument); } catch (Exception ex) { DialogService.ShowMessageAsync(_mainVm, "Error Getting Data", ex.Message); return; } //add OHLC bars to chart InstrumentChartCreator.AddCandlesticks(data, newModel); //Tuple: trade time, price, quantity List <Tuple <DateTime, decimal, int> > groupedOrders = GetGroupedOrders(); //add transaction markers InstrumentChartCreator.AddTransactionScatterPoints(groupedOrders, newModel, ShowOrderAnnotations, ShowQuantityAnnotations); //then we create the lines between trades InstrumentChartCreator.AddProfitLossLines(groupedOrders, newModel); InstrumentChartModel = newModel; //and finally refresh the chart InstrumentChartModel.InvalidatePlot(true); }
private async Task DeleteOrders(IList orders) { if (orders == null || orders.Count == 0) { return; } var selectedOrders = orders.Cast <Order>().ToList(); var res = await DialogService.ShowMessageAsync(Parent, "Delete Order(s)", string.Format("Are you sure you want to delete {0} order(s)?", selectedOrders.Count), MessageDialogStyle.AffirmativeAndNegative); if (res != MessageDialogResult.Affirmative) { return; } //if the order belongs to a trade, remove it foreach (Order o in selectedOrders) { if (o.Trade != null) { await TradesRepository.RemoveOrder(o.Trade, o); } } using (var dbContext = _contextFactory.Get()) { foreach (Order o in selectedOrders) { //remove executions first if (o.Executions != null) { List <Execution> toRemove = o.Executions.ToList(); foreach (Execution exec in toRemove) { dbContext.Executions.Remove(exec); } o.Executions.Clear(); } //finally delete the order dbContext.Orders.Remove(o); } await dbContext.SaveChangesAsync(); } }
/// <summary> /// Stuff that needs to be done after loading data from a statement. /// </summary> private async Task PostStatementLoadProcedures(Dictionary <string, DataContainer> newData, ProgressDialogController progressDialog) { progressDialog.SetProgress(0); progressDialog.SetTitle("Importing data"); progressDialog.SetMessage("Importing data"); //backup db before import System.IO.File.Copy("qpas.db", "qpas-backup.db", true); //prevent gaps in data bool continueImport = await ImportDateCheck(newData, progressDialog); if (!continueImport) { return; } //Perform the data import try { foreach (var kvp in newData) { await DataImporter.Import(Data, kvp.Value, kvp.Key, _contextFactory, _tradesRepository); } } catch (Exception ex) { await progressDialog.CloseAsync(); await DialogService.ShowMessageAsync(this, "Data Import Error", ex.Message); _logger.Error(ex, "Data import exception"); return; } //Run scripts progressDialog.SetProgress(0); progressDialog.SetTitle("Running scripts"); await RunOrderScripts(Data.Orders.Where(y => y.Trade == null).OrderBy(y => y.TradeDate).ToList(), progressDialog); await RunTradeScripts(progressDialog); await progressDialog.CloseAsync(); await RefreshCurrentPage(); }
private void CreateCommands() { UpdateChartCommand = new RelayCommand(UpdateChart); CopyChart = new RelayCommand <PlotView>(x => x.CopyToClipboard()); SaveChart = new RelayCommand <PlotView>(x => { try { x.SaveAsPNG(); } catch (Exception ex) { DialogService.ShowMessageAsync(_mainVm, "Error saving image", ex.Message); } }); }
private async void DeleteBench(Benchmark benchmark) { if (benchmark == null) { return; } var result = await DialogService.ShowMessageAsync(_mainVm, "Delete Benchmark", string.Format("Are you sure you want to delete {0}?", benchmark.Name), MessageDialogStyle.AffirmativeAndNegative); if (result == MessageDialogResult.Affirmative) { Context.Benchmarks.Remove(benchmark); Context.SaveChanges(); } }
private async void DeleteTag(Tag tag) { MessageDialogResult res = await DialogService.ShowMessageAsync(Parent, "Delete Tag", string.Format("Are you sure you want to delete {0}?", tag.Name), MessageDialogStyle.AffirmativeAndNegative); if (res != MessageDialogResult.Affirmative) { return; } //keep track of the trades with this tag, we need to update their tagstrings var trades = Context.Trades.ToList().Where(x => x.Tags.Contains(tag)).ToList(); Context.Tags.Remove(tag); Context.SaveChanges(); foreach (Trade t in trades) { t.TagStringUpdated(); } }
private async Task ResetTrades(IList trades) { if (trades == null || trades.Count == 0) { return; } MessageDialogResult res = await DialogService.ShowMessageAsync(Parent, "Reset Trade", string.Format("Are you sure you want to reset {0} trades?", trades.Count), MessageDialogStyle.AffirmativeAndNegative); if (res != MessageDialogResult.Affirmative) { return; } //reset the trades foreach (Trade trade in trades) { await TradesRepository.Reset(trade); } }
private void CreateCommands() { GenerateReportFromStrategy = new RelayCommand <IList>(GenReportFromStrategy); GenerateReportFromTags = new RelayCommand <IList>(GenReportFromTags); GenerateReportFromTrades = new RelayCommand <IList>(GenReportFromTrades); LoadStatementFromWeb = ReactiveCommand.CreateFromTask <string>(async x => { var progressDialog = await DialogService.ShowProgressAsync(this, "Load Statement from Web", "Downloading").ConfigureAwait(false); var newData = await StatementHandler.LoadFromWeb(x, progressDialog); if (newData == null) { await progressDialog.CloseAsync(); return; } await PostStatementLoadProcedures(newData, progressDialog); }); LoadStatementFromFile = ReactiveCommand.CreateFromTask <string>(async x => { var progressDialog = await DialogService.ShowProgressAsync(this, "Load Statement from File", "Opening File"); var newData = await StatementHandler.LoadFromFile(x, progressDialog); if (newData == null) { await progressDialog.CloseAsync(); return; } await PostStatementLoadProcedures(newData, progressDialog); }); LoadStatementFromFile.ThrownExceptions.Subscribe(ex => { _logger.Error(ex, "Error on file load"); DialogService.ShowMessageAsync(this, "Error", ex.Message); }); }
/// <summary> /// Splits one order into two different virtual orders with a given share size. /// Used when one order needs to be assigned to two trades. /// </summary> /// <param name="size"></param> private async void SplitIntoVirtualOrders(int size) { if (SelectedOrder == null) { return; } if (size <= 0) { return; } var res = await DialogService.ShowMessageAsync(Parent, "Virtual Order Creation", string.Format("Are you sure you want to create virtual orders for {0} shares?", size), MessageDialogStyle.AffirmativeAndNegative); if (res != MessageDialogResult.Affirmative) { return; } var originalOrder = SelectedOrder; var cloneBuy = (Order)originalOrder.Clone(); var cloneSell = (Order)originalOrder.Clone(); cloneBuy.Quantity = size; cloneSell.Quantity = -size; cloneBuy.Taxes = 0; cloneSell.Taxes = 0; cloneBuy.Commission = 0; cloneSell.Commission = 0; cloneBuy.Notes = ""; cloneSell.Notes = ""; cloneBuy.BuySell = "BUY"; cloneSell.BuySell = "SELL"; cloneBuy.Trade = null; cloneSell.Trade = null; cloneBuy.FIFORealizedPnL = 0; cloneSell.FIFORealizedPnL = 0; cloneBuy.IBOrderID = null; cloneSell.IBOrderID = null; cloneBuy.TradeMoney = size * originalOrder.Price; cloneSell.TradeMoney = -size * originalOrder.Price; cloneBuy.Proceeds = -size * originalOrder.Price; cloneSell.Proceeds = size * originalOrder.Price; cloneBuy.CostBasis = size * originalOrder.Price; cloneSell.CostBasis = -size * originalOrder.Price; cloneBuy.NetCash = -size * originalOrder.Price; cloneSell.NetCash = size * originalOrder.Price; cloneBuy.MTMPnL = size * (originalOrder.Price - originalOrder.ClosePrice); cloneSell.MTMPnL = -size * (originalOrder.Price - originalOrder.ClosePrice); using (var dbContext = _contextFactory.Get()) { dbContext.Orders.Add(cloneBuy); dbContext.Orders.Add(cloneSell); dbContext.SaveChanges(); _data.Orders.Add(cloneBuy); _data.Orders.Add(cloneSell); } OrdersSource.View.Refresh(); }