private static BacktestCommand Parse(string input) { string[] inputs = input.Split(' '); if (inputs.Length == 0) { throw new InvalidCommandException("Invalid command, usage: {command} [arguments]"); } var commands = Reflections.GetAllSubtypes(typeof(BacktestCommand)); Type commandType; try { commandType = commands .First(x => x.GetCustomAttributes(false) .OfType <CommandName>() .Select(a => a.Value) .Contains(inputs[0])); } catch { throw new InvalidCommandException($"{inputs[0]} is not a valid command"); } try { return(Activator.CreateInstance(commandType, new object[] { inputs }) as BacktestCommand); } catch (Exception e) { throw e.InnerException; } }
/// <inheritdoc/> protected override IEnumerable <string> GetErrors(string name, object value) { if (!Reflections.GetAllSubtypes(_parent).Select(x => x.Name).Contains((string)value)) { yield return($"{name} has value {value} which is not a subclass of {_parent.Name}"); } }
/// <summary> /// Initializes a new instance of the <see cref="StartBacktestCommand"/> class. /// </summary> /// <param name="inputs">inputs.</param> public StartBacktestCommand(string[] inputs) : base(inputs) { Parser parser = new Parser(x => x.HelpWriter = null); parser.ParseArguments <StartBacktestCommandArguments>(inputs) .WithNotParsed(_ => throw new InvalidCommandException("invalid arguments, use help to get more info")) .WithParsed(x => _args = x); // Check if the input type is a valid algorithm _algo = Reflections.GetAllImplementations(typeof(IBaseAlgorithm)) .FirstOrDefault(x => x.Name == _args.AlgorithmName) ?? throw new InvalidCommandException($"{_args.AlgorithmName} is not a known algorithm"); // Retrieve the settings type var settingsType = Reflections.GetAllSubtypes(typeof(AlgorithmConfiguration)) .FirstOrDefault(s => Reflections.AlgorithmMatchesConfiguration(_algo, s)) ?? throw new InvalidCommandException( $"{_args.AlgorithmName} does not have a configuration object and cannot be started."); // Optionally load with custom path. if (!_args.Inline) { _args.ConfigurationPath = _args.ConfigurationPath ?? _args.AlgorithmName + ".yaml"; try { _configuration = ConfigurationLoader.LoadConfiguration(settingsType, _args.ConfigurationPath); } catch (Exception e) { throw new InvalidCommandException(e.Message); } } else { _configuration = BacktestDaemonService.GetConfigurationFromUser(settingsType); } DatabaseUtilities.Instance.ValidateCandleWidth(_configuration.TradingPairs, Configuration.Configuration.Instance.CandleWidth); ConfigureTimestampEdges(BacktestDaemonService.Instance.State, _args); Program.CommandLineArgs.BacktestOutputPath = _args.OutputPath; }
/// <inheritdoc/> public override void Execute(BacktestDaemonState state) { var allCommands = Reflections.GetAllSubtypes(typeof(BacktestCommand)); // Get a list of tuples -> [(name(s), args, description)] var overview = allCommands .Select( c => (string.Join(", ", c.GetCustomAttributes(true) .OfType <CommandName>().Select(x => x.Value)), string.Join(",", c.GetCustomAttribute <CommandArguments>().Values), c.GetCustomAttribute <CommandDescription>().Value)); var table = new ConsoleTable("command", "arguments", "description"); foreach (var(names, args, description) in overview) { table.AddRow(names, args, description); } table.Write(Format.MarkDown); }