Summary: This optimization script selects a specified number of random optimization vectors, which are used for initializing and running the portfolio, and calculating the PnL after each run. After the initial selection of optimization vectors have been runned and scored, the vector range is narrowed around the highest scored vector, and the process is repeated. Each time the process is repeated the vector range is narrowed to vectors that are more likely to produce higher scores. The script does not guarantee that the optimal set of parameter arguments will be found, but it can lead to good approximations using relatively few portfolio runs.
' Assign the parameters to script variables. _passes = passes _runs = runs _findMaximum = findMaximum ' Create for holding the low optimization vector values indexed by vector index. Redefine _lowRanges(OptimizationVectorItemCount() - 1) ' Create for holding the high optimization vector values indexed by vector index. Redefine _highRanges(OptimizationVectorItemCount() - 1) ' Get the number of items in an optimization vector. (The vector length) _vectorLength = OptimizationVectorItemCount() ' Calculate the number of possible optimization vectors. _maxVectors = _passes * _runs ' Define the statistics request used. StatsRequest(-1,DateTimeStart(),DateTimeEnd(),True,True,True,True,useTrades)
' Return the maximum number of optimization vectors. Return _maxVectors
' Check whether the optimization goal is set for the maximum or minimum value. If (_findMaximum) Then Return StatsProfitLoss() Else Return -1 * StatsProfitLoss() End If
' Use for the result optimization vector. Define result(_vectorLength - 1) As Number ' Update the high and low optimization vector range. UpdateHighLowRanges() ' Use for counting the maximum number of attempts for finding an original optimization vector. Define maxAttempts As Integer = 100 ' Search for a new random optimization vector. While maxAttempts > 0 ' Generate a random optimization vector. For i As Integer = 0 To _vectorLength - 1 ' Count the number of vector item options in the current item range. Define maxStepsInRange As Integer = MathFloor((_highRanges(i) - _lowRanges(i)) / OptimizationVectorItemStep(i)) ' Find a random number of steps in the range. Define randomSteps As Integer = MathRandom(0, maxStepsInRange) ' Set a new random value for the vector item. result(i) = _lowRanges(i) + (OptimizationVectorItemStep(i) * randomSteps) ' Check whether the item range is to high and needs to be limited. If (result(i) > _highRanges(i)) Then result(i) = _highRanges(i) End If Next Define exists As Boolean = False ' Iterate over the existing optimization vectors while comparing them to the new one. For i As Integer = 0 To OptimizationVectorCount() - 1 ' Get the current optimization vector. Define vector() As Number = OptimizationVector(i) Define equal As Boolean = True ' Iterate over the optimization vector items while comparing the current vector items to the new vector item. For j As Integer = 0 To _vectorLength - 1 ' Check whether the current vector item isn 't equal to the new vector item. If (result(j) <> vector(j)) Then equal = False End If Next ' If an equal vector was found then flag the new optimization vector as existing. If equal Then exists = True Exit For End If Next ' If the new optimization vector is indeed original, then stop searching for a new vector. If Not exists Then Exit While End If ' Reduce the number of attempts left to find an original optimization vector. maxAttempts -= 1 End While Return result
' Calculate the current pass. Define currentPass As Integer = MathFloor(OptimizationVectorCount() / _runs) ' Calculate the current run. Define currentRun As Integer = OptimizationVectorCount() Mod _runs ' Initialize the low and high values of the optimization vector item ranges, with the values specified by the user. For i As Integer = 0 To _vectorLength - 1 _lowRanges(i) = OptimizationVectorItemLow(i) _highRanges(i) = OptimizationVectorItemHigh(i) Next ' Check whether at least one pass has been completed, since the first vector is random from the entire range of values. If (currentPass >= 1) Then ' Get the first vector index in the previous pass. Define firstVectorIndexInPass As Integer = (currentPass - 1) * _runs ' Get the last vector index in the previous pass. Define lastVectorIndexInPass As Integer = (currentPass * _runs) - 1 ' Initialize the highest scored vector in the pass with the first vector in the pass. Define highestScore As Number = OptimizationVectorScore(firstVectorIndexInPass) ' Initialize the index of the highest scored vector in the current pass with the first vector in the pass. Define bestVectorIndex As Integer = firstVectorIndexInPass ' Iterate over the vectors in the pass while searching for the highest scored vector in the current pass. For j As Integer = firstVectorIndexInPass To lastVectorIndexInPass ' Check whether the current optimization vector score had the highest score so far. If (highestScore < OptimizationVectorScore(j)) Then ' Update the highest score so far. highestScore = OptimizationVectorScore(j) ' Update the best vector index found so far. bestVectorIndex = j End If Next ' Get the highest scored vector in pass as was just found. Define bestVectorInPass() As Number = OptimizationVector(bestVectorIndex) For j As Integer = 0 To _vectorLength - 1 ' Get the number of optimization options for the current item index. Define itemOptions As Number = OptimizationVectorItemOptionCount(j) ' Calculate the number of options to reduce for the current vector item after each pass. Define itemOptionsToRemove As Integer = MathFloor((itemOptions / _passes) * currentPass) ' Get the optimization vector item value of the best optimization vector found so far. Define optimalValue As Number = bestVectorInPass(j) ' Get the step value of the current item. Define itemStep As Number = OptimizationVectorItemStep(j) ' Check whether the high and low range values for the current vector item aren 't yet equal, ' which means they can be adjusted. If (_highRanges(j) <> _lowRanges(j)) Then ' Use for the number of items to remove from the bottom of the range. Define itemsToRemoveFromBottom As Integer = MathFloor(itemOptionsToRemove * ((optimalValue - _lowRanges(j)) / (_highRanges(j) - _lowRanges(j)))) ' Use for the number of items to remove from the top of the range. Define itemsToRemoveFromTop As Integer = MathFloor(itemOptionsToRemove * ((_highRanges(j) - optimalValue) / (_highRanges(j) - _lowRanges(j)))) ' Modify the lower range value for the item. _lowRanges(j) = _lowRanges(j) + itemStep * itemsToRemoveFromBottom ' Modify the higher range value for the item. _highRanges(j) = _highRanges(j) - itemStep * itemsToRemoveFromTop ' Check whether the modified low and high range values are still valid. If (_lowRanges(j) > _highRanges(j)) Then ' Fix the low and high range values as they aren 't valid. _lowRanges(j)= _highRanges(j) End If End If Next End If