Saturday, September 04, 2010

Monte Carlo, PnL [MCPL]

Descripton
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. 


Variables
TypeIdentifierDescription
Integer_passesUse for the number of passes in the optimization process. After each pass the vector range is narrowed around the highest scored vector calculated in the previous pass.
Integer_runsUse for the number of times to run the portfolio with a random optimization vector selected from the value range defined by the pass.
Integer_maxVectorsUse for the maximum number of optimization vectors.
Integer_vectorLengthUse for the number of items in the vector.
NumberArray_lowRangesUse for holding the lower range values for the optimization vector items, indexed by item index.
NumberArray_highRangesUse for holding the higher range values for the optimization vector items, indexed by item index.
Boolean_findMaximumUse for indicating whether to find the maximum or minimum score.

OnInitialize
Function Parameters
TypeIdentifierDescription
IntegerpassesUse for the number of passes in the optimization process. After each pass the vector range is narrowed around the highest scored vector calculated in the previous pass.[Default 5]
IntegerrunsUse for the number of times to run the portfolio with a random optimization vector, for each optimization pass. [Default 5]
BooleanfindMaximumUse for indicating whether to find the maximum or minimum score. [Default True]
BooleanuseTradesUse for indicating whether to use trades or position statistics. [Default True]
Implementation
	 ' 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)

OnMaxVectors
Function Parameters
TypeIdentifierDescription
Implementation
	 ' Return the maximum number of optimization vectors.
	Return _maxVectors

OnScoreVector
Function Parameters
TypeIdentifierDescription
Implementation
	 ' Check whether the optimization goal is set for the maximum or minimum value.
	If (_findMaximum) Then
		Return StatsProfitLoss()
	Else 
		Return -1 * StatsProfitLoss()
	End If

OnSelectVector
Function Parameters
TypeIdentifierDescription
Implementation
	 ' 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

UpdateHighLowRanges
Function Parameters
TypeIdentifierDescription
Implementation
	 ' 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

Copyright © 2010 IQBroker, LLC. All rights reserved.