private static async Task IterateAllParametersNoRecursion(ApproachDefinition approachDefinition, List <AlgorithmParameter> parameters, RunDefinitionBuffer buffer) { //build arrays of possible values double[][] parameterRanges = new double[parameters.Count][]; for (int current = 0; current < parameters.Count; current++) { parameterRanges[current] = parameters[current].GetParamterRange(); } //now get the cartesian product of all the lists var allCombinations = Common.Crossproduct <double>(parameterRanges); foreach (var combination in allCombinations) { var index = 0; foreach (var value in combination) { if (parameters[index].ValueIsBoolean) { parameters[index].BooleanValue = value != 0; } else { parameters[index].NumericValue = value; } index++; } await buffer.AddAsync(new RunDefinition(approachDefinition)); //await Task.Delay(1); } }
public static async Task <int> GenerateAsync(ApproachDefinition approachDefinition, SaveRunDefintionsCallback saveFunction, int bufferBeforeSave = 100, StatusCallback statusFunction = null, int bufferBeforeStatus = 100) { var totalPermutations = 0; //the iteration of all the parameters changes the definition, //so we deep clone to ensure the original definition is not modified ApproachDefinition approach = approachDefinition.DeepClone <ApproachDefinition>(); //Get all the parameters on all algorithms of the approach and initialize them List <AlgorithmParameter> allParameters = PrepareParameters(approach); //Get a total number of iterations expected for status updates RunDefinitionBuffer buffer = PrepareRunDefinitionBuffer(saveFunction, bufferBeforeSave, statusFunction, bufferBeforeStatus, allParameters); //Iterate all the possible combinations of the parameters, and invoke the save and status callbacks stored in the buffer //IterateAllParameters(approach, allParameters, buffer); await IterateAllParametersNoRecursion(approach, allParameters, buffer); //Make sure all items are saved and status updated buffer.FlushBuffer(); totalPermutations = buffer.PermutationCount; return(totalPermutations); }
private static void IterateAllParameters(ApproachDefinition approachDefinition, List <AlgorithmParameter> parameters, RunDefinitionBuffer buffer) { Console.WriteLine("Iterating All Parameters"); if (CancelGeneration) { return; //this will prevent an new definitions from buffering, but it still needs to unwind the stack } var currentParameter = parameters.FirstOrDefault(); if (currentParameter != null) { //we get a list of the remaining parameters that need to be recursed through var otherParameters = parameters.Skip(1).ToList(); if (currentParameter.UseRange) { if (currentParameter.ValueIsBoolean) { //The boolean range is only 2 values...so we just set those two and recurse the other parameters currentParameter.BooleanValue = true; SaveOrNext(approachDefinition, otherParameters, buffer); currentParameter.BooleanValue = false; SaveOrNext(approachDefinition, otherParameters, buffer); } else { //this is a numerical range, so we recurse through all the parameters /* * NOTE: The double extension method of 'LessThanAlmostEqualTo' is used here * to avoid rounding errors due to binary representation of rational numbers * * DECIMAL datatype is more appropriate for this reason, * however is significantly slower than double. When dealing with * millions of iterations, the double vs decimal speed difference is meaningful */ for (double r = currentParameter.RangeStart; r.LessThanAlmostEqualTo(currentParameter.RangeEnd); r += currentParameter.RangeStep) { if (CancelGeneration) { return; //this will prevent an new definitions from buffering, but it still needs to unwind the stack } currentParameter.NumericValue = r; SaveOrNext(approachDefinition, otherParameters, buffer); } } currentParameter.NumericValue = currentParameter.RangeStart; } else { //The parameter already holds the 1 value that will be evaluated, so we iterate the others and evaluate //the other parameters need to incement for each value of r SaveOrNext(approachDefinition, otherParameters, buffer); } } }
private static List <AlgorithmParameter> PrepareParameters(ApproachDefinition approach) { //gather the buy and sell algorithms from the approach into one list var algorithmDefs = approach.AllAlgorithms; //Initialize all the parameters to their initial value InitializeAllParameters(algorithmDefs); //Get all the parameters from across all the algorithms return(algorithmDefs.SelectMany(a => a.Parameters).ToList()); }
private static void SaveOrNext(ApproachDefinition approach, List <AlgorithmParameter> otherParameters, RunDefinitionBuffer buffer) { //we only save if there are no other parameters to iterate //this means this iteration definition is complete and all parameters have been set. if (otherParameters.Count == 0) { //create a run definition and buffer it. The buffer manages flushing/saving the run definitions buffer.AddAsync(new RunDefinition(approach)); } else { Task.Delay(1); //there are other parameters that need to be set before we can save the definition IterateAllParameters(approach, otherParameters, buffer); } }
private async Task <bool> SaveToLocalStorage(ApproachDefinition approachDefinition) { try { Console.WriteLine("in SaveLocalStorage"); await localStorage.SetItemAsync($"ApproachID:{approachDefinition.Id}", approachDefinition); } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(e.StackTrace); return(false); } Console.WriteLine("out SaveLocalStorage"); return(true); }
private static void IterateSingleParameter(ApproachDefinition approach, AlgorithmParameter currentParameter, RunDefinitionBuffer buffer) { if (currentParameter.UseRange) { if (currentParameter.ValueIsBoolean) { //The boolean range is only 2 values...so we just set those two and recurse the other parameters currentParameter.BooleanValue = true; buffer.AddAsync(new RunDefinition(approach)); currentParameter.BooleanValue = false; buffer.AddAsync(new RunDefinition(approach)); } else { //this is a numerical range, so we recurse through all the parameters /* * NOTE: The double extension method of 'LessThanAlmostEqualTo' is used here * to avoid rounding errors due to binary representation of rational numbers * * DECIMAL datatype is more appropriate for this reason, * however is significantly slower than double. When dealing with * millions of iterations, the double vs decimal speed difference is meaningful */ for (double r = currentParameter.RangeStart; r.LessThanAlmostEqualTo(currentParameter.RangeEnd); r += currentParameter.RangeStep) { if (CancelGeneration) { return; //this will prevent an new definitions from buffering, but it still needs to unwind the stack } currentParameter.NumericValue = r; buffer.AddAsync(new RunDefinition(approach)); } } currentParameter.NumericValue = currentParameter.RangeStart; } else { buffer.AddAsync(new RunDefinition(approach)); } }
private async Task <bool> SaveToServer(ApproachDefinition approachDefinition) { ApproachCreateDto createApproach = new ApproachCreateDto { Name = approachDefinition.Name, ApproachDefinitionJson = System.Text.Json.JsonSerializer.Serialize(approachDefinition) }; //Save to server using var response = await _http.PostAsJsonAsync("https://localhost:5051/api/approaches", createApproach); if (response.IsSuccessStatusCode) { var approachReadDto = await response.Content.ReadFromJsonAsync <ApproachReadDto>(); approachDefinition.Id = approachReadDto.Id; //Now save to local storage return(true); } return(false); }
public RunDefinition(ApproachDefinition definitionToClone) { ApproachDefinition = Utility.DeepClone <ApproachDefinition>(definitionToClone); }