Summary:
This script is used for optimizing the portfolio script parameters using the Genetic optimization algorithm.

                    
#region Namespaces using System; using System.IO; using System.Linq; using System.Collections.Generic; #endregion namespace ScriptCode { /// <summary> /// Optimization algorithm scripts are used to select the script parameter values to be used in the next optimization runs. /// </summary> public partial class MyOptimizationAlgorithm : OptimizationAlgorithmScriptBase // NEVER CHANGE THE CLASS NAME { #region Variables // Use for the number of generations. private int _generations; // Use for the number of chromosomes selected in each generation. private int _chromosomes; // Use for the number of parents used to create each generation other than the first. private int _parents; // Use for the number of mutations allowed from the parent's child chromosomes. private int _mutations; // Use for holding the vector indexes of the current generation. private List<int> _currentGeneration; // Use for the random number generator. private Random _random; #endregion #region OnInitialize /// <summary> /// This function is used for accepting the script parameters and for initializing the script prior to all other function calls. /// Once the script is assigned to a desktop, its parameter values can be specified by the user. /// </summary> /// -------------------------------------------------------------------------------------------------- /// PLEASE USE THE SCRIPT WIZARD (CTRL+W) TO ADD, EDIT AND REMOVE THE SCRIPT PARAMETERS /// -------------------------------------------------------------------------------------------------- /// YOU MUST SET A PARAM TAG FOR EACH PARAMETER ACCEPTED BY THIS FUNCTION. /// ALL PARAM TAGS SHOULD BE SET IN THE 'OnInitialize' REGION, RIGHT ABOVE THE 'OnInitialize' FUNCTION. /// THE ORDER OF THE TAGS MUST MATCH THE ORDER OF THE ACTUAL PARAMETERS. /// REQUIRED ATTRIBUTES: /// (1) name: The exact parameter name. /// (2) type: The type of data to collect from the user: /// Set to "Integer" when the data type is 'int' /// Set to "IntegerArray" when the data type is 'int[]' /// Set to "DateTime" when the data type is 'long' /// Set to "DateTimeArray" when the data type is 'long[]' /// Set to "Boolean" when the data type is 'bool' /// Set to "BooleanArray" when the data type is 'bool[]' /// Set to "Double" when the data type is 'double' /// Set to "DoubleArray" when the data type is 'double[]' /// Set to "String" when the data type is 'string' /// Set to "StringArray" when the data type is 'string[]' /// OPTIONAL ATTRIBUTES: /// (3) default: The default parameter value is only valid when the type is Integer, Boolean, Double, String or an API Type. /// (4) min: The minimum parameter value is only valid when the type is Integer or Double. /// (5) max: The maximum parameter value is only valid when the type is Integer or Double. /// EXAMPLE: <param name="" type="" default="" min="" max="">Enter the parameter description here.</param> /// -------------------------------------------------------------------------------------------------- /// <param name="generations" type="Integer" default="10">Use for the number of generations.</param> /// <param name="chromosomes" type="Integer" default="20">Use for the number of chromosomes selected in each generation.</param> /// <param name="parents" type="Integer" default="3">Use for the number of parents used to create each generation other than the first.</param> /// <param name="mutations" type="Integer" default="1">Use for the number of mutations allowed from the parent's child chromosomes.</param> public void OnInitialize( int generations, int chromosomes, int parents, int mutations) { // Set the number of generations. _generations = generations; // Set the number of chromosomes. _chromosomes = chromosomes; // Set the number of parents. _parents = parents; // Set the number of mutations. _mutations = mutations; // Create for holding the vector indexes of the current generation. _currentGeneration = new List<int>(); // Create the random number generator. _random = new Random(); } #endregion #region OnSelectNextOptimizationVectors /// <summary> /// This function is called in order to select the next optimization vectors to be processed. /// The function may be called multiple times in a row before the OnUpdateOptimizationVector function is called. /// </summary> /// <returns type="IntegerArray">The indexes of the next optimization vectors to process.</returns> public override int[] OnSelectNextOptimizationVectors() { // Create for holding whether an optimization vector has been added to the new generation. Dictionary<int, bool> exists = new Dictionary<int, bool>(); // Create for holding the vector for the new chromosomes. List<int> newChromosomes = new List<int>(); // Check whether this is the first generation. if (_currentGeneration.Count == 0) { int attempts = 10000; // Iterate until there are enough chromosomes in the new generation or there are no more attempts to select a unique random vector. while (newChromosomes.Count < _chromosomes && attempts > 0) { // Get a random vector index. int index = _random.Next(0, OptimizationVectorCount()); // Check whether the vector hasn't been processed. if (!exists.ContainsKey(index) && !OptimizationVectorIsProcessed(index)) { // Add the vector index to the new chromosomes. newChromosomes.Add(index); // Add the index to the list of existing indexes. exists.Add(index, true); } // Reduce the number of attempts. attempts--; } } else { // Use for the number of unique parent attempts. int uniqueParentAttempts = 0; // Create for holding the next parent chromosomes. List<int> nextParentChromosomes = new List<int>(); // Iterate until there are enough parents, while selecting the best vectors. while (nextParentChromosomes.Count < _parents && uniqueParentAttempts < _parents) { double bestScore = double.MinValue; int bestVector = - 1; // Iterate over the all of the vectors while searching for the best parents. for (int i = 0; i < OptimizationVectorCount(); i++) { // Check whether the current vector score is an improvement and the vector hasn't yet been selected as a parent. if (OptimizationVectorScore(i) > bestScore && !nextParentChromosomes.Contains(i)) { // Update the best score. bestScore = OptimizationVectorScore(i); // Update the best vector. bestVector = i; } } // Add the best vector to the list of parents. nextParentChromosomes.Add(bestVector); // Increase the number of attempts. uniqueParentAttempts++; } // Select the index of the first parent chromosome. int firstIndex = _random.Next(0, nextParentChromosomes.Count); // Select the index of the second parent chromosome. int secondIndex = _random.Next(0, nextParentChromosomes.Count); // Use for the number of unique parent attempts. uniqueParentAttempts = 100; // Iterate until a different second parent chromosome is selected. while (firstIndex == secondIndex && uniqueParentAttempts > 0) { // Select the index of the second parent chromosome. secondIndex = _random.Next(0, nextParentChromosomes.Count); // Reduce the number of attempts. uniqueParentAttempts--; } // Get the first parent chromosome. double[] firstParent = OptimizationVectorValues(nextParentChromosomes[firstIndex]); // Get the second parent chromosome. double[] secondParent = OptimizationVectorValues(nextParentChromosomes[secondIndex]); // Use for the child chromosome. double[] child = new double[firstParent.Length]; // Create the child vector from the selected parents. for (int i = 0; i < child.Length; i++) { // Randomly select items from the parents. if (_random.NextDouble() >= 0.5) child[i] = firstParent[i]; else child[i] = secondParent[i]; } // Use for the number of attempts to find a unique vector. int attempts = 10000; // Set the allowed mutations. int allowedMutations = _mutations; // Iterate until there are enough chromosomes in the new generation or there are no more attempts to create a unique vector. while (newChromosomes.Count < _chromosomes && attempts > 0) { // Create for holding the optimization vectors which match the child, given the number of allowed mutations. List<int> childMatches = new List<int>(); // Iterate over the optimization vectors while searching for those that match the child, given the number of allowed mutations. for (int i = 0; i < OptimizationVectorCount(); i++) { // Check whether the vector hasn't yet been processed. if (!OptimizationVectorIsProcessed(i)) { // Get the values of the current vector. double[] currentValues = OptimizationVectorValues(i); // Use for counting the number of differences between the current optimization vector and the child. int differences = 0; // Iterate over the current vector values. for (int j = 0; j < currentValues.Length; j++) { // Check whether the current optimization vector has an items which is different than the child. if (currentValues[j] != child[j]) differences++; } // Check whether the number of differences is less that the mutations allowed. if (differences <= allowedMutations) // Add the optimization vector as a possible child. childMatches.Add(i); } } // Check whether child matches were found. if (childMatches.Count > 0) { // Get a random child. int index = _random.Next(0, childMatches.Count); // Iterate until a unique child is selected. while (exists.ContainsKey(childMatches[index]) && attempts > 0) { // Get a random child. index = _random.Next(0, childMatches.Count); // Reduce the number of attempts. attempts--; } // Check whether the vector hasn't been selected for this generation.. if (!exists.ContainsKey(childMatches[index])) { // Add the optimization vector. exists.Add(childMatches[index], true); // Add the child to the new chromosomes list. newChromosomes.Add(childMatches[index]); } } // Increase the allowed mutations, since a match wasn't found. else allowedMutations++; // Reduce the number of attempts. attempts--; } } // Clear the chromosomes in the current generation. _currentGeneration.Clear(); // Return the new chromosomes. return newChromosomes.ToArray(); } #endregion #region OnGetMaxVectors /// <summary> /// This function is called to get the number of optimization vectors that the algorithm will /// select and run if the optimization process runs to completion. /// </summary> /// <returns type="Integer">The maximum number of optimization vectors to be run.</returns> public override int OnGetMaxVectors() { // Calculate the maximum number of vectors to calculate. int maxVectors = _generations * _chromosomes; // Check whether the number of vectors to run is less than the number of existing vectors. if (maxVectors <= OptimizationVectorCount()) return maxVectors; else return OptimizationVectorCount(); } #endregion #region OnUpdateOptimizationVector /// <summary> /// This function is called to notify the optimization algorithm that a vector has been processed. /// </summary> /// <param name="vectorIndex" type="Integer">The vector index of the optimization vector that has been processed</param> public override void OnUpdateOptimizationVector(int vectorIndex) { // Check whether the current generation has too many chromosomes. if (_currentGeneration.Count == _chromosomes) _currentGeneration.Clear(); // Check whether the current generation can be added a vector. if (_currentGeneration.Count < _chromosomes) { // Add the specified vector to the generation. _currentGeneration.Add(vectorIndex); } } #endregion #region OnShutdown /// <summary> /// This function is called when the script is shutdown. /// </summary> public override void OnShutdown() { // OnShutdown Content } #endregion } }

The Algorithmic Trading Software for Hedge Funds and Quants