Example #1
0
        //internal async Task<Dictionary<string, BacktestJobStatus>> GetStatuses(IEnumerable<string> jobIds)
        //{
        //    if (jobIds.IsNullOrEmpty())
        //        return new Dictionary<string, BacktestJobStatus>();

        //    Dictionary<string, BacktestJobStatus> statuses = new Dictionary<string, BacktestJobStatus>();

        //    foreach (var jobId in jobIds)
        //    {
        //        BacktestJobStatus status;
        //        if (!statusesDict.TryGetValue(jobId, out status))
        //            status = (await actioner.Get(jobId))?.Status;

        //        if (status != null)
        //            statuses.Add(jobId, status);
        //    }

        //    return statuses;
        //}

        internal async Task <(bool Success, string Message)> AddJob(BacktestJob job)
        {
            logger.Info($"Adding job {job.Name} to database and active queue");

            var result = await actioner.AddOrUpdate(job.Name, job);

            if (!result.Success)
            {
                return(result);
            }

            pendingJobs.Enqueue(job.Name);

            return(true, $"Successfully added job {job.Name}");
        }
        public static BacktestJobModel ToBacktestJobModel(this BacktestJob job)
        {
            if (job == null)
            {
                return(null);
            }

            return(new BacktestJobModel()
            {
                CreateTime = job.CreateTime,
                Day = job.Day,
                EndTime = job.EndTime,
                GroupId = job.GroupId,
                Name = job.Name,
                Output = job.Output.ToBacktestJobOutputDataModel(),
                StartTime = job.StartTime,
                Status = job.Status.ToBacktestStatusModel(),
                UsedHistoMarketData = job.UsedHistoData
            });
        }
        public async Task <GenericActionResult> UpdateStatus(string backtestJobName, BacktestJob job, CancellationToken ct = default(CancellationToken))
        {
            try
            {
                ct.ThrowIfCancellationRequested();

                if (string.IsNullOrEmpty(backtestJobName))
                {
                    throw new ArgumentNullException(nameof(backtestJobName));
                }

                if (job == null)
                {
                    throw new ArgumentNullException(nameof(job));
                }

                logger.Info($"About to send GET request to {controllerEndpoint}/api/jobs/update-status/{backtestJobName}");

                return(await controllerEndpoint.AppendPathSegment($"/api/jobs/update-status/{backtestJobName}").PostJsonAsync(job, ct).ReceiveJson <GenericActionResult>());
            }
            catch (OperationCanceledException)
            {
                string err = "Not posting job update: operation cancelled";
                logger.Error(err);
                return(new GenericActionResult(false, err));
            }
            catch (ArgumentNullException ex)
            {
                string err = $"Not posting job update: missing or invalid parameter {ex.ParamName}";
                logger.Error(err);
                return(new GenericActionResult(false, err));
            }
            catch (Exception ex)
            {
                string err = "Failed to post job update";
                logger.Error(err, ex);
                return(new GenericActionResult(false, $"{err}: {ex.Message}"));
            }
        }
Example #4
0
        public async Task TestNotifyJobStarted()
        {
            string controllerEndpoint = "https://localhost:44379/";

            JobsConnector connector = JobsConnector.GetConnector(controllerEndpoint);

            string groupName = "RegTestJobGroup";
            string jobName   = "RegTestJob";

            BacktestJob job = new BacktestJob(groupName, jobName)
            {
                Day       = DateTime.Today,
                EndTime   = DateTimeOffset.Now,
                StartTime = DateTimeOffset.Now
            };

            job.Status.ActualStartTime = DateTimeOffset.Now;
            job.Status.CompletionTime  = DateTimeOffset.Now;
            job.Status.Worker          = "RegtestWorker";

            var result = await connector.UpdateStatus(jobName, job);

            Assert.IsNotNull(result);
        }
        public async Task <GenericActionResult> UpdateStatus(string backtestJobName, [FromBody] BacktestJob job)
        {
            var result = await utils.UpdateJob(backtestJobName, job);

            return(new GenericActionResult(result.Success, result.Message));
        }
