{ AutoSystemGen This system is designed to automatically generate profitable trading systems based on price patterns. When the system is optimized, it randomly generates price patterns and writes Easylanguage trading system code for each system that meets specified performance criteria. After the optimization is complete, the code for each successful system can be found in the text file specified in the function WriteSystems. Mike Bryant Breakout Futures www.BreakoutFutures.com mrb@BreakoutFutures.com Copyright 2007 Breakout Futures } Inputs: OptStep (0), { Optimization step; optimize this var } TradeDir (1), { +1 -> long trades; -1 -> short trades } reqNetProf(0), { minimum required net profit } reqMaxDD (0), { required max drawdown limit } reqNTrades(0), { required minimum number of trades } reqPerWins(0), { required minimum percentage of wins } reqProfFac(0); { required minimum profit factor } Var: NRules (0), { Number of rules/patterns to use } NBarExit (0), { Number of bars to hold trades } ii (0), { Loop counter } ProfFac (0), { profit factor } FuncRet (false),{ function return variable } EntNext (false);{ logical flag for entering next bar } Array: PriceL[10](0), { 0 - 3 for O, H, L, C for left-hand side } PriceR[10](0), { 0 - 3 for O, H, L, C for right-hand side } InEq[10] (0), { 0 - 1 for >=, <= } DaysL[10] (0), { days back for left-hand price } DaysR[10] (0); { days back for right-hand price } { Randomly select values for the variables that define the rules } If BarNumber = 1 then FuncRet = GetPatVars(PriceL, PriceR, InEq, DaysL, DaysR, NRules, NBarExit); { Evaluate the price patterns/rules to determine if a trade should be placed } EntNext = true; For ii = 0 to NRules - 1 Begin EntNext = EntNext and EvalPattern(ii, PriceL, PriceR, InEq, DaysL, DaysR); End; { Place the trade, either long or short } If EntNext then Begin If TradeDir > 0 then Buy next bar at market else if TradeDir < 0 then Sell short next bar at market; End; { Exit the open trade NBarExit bars after entry } If BarsSinceEntry = NBarExit then Begin If MarketPosition > 0 then Sell next bar at market else if MarketPosition < 0 then Buy to cover next bar at market; End; { Write out the trading system code if the system is successful } If AbsValue(GrossLoss) > 0 then ProfFac = GrossProfit/AbsValue(GrossLoss) else ProfFac = 100; If LastBarOnChart and NetProfit >= reqNetProf and AbsValue(MaxIDDrawDown) <= AbsValue(reqMaxDD) and TotalTrades >= reqNTrades and PercentProfit >= reqPerWins and ProfFac >= reqProfFac then FuncRet = WriteSystem(OptStep, TradeDir, PriceL, PriceR, InEq, DaysL, DaysR, NRules, NBarExit, "C:\AutoSysGen-Output1.txt"); { Function: GetPatVars Randomly select variable for pattern variables. Called by strategy AutoPatFinder. Mike Bryant Breakout Futures www.BreakoutFutures.com mrb@BreakoutFutures.com Copyright 2007 Breakout Futures } Inputs: PriceL[max1] (NumericArrayRef), { Array of left-hand prices } PriceR[max2] (NumericArrayRef), { Array of right-hand prices } InEq[max3] (NumericArrayRef), { Array of inequality signs } DaysL[max4] (NumericArrayRef), { Array of days back, left side } DaysR[max5] (NumericArrayRef), { Array of days back, right side } NRules (NumericRef), { Number of rules/patterns } NBarExit (NumericRef); { Number of bars until exit } Var: ii (0); { loop counter } NRules = GetRandomInt(1, 10); NBarExit = GetRandomInt(1, 20); For ii = 0 to NRules - 1 Begin PriceL[ii] = GetRandomInt(0, 3); PriceR[ii] = GetRandomInt(0, 3); InEq[ii] = GetRandomInt(0, 1); DaysL[ii] = GetRandomInt(0, 20); DaysR[ii] = GetRandomInt(0, 20); End; GetPatVars = true; { Function: EvalPattern Evaluate the price pattern. PriceL, PriceR: 0 - 3 -> O, H, L, C InEq: 0 - 1 -> >=, <= DaysL, DaysR: 0 - 20 -> days back Rule/Pattern: Value (true/false) = PriceL[DaysL] InEq PriceR[DaysR] Example, Value = C[1] <= L[2]; Mike Bryant Breakout Futures www.BreakoutFutures.com mrb@BreakoutFutures.com Copyright 2007 Breakout Futures } Inputs: iRule (NumericSimple), { Price pattern/rule to evaluate } PriceL[max1] (NumericArrayRef), { Array of left-hand prices } PriceR[max2] (NumericArrayRef), { Array of right-hand prices } InEq[max3] (NumericArrayRef), { Array of inequality signs } DaysL[max4] (NumericArrayRef), { Array of days back, left side } DaysR[max5] (NumericArrayRef); { Array of days back, right side } Var: RuleVal (FALSE); { value of rule/pattern } If PriceL[iRule] = 0 then Begin If PriceR[iRule] = 0 then Begin If InEq[iRule] = 0 then RuleVal = Open[DaysL[iRule]] >= Open[DaysR[iRule]] else if InEq[iRule] = 1 then RuleVal = Open[DaysL[iRule]] <= Open[DaysR[iRule]]; end else if PriceR[iRule] = 1 then Begin If InEq[iRule] = 0 then RuleVal = Open[DaysL[iRule]] >= High[DaysR[iRule]] else if InEq[iRule] = 1 then RuleVal = Open[DaysL[iRule]] <= High[DaysR[iRule]]; end else if PriceR[iRule] = 2 then Begin If InEq[iRule] = 0 then RuleVal = Open[DaysL[iRule]] >= Low[DaysR[iRule]] else if InEq[iRule] = 1 then RuleVal = Open[DaysL[iRule]] <= Low[DaysR[iRule]]; end else if PriceR[iRule] = 3 then Begin If InEq[iRule] = 0 then RuleVal = Open[DaysL[iRule]] >= Close[DaysR[iRule]] else if InEq[iRule] = 1 then RuleVal = Open[DaysL[iRule]] <= Close[DaysR[iRule]]; end; end else if PriceL[iRule] = 1 then Begin If PriceR[iRule] = 0 then Begin If InEq[iRule] = 0 then RuleVal = High[DaysL[iRule]] >= Open[DaysR[iRule]] else if InEq[iRule] = 1 then RuleVal = High[DaysL[iRule]] <= Open[DaysR[iRule]]; end else if PriceR[iRule] = 1 then Begin If InEq[iRule] = 0 then RuleVal = High[DaysL[iRule]] >= High[DaysR[iRule]] else if InEq[iRule] = 1 then RuleVal = High[DaysL[iRule]] <= High[DaysR[iRule]]; end else if PriceR[iRule] = 2 then Begin If InEq[iRule] = 0 then RuleVal = High[DaysL[iRule]] >= Low[DaysR[iRule]] else if InEq[iRule] = 1 then RuleVal = High[DaysL[iRule]] <= Low[DaysR[iRule]]; end else if PriceR[iRule] = 3 then Begin If InEq[iRule] = 0 then RuleVal = High[DaysL[iRule]] >= Close[DaysR[iRule]] else if InEq[iRule] = 1 then RuleVal = High[DaysL[iRule]] <= Close[DaysR[iRule]]; end; end else if PriceL[iRule] = 2 then Begin If PriceR[iRule] = 0 then Begin If InEq[iRule] = 0 then RuleVal = Low[DaysL[iRule]] >= Open[DaysR[iRule]] else if InEq[iRule] = 1 then RuleVal = Low[DaysL[iRule]] <= Open[DaysR[iRule]]; end else if PriceR[iRule] = 1 then Begin If InEq[iRule] = 0 then RuleVal = Low[DaysL[iRule]] >= High[DaysR[iRule]] else if InEq[iRule] = 1 then RuleVal = Low[DaysL[iRule]] <= High[DaysR[iRule]]; end else if PriceR[iRule] = 2 then Begin If InEq[iRule] = 0 then RuleVal = Low[DaysL[iRule]] >= Low[DaysR[iRule]] else if InEq[iRule] = 1 then RuleVal = Low[DaysL[iRule]] <= Low[DaysR[iRule]]; end else if PriceR[iRule] = 3 then Begin If InEq[iRule] = 0 then RuleVal = Low[DaysL[iRule]] >= Close[DaysR[iRule]] else if InEq[iRule] = 1 then RuleVal = Low[DaysL[iRule]] <= Close[DaysR[iRule]]; end; end else if PriceL[iRule] = 3 then Begin If PriceR[iRule] = 0 then Begin If InEq[iRule] = 0 then RuleVal = Close[DaysL[iRule]] >= Open[DaysR[iRule]] else if InEq[iRule] = 1 then RuleVal = Close[DaysL[iRule]] <= Open[DaysR[iRule]]; end else if PriceR[iRule] = 1 then Begin If InEq[iRule] = 0 then RuleVal = Close[DaysL[iRule]] >= High[DaysR[iRule]] else if InEq[iRule] = 1 then RuleVal = Close[DaysL[iRule]] <= High[DaysR[iRule]]; end else if PriceR[iRule] = 2 then Begin If InEq[iRule] = 0 then RuleVal = Close[DaysL[iRule]] >= Low[DaysR[iRule]] else if InEq[iRule] = 1 then RuleVal = Close[DaysL[iRule]] <= Low[DaysR[iRule]]; end else if PriceR[iRule] = 3 then Begin If InEq[iRule] = 0 then RuleVal = Close[DaysL[iRule]] >= Close[DaysR[iRule]] else if InEq[iRule] = 1 then RuleVal = Close[DaysL[iRule]] <= Close[DaysR[iRule]]; end; end; EvalPattern = RuleVal; { Function: WriteSystem Write EasyLanguage code for the price pattern-based system to a text file. Mike Bryant Breakout Futures www.BreakoutFutures.com mrb@BreakoutFutures.com Copyright 2007 Breakout Futures } Inputs: SysNum (NumericSimple), { System number } TradeDir (NumericSimple), { trade direction } PriceL[max1] (NumericArrayRef), { Array of left-hand prices } PriceR[max2] (NumericArrayRef), { Array of right-hand prices } InEq[max3] (NumericArrayRef), { Array of inequality signs } DaysL[max4] (NumericArrayRef), { Array of days back, left side } DaysR[max5] (NumericArrayRef), { Array of days back, right side } NRules (NumericSimple), { Number of rules/patterns } NBarExit (NumericSimple), { Number of bars until exit } FName (StringSimple); { file name to write to } Var: StrOut (""), { output character string } ii (0), { loop counter } ProfFac (0); { profit factor } If AbsValue(GrossLoss) > 0 then ProfFac = GrossProfit/AbsValue(GrossLoss) else ProfFac = 100; If TradeDir > 0 then StrOut = "System " + NumtoStr(SysNum, 0) + ", " + GetSymbolName + ", " + DateString3(CurrentDate, CurrentTime) + ", Long Trades" + NewLine else if TradeDir < 0 then StrOut = "System " + NumtoStr(SysNum, 0) + ", " + GetSymbolName + ", " + DateString3(CurrentDate, CurrentTime) + ", Short Trades" + NewLine; FileAppend(FName, StrOut); StrOut = " Net Profit = " + NumtoStr(NetProfit, 2) + ", Max DD = " + NumtoStr(MaxIDDrawDown, 2) + ", Num Trades = " + NumtoStr(TotalTrades, 0) + ", Percent Wins = " + NumtoStr(PercentProfit, 2) + ", Prof factor = " + NumtoStr(ProfFac, 3) + Newline; FileAppend(FName, StrOut); StrOut = "{ System code starts here... }" + NewLine; FileAppend(FName, StrOut); StrOut = "Var: EntNext (false);" + NewLine; FileAppend(FName, StrOut); StrOut = ""; For ii = 0 to NRules - 1 Begin If PriceL[ii] = 0 then Begin If PriceR[ii] = 0 then Begin If InEq[ii] = 0 then StrOut = StrOut + "Open[" + NumtoStr(DaysL[ii], 0) + "] >= Open[" + NumtoStr(DaysR[ii], 0) + "]" else if InEq[ii] = 1 then StrOut = StrOut + "Open[" + NumtoStr(DaysL[ii], 0) + "] <= Open[" + NumtoStr(DaysR[ii], 0) + "]"; end else if PriceR[ii] = 1 then Begin If InEq[ii] = 0 then StrOut = StrOut + "Open[" + NumtoStr(DaysL[ii], 0) + "] >= High[" + NumtoStr(DaysR[ii], 0) + "]" else if InEq[ii] = 1 then StrOut = StrOut + "Open[" + NumtoStr(DaysL[ii], 0) + "] <= High[" + NumtoStr(DaysR[ii], 0) + "]"; end else if PriceR[ii] = 2 then Begin If InEq[ii] = 0 then StrOut = StrOut + "Open[" + NumtoStr(DaysL[ii], 0) + "] >= Low[" + NumtoStr(DaysR[ii], 0) + "]" else if InEq[ii] = 1 then StrOut = StrOut + "Open[" + NumtoStr(DaysL[ii], 0) + "] <= Low[" + NumtoStr(DaysR[ii], 0) + "]"; end else if PriceR[ii] = 3 then Begin If InEq[ii] = 0 then StrOut = StrOut + "Open[" + NumtoStr(DaysL[ii], 0) + "] >= Close[" + NumtoStr(DaysR[ii], 0) + "]" else if InEq[ii] = 1 then StrOut = StrOut + "Open[" + NumtoStr(DaysL[ii], 0) + "] <= Close[" + NumtoStr(DaysR[ii], 0) + "]"; end; end else if PriceL[ii] = 1 then Begin If PriceR[ii] = 0 then Begin If InEq[ii] = 0 then StrOut = StrOut + "High[" + NumtoStr(DaysL[ii], 0) + "] >= Open[" + NumtoStr(DaysR[ii], 0) + "]" else if InEq[ii] = 1 then StrOut = StrOut + "High[" + NumtoStr(DaysL[ii], 0) + "] <= Open[" + NumtoStr(DaysR[ii], 0) + "]"; end else if PriceR[ii] = 1 then Begin If InEq[ii] = 0 then StrOut = StrOut + "High[" + NumtoStr(DaysL[ii], 0) + "] >= High[" + NumtoStr(DaysR[ii], 0) + "]" else if InEq[ii] = 1 then StrOut = StrOut + "High[" + NumtoStr(DaysL[ii], 0) + "] <= High[" + NumtoStr(DaysR[ii], 0) + "]"; end else if PriceR[ii] = 2 then Begin If InEq[ii] = 0 then StrOut = StrOut + "High[" + NumtoStr(DaysL[ii], 0) + "] >= Low[" + NumtoStr(DaysR[ii], 0) + "]" else if InEq[ii] = 1 then StrOut = StrOut + "High[" + NumtoStr(DaysL[ii], 0) + "] <= Low[" + NumtoStr(DaysR[ii], 0) + "]"; end else if PriceR[ii] = 3 then Begin If InEq[ii] = 0 then StrOut = StrOut + "High[" + NumtoStr(DaysL[ii], 0) + "] >= Close[" + NumtoStr(DaysR[ii], 0) + "]" else if InEq[ii] = 1 then StrOut = StrOut + "High[" + NumtoStr(DaysL[ii], 0) + "] <= Close[" + NumtoStr(DaysR[ii], 0) + "]"; end; end else if PriceL[ii] = 2 then Begin If PriceR[ii] = 0 then Begin If InEq[ii] = 0 then StrOut = StrOut + "Low[" + NumtoStr(DaysL[ii], 0) + "] >= Open[" + NumtoStr(DaysR[ii], 0) + "]" else if InEq[ii] = 1 then StrOut = StrOut + "Low[" + NumtoStr(DaysL[ii], 0) + "] <= Open[" + NumtoStr(DaysR[ii], 0) + "]"; end else if PriceR[ii] = 1 then Begin If InEq[ii] = 0 then StrOut = StrOut + "Low[" + NumtoStr(DaysL[ii], 0) + "] >= High[" + NumtoStr(DaysR[ii], 0) + "]" else if InEq[ii] = 1 then StrOut = StrOut + "Low[" + NumtoStr(DaysL[ii], 0) + "] <= High[" + NumtoStr(DaysR[ii], 0) + "]"; end else if PriceR[ii] = 2 then Begin If InEq[ii] = 0 then StrOut = StrOut + "Low[" + NumtoStr(DaysL[ii], 0) + "] >= Low[" + NumtoStr(DaysR[ii], 0) + "]" else if InEq[ii] = 1 then StrOut = StrOut + "Low[" + NumtoStr(DaysL[ii], 0) + "] <= Low[" + NumtoStr(DaysR[ii], 0) + "]"; end else if PriceR[ii] = 3 then Begin If InEq[ii] = 0 then StrOut = StrOut + "Low[" + NumtoStr(DaysL[ii], 0) + "] >= Close[" + NumtoStr(DaysR[ii], 0) + "]" else if InEq[ii] = 1 then StrOut = StrOut + "Low[" + NumtoStr(DaysL[ii], 0) + "] <= Close[" + NumtoStr(DaysR[ii], 0) + "]"; end; end else if PriceL[ii] = 3 then Begin If PriceR[ii] = 0 then Begin If InEq[ii] = 0 then StrOut = StrOut + "Close[" + NumtoStr(DaysL[ii], 0) + "] >= Open[" + NumtoStr(DaysR[ii], 0) + "]" else if InEq[ii] = 1 then StrOut = StrOut + "Close[" + NumtoStr(DaysL[ii], 0) + "] <= Open[" + NumtoStr(DaysR[ii], 0) + "]"; end else if PriceR[ii] = 1 then Begin If InEq[ii] = 0 then StrOut = StrOut + "Close[" + NumtoStr(DaysL[ii], 0) + "] >= High[" + NumtoStr(DaysR[ii], 0) + "]" else if InEq[ii] = 1 then StrOut = StrOut + "Close[" + NumtoStr(DaysL[ii], 0) + "] <= High[" + NumtoStr(DaysR[ii], 0) + "]"; end else if PriceR[ii] = 2 then Begin If InEq[ii] = 0 then StrOut = StrOut + "Close[" + NumtoStr(DaysL[ii], 0) + "] >= Low[" + NumtoStr(DaysR[ii], 0) + "]" else if InEq[ii] = 1 then StrOut = StrOut + "Close[" + NumtoStr(DaysL[ii], 0) + "] <= Low[" + NumtoStr(DaysR[ii], 0) + "]"; end else if PriceR[ii] = 3 then Begin If InEq[ii] = 0 then StrOut = StrOut + "Close[" + NumtoStr(DaysL[ii], 0) + "] >= Close[" + NumtoStr(DaysR[ii], 0) + "]" else if InEq[ii] = 1 then StrOut = StrOut + "Close[" + NumtoStr(DaysL[ii], 0) + "] <= Close[" + NumtoStr(DaysR[ii], 0) + "]"; end; end; If ii < NRules - 1 then StrOut = StrOut + " and" + NewLine + " " else StrOut = StrOut + ";" + NewLine; End; StrOut = "EntNext = " + StrOut; FileAppend(FName, StrOut); StrOut = "If EntNext then" + NewLine; FileAppend(FName, StrOut); If TradeDir > 0 then StrOut = " Buy next bar at market;" + NewLine else if TradeDir < 0 then StrOut = " Sell short next bar at market;" + NewLine ; FileAppend(FName, StrOut); StrOut = "If BarsSinceEntry = " + NumtoStr(NBarExit, 0) + " then" + NewLine; FileAppend(FName, StrOut); If TradeDir > 0 then StrOut = " Sell next bar at market;" + NewLine else if TradeDir < 0 then StrOut = " Buy to cover next bar at market;" + NewLine ; FileAppend(FName, StrOut); StrOut = "{ End system code }" + NewLine + NewLine; FileAppend(FName, StrOut); WriteSystem = true; { Function: GetRandomInt(LowNum, HighNum) Return a random integer between the range [LowNum, HighNum] (inclusive). Mike Bryant Breakout Futures www.BreakoutFutures.com mrb@BreakoutFutures.com Copyright 2007 Breakout Futures } Inputs: LowNum (NumericSimple), { Lower bound of number to return } HighNum (NumericSimple); { Upper bound of number to return } Var: RawRandom (0), { system-provided number } IntValue (0); RawRandom = Random(HighNum - LowNum) + LowNum; IntValue = Round(RawRandom, 0); GetRandomInt = MaxList(MinList(IntValue, HighNum), LowNum); [LegacyColorValue = true]; { User function: DateString3(DateVal, TimeVal) Returns input DateVal (EasyLanguage date) and TimeVal (24 hour time) as a text string in the format mm/dd/yyyy HH:MM:SS. Omega Research solved their y2k problem by changing the year to 3 digits (e.g., 1999 = "99", 2000 = "100", 2001 = "101", etc). This function creates a 4 digit year by adding 1900 to the 3 digit year. This works for years greater than or equal to 1900. Michael R. Bryant Breakout Futures www.BreakoutFutures.com mrb@BreakoutFutures.com Copyright 2006 Breakout Futures } Input: DateVal (NumericSimple), TimeVal (NumericSimple); Var: TextString (""), YearNum (0), Hour (0), Minutes (0), MinStr (""); If DateVal > 0 and Year(DateVal) >= 0 then Begin TextString = NumToStr(Month(DateVal), 0) + "/"; TextString = TextString + NumToStr(DayofMonth(DateVal), 0) + "/"; YearNum = Year(DateVal) + 1900; TextString = TextString + NumToStr(YearNum, 0); Hour = IntPortion(TimeVal/100.); Minutes = TimeVal - (100 * Hour); if Minutes < 10 then MinStr = "0" + NumToStr(Minutes, 0) else MinStr = NumToStr(Minutes, 0); TextString = TextString + " " + NumToStr(Hour, 0) + ":" + MinStr + ":" + "00"; end else TextString = "NA"; DateString3 = TextString;