Mike, Thanks but I am not able to evaluate the result. Otherwise, yes, I would have done something similar to what you propose.
The actual ConditionGenerator() is a compiled C++ program that is implemented as a plugin to AmiBroker. It only returns strings, and hence I need to use an Include file as there is no other way (that I can think of) to evaluate the string. Reprogramming the C++ would be a big task, so I am trying to find a way to implement the AB side AFL correctly. --- In [email protected], "Mike" <sfclimb...@...> wrote: > > Ozzy, > > In your more complex implementation of your condition generation, are > you able to actually evaluate the result, rather than writing AFL to > a file? > > In the example you've given, I see no reason why you couldn't just > have the function return the result of the evaluation (without > bothering at all with any variables) as shown below. The example > below gives the same results as your hard coded working version. > > In other words, rather than generate strings, go ahead and evaluate > what you would have generated. The actual values are preserved in the > Score property of the trade. So, you no longer need a variable from > which to recall the value later. > > Mike > > //--------------------------------------------------------- > // FUNCTION: ConditionGenerator() > // > // When called, this function calculates buying > // conditions based on a simple algorithm. > // > // For e.g. ConditionGenerator(2) calculates: > // > // C > Ref(C, -2) AND Cross(C, MA(C,4) ) > //--------------------------------------------------------- > > function ConditionGenerator( X ) > { > local Y; > > Y = X * 2; > return ( C > Ref( C, -X ) AND Cross( C, MA( C, Y ) ) ); > } > > //-------------------------------------------------------- > // BACKTEST SOME CONDITIONS: > //-------------------------------------------------------- > > Buy = Sell = Short = Cover = PositionScore = 0; > > for ( a = 1; a < 10; a++ ) > { > Condition = ConditionGenerator( a ); > Buy = Buy OR Condition; > > // Reserved variable "PositionScore" is used to store the > // Condition numbers whenever a Condition is True: > > PositionScore = IIf( Condition AND NOT PositionScore, a, > PositionScore ); > } > > Buy = ExRemSpan( Buy, 12 ); > Sell = Ref( Buy, -12 ); > > > //-------------------------------------------------------- > // ADD THE CUSTOM COLUMN, "CONDITION" TO BACKTEST REPORT > //-------------------------------------------------------- > > SetCustomBacktestProc( "" ); > > if ( Status( "action" ) == actionPortfolio ) > { > bo = GetBacktesterObject(); > > bo.Backtest( 1 ); // run default backtest procedure iterate > through closed trades first > > for ( trade = bo.GetFirstTrade(); trade; trade = bo.GetNextTrade > () ) > { > trade.AddCustomMetric( "Condition", trade.Score ); > } > > bo.ListTrades(); > } > > --- In [email protected], "ozzyapeman" <zoopfree@> wrote: > > > > Hello, I got some great help from Mike (sfclimbers) in solving the > first > > half of this problem, of cycling through a group of Buy conditions, > > adding a custom metric, and identifying conditions per trade . > Thought > > all my issues were completely solved, but ran into an unexpected > > stumbling block when I tried to apply it to my actual trading > system, > > which makes extensive use of Include files, and string generating > > algorithms. Hoping someone can help in pointing out my error (maybe > even > > Mike if he ain't tired of me yet ;-) First, here is a block of code > that > > *does* work, and gives the simple essence of what I want to achieve. > > This system outlines 9 different conditions, cycles through all in a > > backtest, and adds a column to the backtester to indicate which > > Condition was used for which trade: > > > > > > //-------------------------------------------------------- > > // SIMPLE TRADING SYSTEM BASED ON VARIOUS CONDITIONS > > //-------------------------------------------------------- > > > > > > Condition1 = C > Ref(C, -1) AND Cross(C, MA(C,2) ); > > Condition2 = C > Ref(C, -2) AND Cross(C, MA(C,4) ); > > Condition3 = C > Ref(C, -3) AND Cross(C, MA(C,6) ); > > Condition4 = C > Ref(C, -4) AND Cross(C, MA(C,8) ); > > Condition5 = C > Ref(C, -5) AND Cross(C, MA(C,10) ); > > Condition6 = C > Ref(C, -6) AND Cross(C, MA(C,12) ); > > Condition7 = C > Ref(C, -7) AND Cross(C, MA(C,14) ); > > Condition8 = C > Ref(C, -8) AND Cross(C, MA(C,16) ); > > Condition9 = C > Ref(C, -9) AND Cross(C, MA(C,18) ); > > > > > > > > //-------------------------------------------------------- > > // BACKTEST THE ABOVE GROUP OF CONDITIONS: > > //-------------------------------------------------------- > > > > Buy = Sell = Short = Cover = PositionScore = 0; > > > > for ( a = 1; a < 10; a++ ) > > { > > Condition = VarGet( "Condition" + NumToStr( a, 1.0, 0 ) ); > > > > Buy = Buy OR Condition; > > > > // Reserved variable "PositionScore" is used to store the > > // Condition numbers whenever a Condition is True: > > > > PositionScore = IIf( Condition AND NOT PositionScore, a, > PositionScore > > ); > > } > > > > Buy = ExRemSpan(Buy, 12); > > Sell = Ref(Buy, -12); > > > > > > > > //-------------------------------------------------------- > > // ADD THE CUSTOM COLUMN, "CONDITION" TO BACKTEST REPORT > > //-------------------------------------------------------- > > > > SetCustomBacktestProc( "" ); > > > > if ( Status( "action" ) == actionPortfolio ) > > { > > bo = GetBacktesterObject(); > > > > bo.Backtest( 1 ); // run default backtest procedure > > > > // iterate through closed trades first > > > > for ( trade = bo.GetFirstTrade(); trade; trade = bo.GetNextTrade > > () ) > > { > > trade.AddCustomMetric( "Condition", trade.Score ); > > } > > bo.ListTrades(); > > } > > > > Now in my actual trading system, I rely on a rather complex > algorithm, > > to generate "Conditions" on the fly. Each such variable assignment > is > > generated as a block of code, a few lines long, in string format. > If I > > wanted to test out a handful of such conditions, it's no problem to > > simply paste the variable assignments directly into the AFL. > However, > > when I want to cycle through thousands of such conditions, pasting > does > > not work. Amibroker understandbly crashes. So the solution is to > > generate each variable assignment, one at a time, and dump to an > > external file which is #Included into the main AFL. At any one > time, the > > external file only contains a single variable assignment. The > problem > > arises when I loop through the external file. Only the last > Condition is > > ever recognized as a Buy. I've tried using interim static > variables, and > > AddToComposite to store true/false data for each condition, and test > > against that. But nothing seems to work. Below is the basic code. > Note > > that the function ConditionGenerator() is not the one in my actual > > trading system, but a much more simplified version for debug > purposes. > > > > As mentioned, only Condition9 ever gets set as a Buy in the backtest > > report. How do I get *all* conditions to be properly tested for > > potential Buys, so that this block of code essentially mimics the > above > > block? (note you may first have to create a blank file on your > drive, > > "c:\\ConditionsFile.afl" before running the code). > > > > > > //--------------------------------------------------------- > > // FUNCTION: ConditionGenerator() > > // > > // When called, this function generators buying > > // conditions, as a string, based on a simple algorithm. > > // > > // For e.g. ConditionGenerator(2) results in: > > // > > // " Condition2 = C > Ref(C, -2) AND Cross(C, MA(C,4) ); " > > //--------------------------------------------------------- > > > > function ConditionGenerator(X) > > { > > Y = X * 2; > > > > string = "Condition"+ NumToStr(X, 1.0,0) +" = C > Ref(C, -" > > + NumToStr(X, 1.0,0)+ ") AND " > > + "Cross(C, MA(C,"+NumToStr(Y, 1.0,0) + ") );" ; > > > > return string; > > } > > //-------------------------------------------------------- > > > > > > > > > > //-------------------------------------------------------- > > // BACKTEST SOME CONDITIONS: > > // > > // Want to backtest a group of 9 Conditions > > // > > // So we dump to an Include file and cycle through > > // the conditions against historical data > > //-------------------------------------------------------- > > > > #include "c:\\ConditionsFile.afl"; > > > > Buy = Sell = Short = Cover = PositionScore = 0; > > > > for ( a = 1; a < 10; a++ ) > > { > > fh = fopen( "c:\\ConditionsFile.afl", "w"); > > fputs(ConditionGenerator(a), fh); > > fclose( fh ); > > > > Condition = VarGet( "Condition" + NumToStr( a, 1.0, 0 ) ); > > > > Buy = Buy OR Condition; > > > > PositionScore = IIf( Condition AND NOT PositionScore, a, > PositionScore > > ); > > > > Buy = ExRemSpan(Buy, 12); > > Sell = Ref(Buy, -12); > > } > > //-------------------------------------------------------- > > > > > > > > > > //-------------------------------------------------------- > > // ADD THE CUSTOM COLUMN, "CONDITION" TO BACKTEST REPORT > > //-------------------------------------------------------- > > > > SetCustomBacktestProc( "" ); > > > > if ( Status( "action" ) == actionPortfolio ) > > { > > bo = GetBacktesterObject(); > > > > bo.Backtest( 1 ); // run default backtest procedure > > > > // iterate through closed trades first > > > > for ( trade = bo.GetFirstTrade(); trade; trade = > > bo.GetNextTrade() ) > > { > > trade.AddCustomMetric( "Condition", trade.Score); > > } > > bo.ListTrades(); > > } > > >
