public BacktestJobSettingsModel SetCrosses(string jobName, List <CreateJobStep1bPairViewModel> crosses) { return(jobs.AddOrUpdate(jobName, (key) => null, (key, oldValue) => { if (!crosses.IsNullOrEmpty()) { oldValue.CrossesAndTicketSizes = crosses.ToDictionary(c => CrossUtils.GetFromStr(c.Cross), c => c.Quantity); } return oldValue; })); }
public async Task <GenericActionResult> UnsubscribePair(string dbLoggerName, string pair) { return(await DBLoggerManager.Instance.UnsubscribePair(dbLoggerName, CrossUtils.GetFromStr(pair))); }
public (bool Success, string Message, List <BacktestJobSettingsModel> JobsSettings) ReadFile(string filePath) { (bool Success, string Message, List <BacktestJobSettingsModel> JobsSettings)result = (false, null, null); try { if (string.IsNullOrEmpty(filePath)) { throw new ArgumentNullException(nameof(filePath)); } if (!File.Exists(filePath)) { result.Message = $"File {filePath} does not exist"; return(result); } using (ExcelPackage excel = new ExcelPackage(new FileInfo(filePath))) { var ws = excel.Workbook.Worksheets.FirstOrDefault(); if (ws == null) { result.Message = "Excel file is empty"; return(result); } // Validate header if (ws.Dimension.End.Row < 2) { result.Message = $"Incorrect length of the Excel file: expected at least 1 header row and 1 job row"; return(result); } if (ws.Dimension.End.Column < 6) { result.Message = $"Incorrect length of the Excel file: expected at least 5 columns (not counting strat parameters)"; return(result); } if (ws.Cells[1, 1].Value.ToString() != "DLL") { result.Message = $"Incorrect value for column 1: expected 'DLL'"; return(result); } List <BacktestJobSettingsModel> jobsSettings = new List <BacktestJobSettingsModel>(); int rowIndex = 2; while (ws.Cells[rowIndex, 1].Value != null) { #region DLL string dll = ws.Cells[rowIndex, 1].Value?.ToString(); if (string.IsNullOrEmpty(dll)) { return(false, $"Failed to parse job definition on row {rowIndex}: missing value for 'DLL'", null); } var readDllResult = ReadDll(dll); if (!readDllResult.Success) { result.Message = $"Failed to read DLL: {readDllResult.Message}"; logger.Error(result.Message); return(result); } #endregion #region Crosses Dictionary <Cross, int> crossesAndTicketSizes = new Dictionary <Cross, int>(); int colIndex = 2; string header = ws.Cells[1, colIndex].Value?.ToString(); while (!string.IsNullOrEmpty(header) && header.ToLower().StartsWith("cross")) { string crossStrValue = ws.Cells[rowIndex, colIndex].Value?.ToString(); if (!string.IsNullOrEmpty(crossStrValue)) { string[] parts = crossStrValue.Split(':'); if (parts.Length == 2) { if (CrossUtils.TryParse(parts[0], out Cross cross) && int.TryParse(parts[1], out int quantity)) { if (!crossesAndTicketSizes.ContainsKey(cross)) { crossesAndTicketSizes.Add(cross, quantity); } } } } header = ws.Cells[1, ++colIndex].Value?.ToString(); } if (crossesAndTicketSizes.IsNullOrEmpty()) { result.Message = $"Failed to parse at least one cross for job on row {rowIndex}"; return(result); } #endregion #region StartDate if (ws.Cells[1, colIndex].Value.ToString() != "StartDate") { result.Message = $"Incorrect value for column {colIndex}: expected 'StartDate'"; return(result); } if (string.IsNullOrEmpty(ws.Cells[rowIndex, colIndex].Value.ToString()) || !DateTime.TryParse(ws.Cells[rowIndex, colIndex++].Value.ToString(), out DateTime startDate)) { return(false, $"Failed to parse job definition on row {rowIndex}: missing or invalid value for 'StartDate'", null); } #endregion #region EndDate if (ws.Cells[1, colIndex].Value.ToString() != "EndDate") { result.Message = $"Incorrect value for column {colIndex}: expected 'EndDate'"; return(result); } if (string.IsNullOrEmpty(ws.Cells[rowIndex, colIndex].Value.ToString()) || !DateTime.TryParse(ws.Cells[rowIndex, colIndex++].Value.ToString(), out DateTime endDate)) { return(false, $"Failed to parse job definition on row {rowIndex}: missing or invalid value for 'EndDate'", null); } #endregion #region StartTime if (ws.Cells[1, colIndex].Value.ToString() != "StartTime") { result.Message = $"Incorrect value for column {colIndex}: expected 'StartTime'"; return(result); } if (string.IsNullOrEmpty(ws.Cells[rowIndex, colIndex].Value.ToString()) || !DateTime.TryParse(ws.Cells[rowIndex, colIndex++].Value.ToString(), out DateTime startTime)) { return(false, $"Failed to parse job definition on row {rowIndex}: missing or invalid value for 'StartTime'", null); } #endregion #region EndTime if (ws.Cells[1, colIndex].Value.ToString() != "EndTime") { result.Message = $"Incorrect value for column {colIndex}: expected 'EndTime'"; return(result); } if (string.IsNullOrEmpty(ws.Cells[rowIndex, colIndex].Value.ToString()) || !DateTime.TryParse(ws.Cells[rowIndex, colIndex++].Value.ToString(), out DateTime endTime)) { return(false, $"Failed to parse job definition on row {rowIndex}: missing or invalid value for 'EndTime'", null); } #endregion #region UseHistoDatabase if (ws.Cells[1, colIndex].Value.ToString() != "UseHistoDatabase") { result.Message = $"Incorrect value for column {colIndex}: expected 'UseHistoDatabase'"; return(result); } if (string.IsNullOrEmpty(ws.Cells[rowIndex, colIndex].Value.ToString()) || !bool.TryParse(ws.Cells[rowIndex, colIndex++].Value.ToString(), out bool useHistoDatabase)) { return(false, $"Failed to parse job definition on row {rowIndex}: missing or invalid value for 'UseHistoDatabase'", null); } #endregion #region Parameters Dictionary <string, BacktestJobStrategyParameterModel> parameters = new Dictionary <string, BacktestJobStrategyParameterModel>(); for (int paramColIndex = colIndex; paramColIndex <= ws.Dimension.End.Column; paramColIndex++) { string key = ws.Cells[1, paramColIndex].Value.ToString(); string value = ws.Cells[rowIndex, paramColIndex].Value.ToString(); if (!string.IsNullOrEmpty(key) && !parameters.ContainsKey(key)) { parameters.Add(key, new BacktestJobStrategyParameterModel() { Name = key, Tooltip = null, Value = value }); } } #endregion var jobSettings = new BacktestJobSettingsModel() { AlgorithmClass = readDllResult.AlgorithmClass, CrossesAndTicketSizes = crossesAndTicketSizes, EndDate = endDate, EndTime = endTime, NewFileName = readDllResult.DllFileName, OriginalFileName = readDllResult.DllFileName, Parameters = parameters.Values.ToList(), StartDate = startDate, StartTime = startTime, StrategyClass = readDllResult.StrategyClass, StrategyName = readDllResult.StrategyName, StrategyVersion = readDllResult.StrategyVersion, UseHistoDatabase = useHistoDatabase }; jobSettings.JobName = createJobControllerUtils.AssignJobNameAndAddToDictionary(jobSettings); jobsSettings.Add(jobSettings); rowIndex++; } if (jobsSettings.Count > 0) { result.Success = true; result.Message = $"Parsed {jobsSettings.Count} jobs"; result.JobsSettings = jobsSettings; } else { result.Message = "Found no job in the file"; } return(result); } } catch (ArgumentNullException ex) { result.Message = $"Not reading Excel file: missing or invalid parameter {ex.ParamName}"; logger.Error(result.Message); return(result); } catch (Exception ex) { result.Message = "Failed to read Excel file"; logger.Error(result.Message, ex); return(result); } }