Example #6
0
        internal async Task <(bool Success, string Message)> UpdateJob(string jobName, BacktestJob job)
        {
            try
            {
                logger.Info($"Updating job {jobName} in database and dictionary");

                var result = await actioner.AddOrUpdate(jobName, job);

                if (!result.Success)
                {
                    return(result);
                }
                else
                {
                    return(true, $"Successfully updated job {job.Name}");
                }
            }
            catch (Exception ex)
            {
                string err = $"Failed to update job {job?.Name}";
                logger.Error(err, ex);
                return(false, $"{err}: {ex.Message}");
            }
        }
        internal async Task <(bool Success, string Message, string JobName)> CreateJob(string jobName)
        {
            (bool Success, string Message, string JobName)result = (false, null, jobName);

            try
            {
                var jobSettings = GetJobSettings(jobName);

                if (jobSettings == null)
                {
                    result.Message = $"Failed to get settings for job {jobName}";
                    return(result);
                }

                if (string.IsNullOrEmpty(jobSettings?.StrategyName))
                {
                    throw new ArgumentNullException("StrategyName");
                }

                if (string.IsNullOrEmpty(jobSettings?.StrategyVersion))
                {
                    throw new ArgumentNullException("StrategyVersion");
                }

                if (string.IsNullOrEmpty(jobSettings?.StrategyClass))
                {
                    throw new ArgumentNullException("StrategyClass");
                }

                if (jobSettings.CrossesAndTicketSizes.IsNullOrEmpty())
                {
                    throw new ArgumentNullException("Crosses");
                }

                if (jobSettings.Parameters.IsNullOrEmpty())
                {
                    throw new ArgumentNullException("Parameters");
                }

                var days = DateTimeUtils.EachBusinessDay(jobSettings.StartDate, jobSettings.EndDate);

                if (days.IsNullOrEmpty())
                {
                    throw new ArgumentOutOfRangeException(nameof(days), $"Invalid days interval: start {jobSettings.StartDate}, end: {jobSettings.EndDate}");
                }

                var jobGroup = new BacktestJobGroup(jobName)
                {
                    EndDate   = jobSettings.EndDate,
                    EndTime   = jobSettings.EndTime,
                    StartDate = jobSettings.StartDate,
                    StartTime = jobSettings.StartTime,
                    Strategy  = new Strategy()
                    {
                        AlgoTypeName          = jobSettings.AlgorithmClass,
                        CrossesAndTicketSizes = jobSettings.CrossesAndTicketSizes,
                        Name             = jobSettings.StrategyName,
                        Parameters       = jobSettings.Parameters.ToStrategyParameters("Param"),
                        StrategyDllPath  = jobSettings.NewFileName,
                        StrategyTypeName = jobSettings.StrategyClass,
                        Version          = jobSettings.StrategyVersion
                    },
                    UseHistoDatabase = jobSettings.UseHistoDatabase
                };

                List <GenericActionResult> failed = new List <GenericActionResult>();

                int dayCounter = 1;
                foreach (var day in days)
                {
                    var nycOffsetForDay = day.GetNewYorkTimeUtcOffset();

                    BacktestJob job = new BacktestJob(jobName, $"{jobName}_{dayCounter++}")
                    {
                        Day       = day,
                        EndTime   = new DateTimeOffset(jobSettings.EndTime, nycOffsetForDay),        // End time is expressed in NYC timezone. UTC offset can vary depending on the day
                        StartTime = new DateTimeOffset(jobSettings.StartTime, TimeSpan.FromHours(8)) // Start time is expressed in HK timezone. UTC offset is fixed to +08:00
                    };

                    logger.Info($"Inserting new backtest job {job.Name} in dictionary database");

                    CancellationTokenSource cts = new CancellationTokenSource();
                    cts.CancelAfter(TimeSpan.FromSeconds(5));

                    var addResult = await jobsControllerUtils.AddJob(job);

                    if (addResult.Success)
                    {
                        jobGroup.Jobs.Add(job.Name, new BacktestJobLight()
                        {
                            DayStr = day.ToString("yyyy-MM-dd")
                        });
                    }
                    else
                    {
                        failed.Add(new GenericActionResult(addResult.Success, addResult.Message));
                    }
                }

                if (!jobGroup.Jobs.IsNullOrEmpty() && failed.IsNullOrEmpty())
                {
                    var addResult = await jobGroupsControllerUtils.AddJobGroup(jobGroup);

                    if (addResult.Success)
                    {
                        result.Success = true;
                        result.Message = $"Successfully split backtest job {jobName} into {jobGroup.Jobs.Count} subjobs ({string.Join(", ", jobGroup.Jobs.Keys)}) and submitted.";
                    }
                    else
                    {
                        result.Message = $"Failed to submit group job {jobName}: {result.Message}";
                    }
                }
                else
                {
                    result.Message = $"Failed to submit one or more subjobs: {string.Join(", ", failed.Select(f => f.Message))}";
                }

                return(result);
            }
            catch (ArgumentNullException ex)
            {
                result.Message = $"Failed to insert backtest job: missing or invalid parameter {ex.ParamName}";
                logger.Error(result.Message);
                return(result);
            }
            catch (Exception ex)
            {
                logger.Error("Failed to insert backtest job", ex);
                result.Message = $"Failed to insert backtest job: {ex.Message}";
                return(result);
            }
        }