{ User function: MonteCarlo Monte Carlo simulation for position sizing. This function records the profits and losses from the trading system that calls it and generates random sequences of the trades. For each sequence, it calculates the return and drawdown assuming a fixed percent of the account is risked on each trade. The result is the probability that with a given account size and risk percentage you can meet given rate of return and drawdown goals. For example, it might calculate the probability that you can achieve a rate of return of 50% with 30% drawdown by risking 10% on each trade. ATTENTION TRADESTATION 4.0 USERS Because this function calls the built-in function Random, which is new to TradeStation 2000i, this function will not work in TradeStation 4.0. I have developed a version of MonteCarlo with additional functionality and several input and output options that will work with either TradeStation 2000i or 4.0. This version can be purchased on my web site. Copyright 2001 Breakout Future www.BreakoutFutures.com mrb@BreakoutFutures.com } Input: ASize (NumericSimple), { account size, $ } RetGoal (NumericSimple), { rate of return goal, %} DDGoal (NumericSimple), { max closed out trade drawdown, % } RiskPer (NumericSimple), { percentage risk per trade } TrRisk (NumericSeries), { risk for current trade, $ } NRand (NumericSimple); { number of random sequences } Array: Trades[200](0), { Trades, $ (win +; loss -) } TrRisks[200](0), { trade risks, $ (+) } RandNums[200](0), { array of random numbers } RandIndx[200](-1); { randomly chosen indices for trade array } Var: NTrades (0), { Number of trades } iSeq (0), { sequence number } MaxNum (0), { max number left in random number array RandNums } iMax (0), { index (location) of MaxNum in array RandNums } NCon (0), { number of contracts } Equity (0), { account equity } NewEquity (0), { account equity } EqtyHigh (0), { highest equity } DD (0), { closed trade drawdown } DDmax (0), { worst case closed trade drawdown } PReturn (0), { percent return } AveRet (0), { average percent return } ProbRet (0), { probability of return goal } ProbDD (0), { probability of drawdown goal } ProbComb(0), { probability of return & DD goals } ii (0), { loop counter } jj (0), { loop counter } k (0); { loop counter } { Collect profit/loss and risk } If TotalTrades > NTrades then Begin If TotalTrades - NTrades < 2 then Begin NTrades = NTrades + 1; Trades[NTrades - 1] = PositionProfit(1); TrRisks[NTrades - 1] = TrRisk; end else Begin { case where TotalTrades increments by 2 from one bar to next } NTrades = NTrades + 1; Trades[NTrades - 1] = PositionProfit(2); TrRisks[NTrades - 1] = TrRisk[1]; NTrades = NTrades + 1; Trades[NTrades - 1] = PositionProfit(1); TrRisks[NTrades - 1] = TrRisk; end; end; { Calculate results 1 day from last bar on chart } If Date = JulianToDate(DateToJulian(LastCalcDate) - 1) {LastBarOnChart} then Begin for iSeq = 1 to NRand Begin { loop over # of random sequences } { Generate random sequence of trades } For ii = 0 to NTrades - 1 Begin { generate random numbers } RandNums[ii] = IntPortion(NTrades * Random(10)); end; For ii = 0 to NTrades - 1 Begin { sort index of RandNums array } MaxNum = -1; For jj = 0 to NTrades - 1 Begin { find biggest remaining number } If RandNums[jj] > MaxNum then Begin MaxNum = RandNums[jj]; iMax = jj; end; end; RandIndx[ii] = iMax; { record location of max number } RandNums[iMax] = -1; { "remove" max number from array } end; { Calculate account balance and drawdown for current sequence of trades } Equity = ASize; EqtyHigh = Equity; DDmax = 0; For ii = 0 to NTrades - 1 Begin NCon = IntPortion(RiskPer/100 * Equity/TrRisks[RandIndx[ii]]); NewEquity = Equity + NCon * Trades[RandIndx[ii]]; { Calculate closed trade percent drawdown } If (NewEquity > EqtyHigh) then EqtyHigh = NewEquity else Begin DD = 100 * (EqtyHigh - NewEquity)/EqtyHigh; if (DD > DDmax) then DDmax = DD; end; Equity = NewEquity; end; { for ii } PReturn = 100 * (Equity - ASize)/ASize; { Accumulate results for probability calculations } AveRet = AveRet + PReturn; if (PReturn >= RetGoal) then ProbRet = ProbRet + 1; if (DDmax <= DDGoal) then ProbDD = ProbDD + 1; if (PReturn >= RetGoal and DDmax <= DDGoal) then ProbComb = ProbComb + 1; End; { for iSeq } { Calculate probabilities by dividing sums by number of sequences } AveRet = AveRet/NRand; ProbRet = 100 * ProbRet/NRand; ProbDD = 100 * ProbDD/NRand; ProbComb = 100 * ProbComb/NRand; MessageLog("RiskPer=", RiskPer:5:1," RetGoal=", RetGoal:5:1," DDGoal=", DDGoal:5:1, " ProbRet=",ProbRet:5:1," ProbDD=",ProbDD:5:1," ProbComb=", ProbComb:5:1); MessageLog("Average Return = ", AveRet:6:2); end; MonteCarlo = 1;