My Take on A Mega Script

Posted By: Anonymous

My Take on A Mega Script - 09/24/12 10:06

I had plans on trading the Z1 on a microlot but due to complications from FXCM it seems it is not such a good idea at this time. So I have decided to combine a couple of scripts I know inside out.

The script will include the trend and cycle trading scripts from the tutorials and hucks trend catcher.

Code:
// Workshop 6: Portfolio trading ///////////////////

function tradeTrend()
{
	TimeFrame = 1;
	var *Price = series(price());
	var *Trend = series(LowPass(Price,optimize(250,100,1000)));
	Stop = optimize(2,1,10) * ATR(100);
	
	if(strstr(Algo,":L") and valley(Trend)) 
		enterLong();
	else if(strstr(Algo,":S") and peak(Trend)) 
		enterShort();
}

function tradeCounterTrend()
{
	var *Price = series(price());
	var Threshold = optimize(1.0,0.5,2,0.1);
	var *DomPeriod = series(DominantPeriod(Price,30));
	var LowPeriod = LowPass(DomPeriod,500);
	var *HP = series(HighPass(Price,LowPeriod*optimize(1,0.5,2)));
	var *Signal = series(Fisher(HP,500));
	Stop = optimize(2,1,10) * ATR(100);

	if(strstr(Algo,":L") and crossUnder(Signal,-Threshold)) 
		enterLong(); 
	else if(strstr(Algo,":S") and crossOver(Signal,Threshold)) 
		enterShort();
}

function HuckTrend()
{
	TimeFrame = 1;
	var *Price = series(price());
	var *LP5 = series(LowPass(Price,5));
	var *LP10 = series(LowPass(Price,optimize(10,6,20))); 
	var *RSI10 = series(RSI(Price,10)); 
	Stop = optimize(5,1,10)*ATR(30);
	
	static int crossed = 0;
	if(crossOver(LP5,LP10))
		crossed = Delay;
	else if(crossUnder(LP5,LP10))
		crossed = -Delay;
		
	if(strstr(Algo,":L") and (crossed > 0 && crossOver(RSI10,50)) {
		enterLong();
		crossed = 0;
	} else if(strstr(Algo,":S") and (crossed < 0 && crossUnder(RSI10,50)) {
		enterShort();
		crossed = 0;
 	} else
		crossed -= sign(crossed);
}

function run()
{
	set(PARAMETERS+FACTORS+LOGFILE); // use optimized parameters and reinvestment factors
	BarPeriod = 240;	// 4 hour bars
	LookBack = 500;	// needed for Fisher()
	NumWFOCycles = 8; // activate WFO
	NumBarCycles = 4;	// 4 times oversampling
	
	if(ReTrain) {
		UpdateDays = 30;	// reload new price data from the server every 30 days
		SelectWFO = -1;	// select the last cycle for re-optimization
	}
	
// portfolio loop
	while(asset(loop("EUR/USD","USD/CHF","GBP/USD","AUD/USD","USD/CAD","USD/JPY","USD/NZD",)))
	while(algo(loop("TRND:L","TRND:S","CNTR:L","CNTR:S","HuckTrend:L","HuckTrend:S")))
	{
// set up the optimal margin
		if(Train)
			Lots = 1;
		else if(strstr(Algo,":L") and OptimalFLong > 0) {
			Lots = 1;			 
			Margin = clamp((WinLong-LossLong) * OptimalFLong/2, 50, 10000);
		} else if(strstr(Algo,":S") and OptimalFShort > 0) {
			Lots = 1;
			Margin = clamp((WinShort-LossShort) * OptimalFShort/2, 50, 10000);
		} else
			Lots = 0; // switch off trading

		if(strstr(Algo,"TRND")) 
			tradeTrend();
		else if(strstr(Algo,"CNTR")) 
			tradeCounterTrend();
	}
	
	PlotWidth = 1000;
	PlotHeight1 = 320;
}



Script wont comply, can someone help me find the error?
Posted By: Gattaca

Re: My Take on A Mega Script - 09/24/12 10:31

The 'delay' variable is not declared.
Posted By: jcl

Re: My Take on A Mega Script - 09/24/12 10:46

When you get a message like this:

Error in 'line 44:
'Delay' undeclared identifier
> crossed = Delay; <

you'll know that you've forgotten to define the variable "Delay" before using it in line 44.
Posted By: jcl

Re: My Take on A Mega Script - 09/24/12 14:50

There's also another problem with this script.

I mentioned in the other thread that the "static" keyword keeps the content of the "crossed" variable even when the function is left. This is not desired here, because the HuckTrend() function is called many times in your portfolio script, every time with a different asset. Thus you need a different way to temporary store the content of "crossed" separately per asset.

There are 8 variables for this purpose, with the name SkillLong[0] ... SkillLong[7]. Instead of defining crossed as static, in a portfolio script you would write at the begin of the function

int crossed = SkillLong[0];

for loading the variable content from SkillLong[0]. And for storing it again after it was modified in the function, add this line at the end:

SkillLong[0] = crossed;

The "crossed" variable can now have a different content for any asset.
Posted By: Anonymous

Re: My Take on A Mega Script - 09/25/12 06:37

Will go over everything and try implementing it
Posted By: Anonymous

Re: My Take on A Mega Script - 09/26/12 15:13

Tried implementing the concepts and error again.
Code:
// Workshop 6: Portfolio trading ///////////////////

function tradeTrend()
{
	TimeFrame = 1;
	var *Price = series(price());
	var *Trend = series(LowPass(Price,optimize(250,100,1000)));
	Stop = optimize(2,1,10) * ATR(100);
	
	if(strstr(Algo,":L") and valley(Trend)) 
		enterLong();
	else if(strstr(Algo,":S") and peak(Trend)) 
		enterShort();
}

function tradeCounterTrend()
{
	var *Price = series(price());
	var Threshold = optimize(1.0,0.5,2,0.1);
	var *DomPeriod = series(DominantPeriod(Price,30));
	var LowPeriod = LowPass(DomPeriod,500);
	var *HP = series(HighPass(Price,LowPeriod*optimize(1,0.5,2)));
	var *Signal = series(Fisher(HP,500));
	Stop = optimize(2,1,10) * ATR(100);

	if(strstr(Algo,":L") and crossUnder(Signal,-Threshold)) 
		enterLong(); 
	else if(strstr(Algo,":S") and crossOver(Signal,Threshold)) 
		enterShort();
}

function HuckTrend()
{
	
	TimeFrame = 1;
	var *Price = series(price());
	var *LP5 = series(LowPass(Price,5));
	var *LP10 = series(LowPass(Price,optimize(10,6,20))); 
	var *RSI10 = series(RSI(Price,10)); 
	Stop = optimize(5,1,10)*ATR(30);
        int crossed = SkillLong[0]
	
	
	
	if(crossOver(LP5,LP10))
		crossed = Delay;
	else if(crossUnder(LP5,LP10))
		crossed = -Delay;
		
	if(strstr(Algo,":L") and (crossed > 0 && crossOver(RSI10,50)) {
		enterLong();
		crossed = 0;
	} else if(strstr(Algo,":S") and (crossed < 0 && crossUnder(RSI10,50)) {
		enterShort();
		crossed = 0;
 	} else
		SkillLong[0] = crossed;
}

function run()
{
	set(PARAMETERS+FACTORS+LOGFILE); // use optimized parameters and reinvestment factors
	BarPeriod = 240;	// 4 hour bars
	LookBack = 500;	// needed for Fisher()
	NumWFOCycles = 8; // activate WFO
	NumBarCycles = 4;	// 4 times oversampling
	
	if(ReTrain) {
		UpdateDays = 30;	// reload new price data from the server every 30 days
		SelectWFO = -1;	// select the last cycle for re-optimization
	}
	
// portfolio loop
	while(asset(loop("EUR/USD","USD/CHF","GBP/USD","AUD/USD","USD/CAD","USD/JPY","USD/NZD",)))
	while(algo(loop("TRND:L","TRND:S","CNTR:L","CNTR:S","HuckTrend:L","HuckTrend:S")))
	{
// set up the optimal margin
		if(Train)
			Lots = 1;
		else if(strstr(Algo,":L") and OptimalFLong > 0) {
			Lots = 1;			 
			Margin = clamp((WinLong-LossLong) * OptimalFLong/2, 50, 10000);
		} else if(strstr(Algo,":S") and OptimalFShort > 0) {
			Lots = 1;
			Margin = clamp((WinShort-LossShort) * OptimalFShort/2, 50, 10000);
		} else
			Lots = 0; // switch off trading

		if(strstr(Algo,"TRND")) 
			tradeTrend();
		else if(strstr(Algo,"CNTR")) 
			tradeCounterTrend();
		     else if(strstr(Algo,"HuckTrend")) 
			  HuckTrend();	
			
	}
	
	PlotWidth = 1000;
	PlotHeight1 = 320;
}

Posted By: Anonymous

Re: My Take on A Mega Script - 10/03/12 13:27

JCL I am having a hard time getting this to work. Can you please help me out?
Posted By: jcl

Re: My Take on A Mega Script - 10/04/12 07:15

You have still not defined the Delay variable

int Delay = 3;

and there's something garbled now at the end of your function. crossed must be decremented. That was correct in your previous code.
Posted By: Guiom

Re: My Take on A Mega Script - 10/08/12 09:18

Originally Posted By: liftoff
Tried implementing the concepts and error again.


I think that's the code for what you wanted to do, you had a missing ";" after int crossed = SkillLong[0], missing declaration of Delay and an extra "," at the end of while(asset(loop...))

I only tested/optimized with EURUSD and USDCHF and it took almost an hour and the result isn't interesting:
Profit 5934 MI 211 DD 6104 Capital 6861
Trades 218 Win 33% Avg +27.22 Bars 81
AR 37% PF 1.32 SR 0.47 UI 47.9% Error 35%

Code:
// Portfolio trading: Trend, Counter Trend and Huck Trend ///////////////////

function tradeTrend()
{
	TimeFrame = 1;
	var *Price = series(price());
	var *Trend = series(LowPass(Price,optimize(250,100,1000)));
	Stop = optimize(2,1,10) * ATR(100);
	
	if(strstr(Algo,":L") and valley(Trend)) 
		enterLong();
	else if(strstr(Algo,":S") and peak(Trend)) 
		enterShort();
}

function tradeCounterTrend()
{
	var *Price = series(price());
	var Threshold = optimize(1.0,0.5,2,0.1);
	var *DomPeriod = series(DominantPeriod(Price,30));
	var LowPeriod = LowPass(DomPeriod,500);
	var *HP = series(HighPass(Price,LowPeriod*optimize(1,0.5,2)));
	var *Signal = series(Fisher(HP,500));
	Stop = optimize(2,1,10) * ATR(100);

	if(strstr(Algo,":L") and crossUnder(Signal,-Threshold)) 
		enterLong(); 
	else if(strstr(Algo,":S") and crossOver(Signal,Threshold)) 
		enterShort();
}

function HuckTrend()
{
	
	TimeFrame = 1;
	var *Price = series(price());
	var *LP5 = series(LowPass(Price,5));
	var *LP10 = series(LowPass(Price,optimize(10,6,20))); 
	var *RSI10 = series(RSI(Price,10)); 
	Stop = optimize(5,1,10)*ATR(30);
   int crossed = SkillLong[0];
	int Delay = 3;
	
	
	if(crossOver(LP5,LP10))
		crossed = Delay;
	else if(crossUnder(LP5,LP10))
		crossed = -Delay;
		
	if(strstr(Algo,":L") and (crossed > 0 && crossOver(RSI10,50))) {
		enterLong();
		crossed = 0;
	} else if(strstr(Algo,":S") and (crossed < 0 && crossUnder(RSI10,50))) {
		enterShort();
		crossed = 0;
 	} else
		SkillLong[0] -= sign(crossed);
}

function run()
{
	set(PARAMETERS+FACTORS+LOGFILE); // use optimized parameters and reinvestment factors
	BarPeriod = 240;	// 4 hour bars
	LookBack = 500;	// needed for Fisher()
	NumWFOCycles = 8; // activate WFO
	NumBarCycles = 4;	// 4 times oversampling
	
	if(ReTrain) {
		UpdateDays = 30;	// reload new price data from the server every 30 days
		SelectWFO = -1;	// select the last cycle for re-optimization
	}
	
// portfolio loop
	while(asset(loop("EUR/USD","USD/CHF")))
	while(algo(loop("TRND:L","TRND:S","CNTR:L","CNTR:S","HuckTrend:L","HuckTrend:S")))
	{
// set up the optimal margin
		if(Train)
			Lots = 1;
		else if(strstr(Algo,":L") and OptimalFLong > 0) {
			Lots = 1;			 
			Margin = clamp((WinLong-LossLong) * OptimalFLong/2, 50, 10000);
		} else if(strstr(Algo,":S") and OptimalFShort > 0) {
			Lots = 1;
			Margin = clamp((WinShort-LossShort) * OptimalFShort/2, 50, 10000);
		} else
			Lots = 0; // switch off trading

		if(strstr(Algo,"TRND")) 
			tradeTrend();
		else if(strstr(Algo,"CNTR")) 
			tradeCounterTrend();
		     else if(strstr(Algo,"HuckTrend")) 
			  HuckTrend();	
			
	}
	
	PlotWidth = 1000;
	PlotHeight1 = 320;
}

Posted By: Anonymous

Re: My Take on A Mega Script - 10/08/12 13:46

Thank you mate. I did the corrections myself over the weekend and tested it... It didn't turn out too great. it was profitable but required too high a capital, I think something like 10,000.
Posted By: TankWolf

Re: My Take on A Mega Script - 11/15/12 03:27

I have another question in regards to the SkillLong variables, I just cant seem to work this out. This following code was posted to store the crossing for Hucks strategy.

Quote:

while(asset(loop("EUR/USD","GBP/USD",USD/CHF"))) {

int crossed = SkillLong[0];
int Delay = 3;


if(crossOver(LP5,LP10))
crossed = Delay;
else if(crossUnder(LP5,LP10))
crossed = -Delay;

if(crossed > 0 && crossOver(RSI10,50))) {
enterLong();
crossed = 0;
} else if(crossed < 0 && crossUnder(RSI10,50))) {
enterShort();
crossed = 0;
} else
SkillLong[0] -= sign(crossed);
}


Is this code correct for storing the cross on multiple assets? Because it doesnt seem so. The reason I dont think it is because when I run my strategy with just one asset Im getting no problems, however when I run multiple assets Im getting errors. So running through it we create a variable called crossed which is stored with the SkillLong[0] variable? Then we store the delay into the crossed variable? So does then mean that Delay has been stored in crossed or SkillLong[0]? And then should we be checking if SkillLong[0] > 0 or crossed > 0? Im super confused about how this works if jcl or someone could go the theory to thisagain Id really appreciate it.
Posted By: TankWolf

Re: My Take on A Mega Script - 11/15/12 05:20

Ok so I think I have answered my own question, been playing around for hours today and I finally just got the SkillLong version to match the static int one.

Quote:

while(asset(loop("EUR/USD","GBP/USD",USD/CHF"))) {

int crossed = SkillLong[0];
int Delay = 3;


if(crossOver(LP5,LP10))
SkillLong[0] = Delay;
else if(crossUnder(LP5,LP10))
SkillLong[0] = -Delay;

if(SkillLong[0] > 0 && crossOver(RSI10,50))) {
enterLong();
crossed = 0;
SkillLong[0] = crossed;
} else if(SkillLong[0] < 0 && crossUnder(RSI10,50))) {
enterShort();
crossed = 0;
SkillLong[0] = crossed;
} else
SkillLong[0] -= sign(crossed);
}


Ok so this is how I understand the theory. We create a variable called crossed and store SkillLong[0] into it. Then we store the Delay into SkillLong[0]. Next we check if SkillLong[0] > or < than 0. If it is trade is entered long or short. Then we store 0 back into crosssed and then store crossed back into SkillLong[0]. I got the same results running this code vs the static int crossed = 0 method on one asset so I assume its right. Any feedback or advice still would very much be appreciated.
Posted By: jcl

Re: My Take on A Mega Script - 11/15/12 09:50

This code seems to work, but it's not perfect - it looks too complicated. In programming, simpler and shorter is always better. I see no reason in your code for a "crossed" variable.

Code:
int Delay = 3;
if(crossOver(LP5,LP10))
  SkillLong[0] = Delay;
else if(crossUnder(LP5,LP10))
  SkillLong[0] = -Delay;

if(SkillLong[0] > 0 && crossOver(RSI10,50))) {
  enterLong();
  SkillLong[0] = 0;
} else if(SkillLong[0] < 0 && crossUnder(RSI10,50))) {
  enterShort();
  SkillLong[0] = 0;
} else
  SkillLong[0] -= sign(SkillLong[0]);



Here's an easier method without any SkillLong:

Code:
var *Signals = series(0);
if(crossOver(LP5,LP10))
  *Signals = 1;
else if(crossUnder(LP5,LP10))
  *Signals = -1;

if(Sum(Signals,3) > 0 && crossOver(RSI10,50)))
  enterLong();
else if(Sum(Signals,3) < 0 && crossUnder(RSI10,50)))
  enterShort();



This method to check if some signal happened within the last 3 bars is explained in Workshop 4:

http://zorro-trader.com/manual/en/tutorial_trade.htm
Posted By: Anonymous

Re: My Take on A Mega Script - 12/20/13 07:09

Well, its been over a year and I keep asking myself what I could have achieved if I had stuck with this. Well there is nothing to asking questions with what could have been.
Good thing is I have had sometime to learn the basics of programming and I am ready to give this one more serious try.
I can see some folks here have really stuck with this and they are better at scripting with the C lite variant... I hope they ll hold my hand and help me along as I try and get this working.

I was thinking of a way I could learn and get people involved and interested in helping me. What I came up with is translating the work of Art of Automation from babypips. ( http://www.babypips.com/blogs/art-of-automation )
I will be working my way backwards from his latest post. Pick the latest system he has reviewed and try and automate it using zorro and I will do a test to see how it fairs. I believe that will give me a set of useful systems worth working on for the next couple of months to keep me busy and learning.
So what do you guys think, a good idea?
Posted By: DMB

Re: My Take on A Mega Script - 12/20/13 10:30

I like this babypips blog. Lots of complete system descriptions to tinker with. Maybe using signal processing theory and WFO will give us an edge. We'll I will work through some after I am finished my current projects and share what I come up with.
Posted By: Anonymous

Re: My Take on A Mega Script - 12/20/13 17:58

Great to see you are on board. Based on the obstacles I faced the last time, I will definitely need all the help I can get.
Posted By: Anonymous

Re: My Take on A Mega Script - 12/23/13 08:16

So after doing some reading over the weekend, I believe I need to spend sometime going over the tutorials and merging them with dusktraders Design Process Approach.
I will therefore be detailing what I do and how I do it in this thread. Any one who comes along later can read through it and learn from my progression.
I will be starting out with the Trend Following Edge.
Posted By: DMB

Re: My Take on A Mega Script - 12/23/13 08:56

I am going to have a go at the Three Little Pigs system. It appears to have enough complication with multiple time frames to teach me something, and it could be adapted to signal processing theory pretty easily in a version 2. Maybe I will be done in the next two weeks. If not, it will be delayed as per my time restrictions. But we'll see what happens.
Posted By: Anonymous

Re: My Take on A Mega Script - 12/23/13 12:21

Step 1a: Goal: identify marginally-profitable edge
No WFO; No oversample; Simple Stop; Std entry

So in step one we test the trading logic naked to see if it has an edge. A straight backtest, no Oversampling, a simple stop with no defined appropriate logic. Std entry also follows the generic nature of the stop.

Code:
function run()
{
	//Parameters
  	set(PARAMETERS);
	StartDate = 20080101;
	EndDate = 20131220;
	BarPeriod = 60;
	
//edge trading logic
  var  BarsPassed = optimize(1000,500,1500,10); // refers to the barspassed to the LowPass function.
  
  vars Price = series(price());
  vars Trend = series(LowPass(Price,BarsPassed));

  Stop = 4*ATR(100); //simple stop level
    
  if(valley(Trend))
    enterLong(); //standard entry
  else if(peak(Trend))
    enterShort(); //standard entry
}



Code:
TF-e1 EUR/USD 2008..2013
Read TF-e1_EURUSD.par
Profit 438$  MI 6$  DD 138$  Capital 104$
Trades 464  Win 22%  Avg +12.4p  Bars 76
AR 73%  PF 1.41  SR 0.63  UI 20.0%  Error 38%



Running this simple code produces a return of over 73% meaning it has an edge or exploits some inefficiency in the market. I therefore proceed to 1b.

Step 1b: optimize the BarPeriod
I prefer longer time frames because it is my belief that they reduce errors in backtesting *belief based on no research*. I will let Zorro however test and tell me which barperiods produce the best results based on the current nature of the strategy.
I want to manually review the optimization chart for this step, so I hardcode the number of bars argument passed into the LowPass function, which I can do by getting the found-best values out of the Data/script.par file. The .par file tells me 810 is the best figure to use.

Training then with only 1 optimized parameter (the BarPeriod) will cause Zorro to produce the optimallity chart that I can use. I can see clearly from this chart that BarPeriod 60 is indeed the best of the bunch.
Code:
function run()
{
	//Parameters
  	set(PARAMETERS);
	StartDate = 20080101;
	EndDate = 20131220;
	BarPeriod = optimize(60,60,1440,60);
	
	//edge trading logic
  var  BarsPassed = 810; //optimize(810,500,1500, 10) ... refers to the barspassed to the LowPass function.
  
  vars Price = series(price());
  vars Trend = series(LowPass(Price,BarsPassed));

  Stop = 4*ATR(100); //simple stop level
    
  if(valley(Trend))
    enterLong(); //standard entry
  else if(peak(Trend))
    enterShort(); //standard entry
}


The graph does show that the system is profitable over a lot of time frames but the highest profit and number of trades is achieved when I use the one hour. So I will stick to that.


Step 1c: Goal: identify optimizable parameters
No WFO; No oversample; Simple Stop; Std entry
In this step, I want to focus on all the parameters that might play a role in the edge logic specifically. I need to try to keep a global view of my ultimate intent, which is to produce a multi-asset tradebot. The parameters that work for my current asset (I have started with EURUSD) may not be appropriate for other assets, so I want to give them the flexibility to move around for other asset personalities, and for market changes over time.

Therefore, ideally, I want to try to identify parameters that do affect core logic and give them flexibility to adjust (via Zorro's optimizer), but at the same time I want to constrain them based on a reasonable range that will be identified from the parameter optimization charts. Zorro will only produce an opt chart if I am optimizing 1 parameter, so I need to first hardcode the other parameters and then individually check each one to review its opt chart. With this strategy, the parameter that affects core logic is called BarPassed. The parameter should already be hardcoded from our last Step 1b, because we needed to do that in order to check that BarPeriod opt chart. So now I will hardcode BarPeriod back to 60 minutes, and select the first parameter to be optimized. (TIP: so that I don't forget what the original optimal parameter was, I set this value as the "start" value in the optimizer call.)

Code:
function run()
{
	//Parameters
  	set(PARAMETERS);
	StartDate = 20080101;
	EndDate = 20131220;
	BarPeriod = 60; // optimize(60,60,1440,60);
	
	//edge trading logic
  var  BarsPassed = 820; // optimize(820,500,1500, 10);
  
  vars Price = series(price());
  vars Trend = series(LowPass(Price,BarsPassed));

  Stop = 4*ATR(100); //simple stop level
    
  if(valley(Trend))
    enterLong(); //standard entry
  else if(peak(Trend))
    enterShort(); //standard entry
}





I initially set the "reasonable range" of the parameter BarsPassed to 750-1200, with the optimal value of 820 in the "start" position. Since this is the only logic parameter we are optimizing, I was not too comfortable putting such a narrow constraint on the parameter. I therefore left the range as it was initially.
I am done optimizing core-logic parameters, I now re-Train and re-Test. In multi-parameter Trains, Zorro only looks at one parameter at a time, and relies on the "start" value for all other parameters. Since we are optimizing only one parameter in this section mainly because of the nature of this code, we end up with basically the same returns.
Code:
function run()
{
	//Parameters
  	set(PARAMETERS);
	StartDate = 20080101;
	EndDate = 20131220;
	BarPeriod = 60; // optimize(60,60,1440,60);
	
	//edge trading logic
  var  BarsPassed = 820; // optimize(820,500,1500, 10);
  
  vars Price = series(price());
  vars Trend = series(LowPass(Price,BarsPassed));

  Stop = 4*ATR(100); //simple stop level
    
  if(valley(Trend))
    enterLong(); //standard entry
  else if(peak(Trend))
    enterShort(); //standard entry
}



Step 1d
No WFO; No oversample; Rev entry
In this step, I add the enhancements of reverseLong() and reverseShort() to replace the simple entries. These helper functions have special features that are desirable and explained in Workshop 5.

Also in this step, I perform the same optimization as in Step 1c, focusing specifically on the Stop. To find a good-working ATR value for this tradebot, I tested the following varieties before settling on ATR(200): 300, 200, 150, 100, 50, 25, 10. At this point I was thinking of just creating a new variable and setting it to pass optimized values to the
ATR function, but I was a bit hestitant as this might qualify as curve fitting. I will
look into the possibility when I improve at this.I settled on 200.
Here is the resultant code after all these adjustments:
Code:
function run()
{
	//Parameters
  	set(PARAMETERS);
	StartDate = 20080101;
	EndDate = 20131220;
	BarPeriod = 60; // optimize(60,60,1440,60);
	
	//edge trading logic
  var  BarsPassed = 820; // optimize(820,500,1500, 10);
  
  vars Price = series(price());
  vars Trend = series(LowPass(Price,BarsPassed));

  Stop = optimize(5,1,15,1,-5)*ATR(100);
    
  if(valley(Trend))
    //enterLong(); //standard entry
	   reverseLong(1);
  else if(peak(Trend))
    //enterShort(); //standard entry
		reverseShort(1);
}



Step 1e
Yes WFO; Yes oversample, Rev entry
In this step, I've added a variable to control maxtrades (a feature of the reverseLong() and reverseShort() helper functions). I can get an idea of how many trades the system might take from looking at the Performance Report on Step 1c. I will manually adjust the value up and down to determine how many trades are most appropriate.

Also in this step, I've added oversampling. This is described in the manual. I will use an oversampling value of 3.

Going by dusktraders findings, I will be using his if code to set oversampling on only during Test. To accommodate this, I add some code to make sure NumSampleCycles is never set during a Train, but always set during a Test.

Additionally, this step adds Rolling Walk-Forward-Optimization. I have added dusktradesrs code that warns me (and stops the Train) if it falls below a threshold of 30 trades per cycle.
Code:
function run()
{
	//Parameters
  	set(PARAMETERS);
	StartDate = 20080101;
	EndDate = 20131220;
	BarPeriod = 60; // optimize(60,60,1440,60);
	
	if(is(TESTMODE)) NumSampleCycles = 3; //oversampling on Test only, not Train
	if (Train) { RollLong = 0; RollShort = 0; } //help prevent asymmetry in parameters & profit factors
	DataSplit = 70; //70% training, 30% OOS test
	NumWFOCycles = 5;
	int maxtrades = 1;

	//require minimum 30 trades per WFO cycle or stop training
	static int LastWFOCycle = 0, LastNumTrades = 0;
	if(Train && (WFOCycle != LastWFOCycle) )
	{
		if(LastNumTrades > 0 and LastNumTrades < 30)
		{
			char tradecount[100];
			sprintf(tradecount,"Not enough trades per cycle: %d",LastNumTrades);
			quit(tradecount);
		}
		LastWFOCycle = WFOCycle;
	}
	LastNumTrades = NumWinTotal+NumLossTotal;
	
	//edge trading logic
  var  BarsPassed = 820; // optimize(820,500,1500, 10);
  
  vars Price = series(price());
  vars Trend = series(LowPass(Price,BarsPassed));

  Stop = optimize(5,1,15,1,-5)*ATR(100);
    
  if(valley(Trend))
   	   reverseLong(1);
  else if(peak(Trend))
   		reverseShort(1);
}


In this step, I am looking for only a "reasonable positive return", because future adjustments will have a major impact on profitability. As you can see, I'm incrementally changing the composition of the strategy. With each change, I check the Test result to make sure nothing has gone haywire (and backtrack if it does).
Code:
Walk-Forward Test: TF-e1 EUR/USD 2008..2013
Read TF-e1_EURUSD_1.par TF-e1_EURUSD_2.par TF-e1_EURUSD_3.par TF-e1_EURUSD_4.par
Profit 238$  MI 5$  DD 113$  Capital 106$
Trades 271  Win 24%  Avg +11.5p  Bars 82
AR 60%  PF 1.43  SR 0.63  UI 21.7%  Error 43%


Off to go grab a meal. I will be back to go through the next processes in a couple of hours. The reason I am doing this on here is to get the more advanced coders and traders to point out shortfalls in my reasoning in how I am adapting dusktraders approach. So all inputs are welcome.
Posted By: Anonymous

Re: My Take on A Mega Script - 12/23/13 20:22

Step 1f: Goal: identify modifiers that work well
Yes WFO; Yes oversample; Yes maxtrades; Yes all param optimizing; No emode

I believe the modifiers dusktrader have a potential of leading me to curve fit. I will therefore try to find economic or financial outlook reasons of why I think they should be applied before I include any of them. I will therefore pick them one after another and see if it should be included.

fridayClose()
Since this is a trend following strategy we hope to follow the trend as long as possible. So I will overlook this modifier,

hourOpen()
I dont think I will be needing this too.

todayOpenCombo()
I am a big believer in the markets being influenced by the big players to an extent. I therefore believe if trends are going to develop over the long term then the big boys are going to have to plan on how best to jump on it. A conspiracy nut over here, I know. I therefore see this tool as essential in reducing noise. I will therefore be including it.

todayCloseCombo()

marketOpenCombo()
As a conspiracy nut, I believe when the big boys are on a trade, they are ready to let it ride and more often than not this will be when they are in the market and when volume is there to ride. I will therefore be using this modifier.

Following dusktraders procedure:


1. DISABLE WFO temporarily (comment out the NumWFOCycles and DataSplit lines)

2. Hardcode all currently optimizable parameters. I do it this way, for example:
Code:
var TimeCycle = 64; //optimize(64,55,75,1,0);


3. Set an optimize on the first modifier to check, such as this:
Code:
int marketopencombo = optimize(1,1,15,1);


After viewing the optimality graph. I pick 3 as the default.
Code:
int dayopencombo = optimize(1,1,63,1);


After viewing the optimality graph, I pick 37 as the default.


I don't have any idea what the "estimated best start value" is yet, so I've used just 1. IMPORTANT: no other parameters should be set to optimize except the modifier at this stage.

4. Now tell Zorro to Train. It will recurse through each value of the modifier, as compared with the known-reasonable values that we hardcoded in all the other parameters. This produces a figure in the Zorro window after Train that can then become your "estimated best start value". I will now store this value in my script like this:
Code:
int marketopencombo = 15; //optimize(3,1,15,1);


Code:
int dayopencombo = 63; //optimize(37,1,63,1);



Shown here: 3 was the best value in that Train, so I'm recording that as part of my optimize statement. It is commented-out because my next step was to check the dayopecombo modifier. The value 63 in this case is the default "days" value for this particular modifier.

5. Go back and repeat for each optimizable modifier, starting from step #3. This will allow you to realize the "estimated best start value" for each optimizable modifier.

6. Don't forget to re-ENABLE the WFO that we disabled in step #1. Also re-ENABLE all core parameter and Stop/Trail optimization statements before proceeding.

So putting all this together... the strategy now looks like the one below, after identifying all the "estimated best start values" for each modifier. Rather than go by dusktraders route of having picking modifiers based on AR effect, I decided to use my understanding of the markets so I stick with these two modifiers.
Code:
function fridayClose(int fridayclose)
{
	//allows Friday trading up until NYSE 3pm; close trades and don't allow after this
	if(fridayclose && dow() == FRIDAY && lhour(ET) >= 15) 
		{
			exitLong("*");
			exitShort("*");
			return 1; //condition met; indicate no further trades
		}
	return 0; //condition not met; safe to take new trades
}
function hourOpen(int hourblockstart, int hourblockend)
{
	//blocks new open trades between selected hours
	//uses NYSE time, including DST
	if ( (lhour(ET) >= hourblockstart) && (lhour(ET) < hourblockend) )
		return 0; //between blocked hours, do not allow trade opens
	else
		return 1; //no conditions met, allow trades by default
}
function todayOpenCombo(var dayopencombo)
{
	//allows optimizer to specify the best combo of days for opens
	//bit position 0 = Monday
	//bit position 1 = Tuesday
	//bit position 2 = Wednesday
	//bit position 3 = Thursday
	//bit position 4 = Friday
	//bit position 5 = Sunday
	//given a combination #, the function will return whether
	//current dow() is in the combination

	int dayopencombobits = dayopencombo+.5; //truncate to rounded int
	int today = dow() - 1; //Mon is 0
	if (today == 6) today = 5; //bump Sun to 5 (no Sat, keep binary range 0-63)

	if (dayopencombobits & (1 << today)) return 1; //current dow() is in the combo
		else return 0; //current dow() not in combo, do not allow trade opens
}
function todayCloseCombo(var dayclosecombo)
{
	//allows optimizer to specify the best combo of days to close by NYSE 4pm
	//bit position 0 = Monday
	//bit position 1 = Tuesday
	//bit position 2 = Wednesday
	//bit position 3 = Thursday
	//bit position 4 = Friday
	//bit position 5 = Sunday
	//given a combination #, the function will determine if we are beyond
	//a combo close time, close all trades if necessary, and return 1
	//if no further trades allowed today

	int dayclosecombobits = dayclosecombo+.5; //truncate to rounded int
	int today = dow() - 1; //Mon is 0
	if (today == 6) today = 5; //bump Sun to 5 (no Sat, keep binary range 0-63)

	if ((dayclosecombobits & (1 << today)) && lhour(ET) >= 16) 
	{
		exitLong("*");
		exitShort("*");
		return 1; //current dow() is in the combo; indicate no further trades
	}
	else return 0; //current dow() not in combo, safe to take new trades
}
function marketOpenCombo(var marketopencombo)
{
	//allows optimizer to specify best markets to initiate trades
	//bit position 0 = New York 8am-5pm Eastern
	//bit position 1 = Sydney 5pm-2am Eastern
	//bit position 2 = Tokyo 7pm-4am Eastern
	//bit position 3 = London 3am-12pm Eastern
	//given a combination #, the function will determine if current time is within
	//a market part of the combination (returns 1 to allow trading if true)
	
	int marketcombobits = marketopencombo+.5; //truncate to rounded int
	if ( (lhour(ET) >=8) && (lhour(ET) <17) && (marketcombobits & (1 << 0)) ) return 1; //inside New York
	if ( (lhour(ET) >=17) || (lhour(ET) <2) && (marketcombobits & (1 << 1)) ) return 1; //inside Sydney
	if ( (lhour(ET) >=19) || (lhour(ET) <4) && (marketcombobits & (1 << 2)) ) return 1; //inside Tokyo
	if ( (lhour(ET) >=3) && (lhour(ET) <12) && (marketcombobits & (1 << 3)) ) return 1; //inside London
	return 0; //default - current market not in combination, don't allow trade opens
}
function checkModifiers()
{
	int reversedir = 0; //default normal trade direction (0) unless specified otherwise
	int fridayclose = 0; //enforce auto-close and no trades after NYSE 3pm Friday
	int hourblockstart = 0; //block trade opens beginning at NY hour
	int hourblockend = 0; //block trade opens ending at NY hour
	int dayopencombo = 63;//optimize(61,1,63,1); //combo of days to open; 63=every day
	int dayclosecombo = 0; //combo of days to close after NYSE 4pm; 0=none; 63=every day
	int marketopencombo = 15; //optimize(3,1,15,1); //combo of markets to allow trade opens; 15=every market

	if ( (!fridayClose(fridayclose) //close NYSE 3pm on Friday
		|| !todayCloseCombo(dayclosecombo) ) //close NYSE 4pm on selected days
		&& todayOpenCombo(dayopencombo) //open on selected days only
		&& marketOpenCombo(marketopencombo) //open during selected markets only
		&& hourOpen(hourblockstart,hourblockend) ) //open during selected hours only
			return 1; //ok to place new trades
	else
		return 0; //no trade, restricted by a modifier	
}
function run()
{
	//Parameters
  	set(PARAMETERS);
	StartDate = 20080101;
	EndDate = 20131220;
	BarPeriod = 60; // optimize(60,60,1440,60);
	int maxtrades = 1;
	
	if(is(TESTMODE)) NumSampleCycles = 3; //oversampling on Test only, not Train
	if (Train) { RollLong = 0; RollShort = 0; } //help prevent asymmetry in parameters & profit factors
	DataSplit = 70; //70% training, 30% OOS test
	NumWFOCycles = 5;
	int maxtrades = 1;

	//require minimum 30 trades per WFO cycle or stop training
	static int LastWFOCycle = 0, LastNumTrades = 0;
	if(Train && (WFOCycle != LastWFOCycle) )
	{
		if(LastNumTrades > 0 and LastNumTrades < 30)
		{
			char tradecount[100];
			sprintf(tradecount,"Not enough trades per cycle: %d",LastNumTrades);
			quit(tradecount);
		}
	LastWFOCycle = WFOCycle;
	}
	LastNumTrades = NumWinTotal+NumLossTotal;
	
	//edge trading logic
  var  BarsPassed = optimize(820,500,1500, 10);
  
  vars Price = series(price());
  vars Trend = series(LowPass(Price,BarsPassed));

  Stop = optimize(5,1,15,1,-5)*ATR(100);
   
  if (checkModifiers())
  {
  		if(valley(Trend))
   	   reverseLong(maxtrades);
 		else if(peak(Trend))
   		reverseShort(maxtrades);
  }
}


As you can see, I have not optimised any of the modifiers. I seem to have lost all the returns once I plugged in the modifiers. I will leave it as it is and investigate tomorrow. A really fun learning experience.
Posted By: Anonymous

Re: My Take on A Mega Script - 12/24/13 15:25

So we pick up from where we left of yesterday. I went over the process again and I seem to have propped up the average return to 47%. The current code stands as follows.
Code:
function fridayClose(int fridayclose)
{
	//allows Friday trading up until NYSE 3pm; close trades and don't allow after this
	if(fridayclose && dow() == FRIDAY && lhour(ET) >= 15) 
		{
			exitLong("*");
			exitShort("*");
			return 1; //condition met; indicate no further trades
		}
	return 0; //condition not met; safe to take new trades
}
function hourOpen(int hourblockstart, int hourblockend)
{
	//blocks new open trades between selected hours
	//uses NYSE time, including DST
	if ( (lhour(ET) >= hourblockstart) && (lhour(ET) < hourblockend) )
		return 0; //between blocked hours, do not allow trade opens
	else
		return 1; //no conditions met, allow trades by default
}
function todayOpenCombo(var dayopencombo)
{
	//allows optimizer to specify the best combo of days for opens
	//bit position 0 = Monday
	//bit position 1 = Tuesday
	//bit position 2 = Wednesday
	//bit position 3 = Thursday
	//bit position 4 = Friday
	//bit position 5 = Sunday
	//given a combination #, the function will return whether
	//current dow() is in the combination

	int dayopencombobits = dayopencombo+.5; //truncate to rounded int
	int today = dow() - 1; //Mon is 0
	if (today == 6) today = 5; //bump Sun to 5 (no Sat, keep binary range 0-63)

	if (dayopencombobits & (1 << today)) return 1; //current dow() is in the combo
		else return 0; //current dow() not in combo, do not allow trade opens
}
function todayCloseCombo(var dayclosecombo)
{
	//allows optimizer to specify the best combo of days to close by NYSE 4pm
	//bit position 0 = Monday
	//bit position 1 = Tuesday
	//bit position 2 = Wednesday
	//bit position 3 = Thursday
	//bit position 4 = Friday
	//bit position 5 = Sunday
	//given a combination #, the function will determine if we are beyond
	//a combo close time, close all trades if necessary, and return 1
	//if no further trades allowed today

	int dayclosecombobits = dayclosecombo+.5; //truncate to rounded int
	int today = dow() - 1; //Mon is 0
	if (today == 6) today = 5; //bump Sun to 5 (no Sat, keep binary range 0-63)

	if ((dayclosecombobits & (1 << today)) && lhour(ET) >= 16) 
	{
		exitLong("*");
		exitShort("*");
		return 1; //current dow() is in the combo; indicate no further trades
	}
	else return 0; //current dow() not in combo, safe to take new trades
}
function marketOpenCombo(var marketopencombo)
{
	//allows optimizer to specify best markets to initiate trades
	//bit position 0 = New York 8am-5pm Eastern
	//bit position 1 = Sydney 5pm-2am Eastern
	//bit position 2 = Tokyo 7pm-4am Eastern
	//bit position 3 = London 3am-12pm Eastern
	//given a combination #, the function will determine if current time is within
	//a market part of the combination (returns 1 to allow trading if true)
	
	int marketcombobits = marketopencombo+.5; //truncate to rounded int
	if ( (lhour(ET) >=8) && (lhour(ET) <17) && (marketcombobits & (1 << 0)) ) return 1; //inside New York
	if ( (lhour(ET) >=17) || (lhour(ET) <2) && (marketcombobits & (1 << 1)) ) return 1; //inside Sydney
	if ( (lhour(ET) >=19) || (lhour(ET) <4) && (marketcombobits & (1 << 2)) ) return 1; //inside Tokyo
	if ( (lhour(ET) >=3) && (lhour(ET) <12) && (marketcombobits & (1 << 3)) ) return 1; //inside London
	return 0; //default - current market not in combination, don't allow trade opens
}
function checkModifiers()
{
	int reversedir = 0; //default normal trade direction (0) unless specified otherwise
	int fridayclose = 0; //enforce auto-close and no trades after NYSE 3pm Friday
	int hourblockstart = 0; //block trade opens beginning at NY hour
	int hourblockend = 0; //block trade opens ending at NY hour
	int dayopencombo = optimize(61,1,63,1); //combo of days to open; 63=every day
	int dayclosecombo = optimize(29,1,63,1); //combo of days to close after NYSE 4pm; 0=none; 63=every day
	int marketopencombo = optimize(13,1,15,1); //combo of markets to allow trade opens; 15=every market

	if ( (!fridayClose(fridayclose) //close NYSE 3pm on Friday
		|| !todayCloseCombo(dayclosecombo) ) //close NYSE 4pm on selected days
		&& todayOpenCombo(dayopencombo) //open on selected days only
		&& marketOpenCombo(marketopencombo) //open during selected markets only
		&& hourOpen(hourblockstart,hourblockend) ) //open during selected hours only
			return 1; //ok to place new trades
	else
		return 0; //no trade, restricted by a modifier	
}


function run()
{
	//Parameters
  	set(PARAMETERS);
	StartDate = 20080101;
	EndDate = 20131220;
	BarPeriod = 60; //optimize(60,60,1440,60);
		
	if(is(TESTMODE)) NumSampleCycles = 6; //oversampling on Test only, not Train
	if (Train) { RollLong = 0; RollShort = 0; } //help prevent asymmetry in parameters & profit factors
	DataSplit = 70; //70% training, 30% OOS test
	NumWFOCycles = 5;
	int maxtrades = 1;

//	require minimum 30 trades per WFO cycle or stop training
	static int LastWFOCycle = 0, LastNumTrades = 0;
	if(Train && (WFOCycle != LastWFOCycle) )
	{
		if(LastNumTrades > 0 and LastNumTrades < 30)
		{
			char tradecount[100];
			sprintf(tradecount,"Not enough trades per cycle: %d",LastNumTrades);
			quit(tradecount);
		}
		LastWFOCycle = WFOCycle;
	}
	LastNumTrades = NumWinTotal+NumLossTotal;
	
	//edge trading logic
   var  BarsPassed = optimize(820,300,1300, 10);
  
   vars Price = series(price());
   vars Trend = series(LowPass(Price,BarsPassed));

   Stop = ATR(100)* optimize(3,1,6,1,-3); 
    
   if (checkModifiers())
   {
   	if(valley(Trend))
    		reverseLong(maxtrades);
   	else if(peak(Trend))
    		reverseShort(maxtrades);
	}
   
}



So I continue with the other steps.

Step 1g: Goal: determine if equity-curve trading would be helpful
Yes WFO; Yes oversample; Yes maxtrades; Yes all param optimizing; Yes best modifier(s); Yes emode
so as dusktrader advices, I will uncomment, train and test each one of the emodes.
For this strategy, emode 1 and emode 3 produce 109%, so I went with emode 1.

Step 2a: Goal: simulate actual margin and/or reinvestment
Yes rolling WFO; Yes oversample; Yes maxtrades; Yes all param optimizing; Yes modifier(s); Yes emode; Yes reinvest

So this step involves using optf to mathematically determine how good the bot has become. With this numeric evaluation, we can be more objective in comparing it to our other strategies.

So we first set the FACTOR flag on for calculating the optf figure
Code:
set(PARAMETERS+FACTORS);



We move from single lots to lots based on an account figure from now on. Meaning our margin is determined in relation to our starting capital. We are however not compounding.
The following code section lives just above the "edge trading logic" section:
Code:
//reinvest a portion of profits
	int reinvestprofits = 0; //invoke margin setting during trade logic
	Margin = 0; //default
	var MarginLong = 0; //default
	var MarginShort = 0; //default
	if (reinvestprofits)
	{
		Capital = 1000; //simulated account balance
		var riskCapital = 900; //basis to trade with
		if (OptimalF>.001) //profitable as compared to other assets
		{
			MarginLong = OptimalFLong * riskCapital;
			MarginShort = OptimalFShort * riskCapital;
		}
	}



And then just before our trade entry commands, I place this code:
Code:
if (reinvestprofits && MarginLong>0) Margin = MarginLong; else if(is(TRADEMODE)) Lots = -1;


Code:
if (reinvestprofits && MarginShort>0) Margin = MarginShort; else if(is(TRADEMODE)) Lots = -1;



So I train the strategy with reinvestment turned to 0 and turn it to true (1) and test the strategy.


The number of trades are really low. I have no idea why but I am guessing it has something to do with my code. Hopefully as I better grasp coding I can come back to this and find what is wrong.

Step 3a: Goal: identify best assets
Yes WFO; Yes oversample; Yes maxtrades; Yes all param optimizing; Yes best modifier(s); Yes emode; No reinvest
At this point I add other assets to the strategy. I was looking to add AUDUSD and NZDUSD but NZDUSD did not have the minimum 30 trades, so I set it aside and focused on EURUSD and AUDUSD. I turned reinvestment off, trained and tested.
Code:
Walk-Forward Test: TF-e1 portfolio 2008..2013
Can't open TF-e1.fac (rt)
Read TF-e1_1.par TF-e1_2.par TF-e1_3.par TF-e1_4.par
Profit 17$  MI 0$  DD 33$  Capital 39$
Trades 156  Win 44%  Avg +1.4p  Bars 7
AR 15%  PF 1.09  SR 0.22  UI 118.0%  Error 53%



With such a huge UI and error term, I have surely done something wrong.

Step 3b
Yes WFO; Yes oversample; Yes maxtrades; Yes all param optimizing; Yes best modifier(s); Yes emode; Yes reinvest; Yes multi-asset loop

So at this point I turn on reinvestment and test.
Code:
TF-e1 compiling................
Walk-Forward Test: TF-e1 portfolio 2008..2013
Can't open TF-e1.fac (rt)
Read TF-e1_1.par TF-e1_2.par TF-e1_3.par TF-e1_4.par
Profit 17$  MI 0$  DD 33$  Capital 48$
Trades 156  Win 44%  Avg +1.4p  Bars 7
CAGR 8%  PF 1.09  SR 0.20  UI 118.0%  Error 53%



I have definitely done a lot wrong along the way with such a huge Ulcer and error.
This is the code I ended up with.

Code:
function fridayClose(int fridayclose)
{
	//allows Friday trading up until NYSE 3pm; close trades and don't allow after this
	if(fridayclose && dow() == FRIDAY && lhour(ET) >= 15) 
		{
			exitLong("*");
			exitShort("*");
			return 1; //condition met; indicate no further trades
		}
	return 0; //condition not met; safe to take new trades
}
function hourOpen(int hourblockstart, int hourblockend)
{
	//blocks new open trades between selected hours
	//uses NYSE time, including DST
	if ( (lhour(ET) >= hourblockstart) && (lhour(ET) < hourblockend) )
		return 0; //between blocked hours, do not allow trade opens
	else
		return 1; //no conditions met, allow trades by default
}
function todayOpenCombo(var dayopencombo)
{
	//allows optimizer to specify the best combo of days for opens
	//bit position 0 = Monday
	//bit position 1 = Tuesday
	//bit position 2 = Wednesday
	//bit position 3 = Thursday
	//bit position 4 = Friday
	//bit position 5 = Sunday
	//given a combination #, the function will return whether
	//current dow() is in the combination

	int dayopencombobits = dayopencombo+.5; //truncate to rounded int
	int today = dow() - 1; //Mon is 0
	if (today == 6) today = 5; //bump Sun to 5 (no Sat, keep binary range 0-63)

	if (dayopencombobits & (1 << today)) return 1; //current dow() is in the combo
		else return 0; //current dow() not in combo, do not allow trade opens
}
function todayCloseCombo(var dayclosecombo)
{
	//allows optimizer to specify the best combo of days to close by NYSE 4pm
	//bit position 0 = Monday
	//bit position 1 = Tuesday
	//bit position 2 = Wednesday
	//bit position 3 = Thursday
	//bit position 4 = Friday
	//bit position 5 = Sunday
	//given a combination #, the function will determine if we are beyond
	//a combo close time, close all trades if necessary, and return 1
	//if no further trades allowed today

	int dayclosecombobits = dayclosecombo+.5; //truncate to rounded int
	int today = dow() - 1; //Mon is 0
	if (today == 6) today = 5; //bump Sun to 5 (no Sat, keep binary range 0-63)

	if ((dayclosecombobits & (1 << today)) && lhour(ET) >= 16) 
	{
		exitLong("*");
		exitShort("*");
		return 1; //current dow() is in the combo; indicate no further trades
	}
	else return 0; //current dow() not in combo, safe to take new trades
}
function marketOpenCombo(var marketopencombo)
{
	//allows optimizer to specify best markets to initiate trades
	//bit position 0 = New York 8am-5pm Eastern
	//bit position 1 = Sydney 5pm-2am Eastern
	//bit position 2 = Tokyo 7pm-4am Eastern
	//bit position 3 = London 3am-12pm Eastern
	//given a combination #, the function will determine if current time is within
	//a market part of the combination (returns 1 to allow trading if true)
	
	int marketcombobits = marketopencombo+.5; //truncate to rounded int
	if ( (lhour(ET) >=8) && (lhour(ET) <17) && (marketcombobits & (1 << 0)) ) return 1; //inside New York
	if ( (lhour(ET) >=17) || (lhour(ET) <2) && (marketcombobits & (1 << 1)) ) return 1; //inside Sydney
	if ( (lhour(ET) >=19) || (lhour(ET) <4) && (marketcombobits & (1 << 2)) ) return 1; //inside Tokyo
	if ( (lhour(ET) >=3) && (lhour(ET) <12) && (marketcombobits & (1 << 3)) ) return 1; //inside London
	return 0; //default - current market not in combination, don't allow trade opens
}
function checkModifiers()
{
	int reversedir = 0; //default normal trade direction (0) unless specified otherwise
	int fridayclose = 0; //enforce auto-close and no trades after NYSE 3pm Friday
	int hourblockstart = 0; //block trade opens beginning at NY hour
	int hourblockend = 0; //block trade opens ending at NY hour
	int dayopencombo = optimize(61,1,63,1); //combo of days to open; 63=every day
	int dayclosecombo = optimize(29,1,63,1); //combo of days to close after NYSE 4pm; 0=none; 63=every day
	int marketopencombo = optimize(13,1,15,1); //combo of markets to allow trade opens; 15=every market

	if ( (!fridayClose(fridayclose) //close NYSE 3pm on Friday
		|| !todayCloseCombo(dayclosecombo) ) //close NYSE 4pm on selected days
		&& todayOpenCombo(dayopencombo) //open on selected days only
		&& marketOpenCombo(marketopencombo) //open during selected markets only
		&& hourOpen(hourblockstart,hourblockend) ) //open during selected hours only
			return 1; //ok to place new trades
	else
		return 0; //no trade, restricted by a modifier	
}

function checkEquity(var emode)
{
	//emode 1 = standard: sets phantom/normal mode only (via Lots)
	//emode 2 = switch hitter: always in market (Lots=1), fades direction (via dir)
	//emode 3 = reward success with weighting: increase trades based on degree of improvement
	//emode 4 = mean reversion: trade when equity curve falls (Lots=1), sit out when it rises (Lots=-1)
	vars EquityCurve = series(EquityLong+EquityShort); //includes all phantom equity
	var dir; //indicates normal trade direction (dir=1) or reverse (dir=-1)

	//narrower curves
	//var slow = 50;
	//var fast = 10;

	//wider curves
	//var slow = 100;
	//var fast = 10;

	//mega-wide curves
	var slow = 200;
	var fast = 10;

	//uber-wide curves
	//var slow = 300;
	//var fast = 10;

	//optimized curves
	//var slow = optimize(50,50,300,12);
	//var fast = 10;

	vars EquityLP = series(LowPass(EquityCurve,fast));
	var EquityLPfalling = LowPass(EquityLP,slow);
	var EquityLPrisingBigger = LowPass(EquityLP,slow*3.2);
	var EquityLPrisingBig = LowPass(EquityLP,slow*1.5);
	plot("EquityLPslow",LowPass(EquityLP,slow),1,BLUE);
	plot("EquityLPfast",LowPass(EquityLP,fast),0,GREEN);
	
	if(EquityLP[0] < EquityLPfalling && falling(EquityLP)) { //drawdown
		if (emode==1) Lots = -1; //set phantom trade mode
		if (emode==2) return 1; //fade: take signals when losing
		if (emode==3) { //reward success with weighting
			Lots = -1; //set phantom trade mode
			return 1; //allow max 1 phantom trade in drawdown
		}
		if (emode==4) Lots = 1; //mean-reversion: start trading when equity curve falls
		
	}
	else { //positive equity curve
		if (emode==1) Lots = 1; //set normal trade mode
		if (emode==2) return -1; //fade: take reverse signals when winning
		if (emode==3) { //reward success with weighting
			Lots = 1; //set normal trade mode
			if (EquityLP[0] > EquityLPrisingBigger && rising(EquityLP)) return 3; //very big rising
			else if (EquityLP[0] > EquityLPrisingBig && rising(EquityLP)) return 2; //big rising
			else return 1; //rising but not yet significantly
		}
		if (emode==4) Lots = -1; //mean-reversion: stop trading when equity curve rises
	}
}

function run()
{
	//Parameters
  	set(PARAMETERS+FACTORS);
	StartDate = 20080101;
	EndDate = 20131220;
	BarPeriod = 60; //optimize(60,60,1440,60);
	LookBack = 600;
			
	if(is(TESTMODE)) NumSampleCycles = 6; //oversampling on Test only, not Train
	if (Train) { RollLong = 0; RollShort = 0; } //help prevent asymmetry in parameters & profit factors
	DataSplit = 70; //70% training, 30% OOS test
	NumWFOCycles = 5;
	int maxtrades = 1;

//	require minimum 30 trades per WFO cycle or stop training
	static int LastWFOCycle = 0, LastNumTrades = 0;
	if(Train && (WFOCycle != LastWFOCycle) )
	{
		if(LastNumTrades > 0 and LastNumTrades < 30)
		{
			char tradecount[100];
			sprintf(tradecount,"Not enough trades per cycle: %d",LastNumTrades);
			quit(tradecount);
		}
		LastWFOCycle = WFOCycle;
	}
	LastNumTrades = NumWinTotal+NumLossTotal;
		//equity-curve trading
	checkEquity(1); //emode 1: normal/phantom trading
	//reversedir = checkEquity(2); //emode 2: switch hitter
	//maxtrades = checkEquity(3); //emode 3: reward success
	//checkEquity(4); //emode 4: mean-reversion mode
	//reinvest a portion of profits
	
	while(asset(loop("EUR/USD","AUD/USD")))
	{
	
		int reinvestprofits = 1; //invoke margin setting during trade logic
		Margin = 1; //default
		var MarginLong = 0; //default
		var MarginShort = 0; //default
		if (reinvestprofits)
		{
			Capital = 50; //simulated account balance
			var riskCapital = 40; //basis to trade with
			if (OptimalF>.001) //profitable as compared to other assets
			{
				MarginLong = OptimalFLong * riskCapital;
				MarginShort = OptimalFShort * riskCapital;
			}
		}
		
		//edge trading logic
	   var  BarsPassed = optimize(820,300,1300, 10);
	  
	   vars Price = series(price());
	   vars Trend = series(LowPass(Price,BarsPassed));
	
	   Stop = ATR(100)* optimize(3,1,6,1,-3); 
	    
	   if (checkModifiers())
	   {
	   	if(valley(Trend))
	   	{
	   		if (reinvestprofits && MarginLong>0) Margin = MarginLong; else if(is(TRADEMODE)) Lots = -1;
	   		reverseLong(maxtrades);
	   	}
	   	else if(peak(Trend))
	   	{
				if (reinvestprofits && MarginShort>0) Margin = MarginShort; else if(is(TRADEMODE)) Lots = -1;
	    		reverseShort(maxtrades);
			}
	    		
		}
   }
}



I will take the time to read up on workshop 4, 5 and 6 again. Go over dusk traders modifiers and emodes and get a better understanding of them and see if I can take counter trend code in workshop 5 through the process.
If you notice where I might have made mistakes, please point them out so I can learn from them. eek
Posted By: Anonymous

Re: My Take on A Mega Script - 12/28/13 18:57

Took a couple of days off to read and do some digging around. Looks like if I am going to find any profitable systems, I have a lot more to learn. Thankfully I have the basics of script writing in zorro down to some level. I can now identify the error of leaving out ";" ... The main reason why my first zorro adventure ended abruptly. I want to make my way through the suggested books in the first quarter of 2014. But during this period I don't want to get rusty on the script writing end so I will try taking one free system or EA out there on the web and convert it to a zorro script and see how well it fares. Since my programming skills are not that strong now, please point out logic lapses you observe in my translations.
Posted By: Anonymous

Re: My Take on A Mega Script - 12/28/13 19:02

So I tried converting a very simple straight forward EA this evening. Its called MACD Cross AUDD1. You can follow this link to download and EA and read the rules with the MetaEditor and see if I did everything the way it should be done.
This is the script I came up with following the rules.
Code:
function run()
{
	StartDate = 2002;
	BarPeriod = 1440;
	LookBack = 150;
	//edge trading logic
   int FastPeriod = 12;
   int SlowPeriod = 26;
	int SignalPeriod = 9;
	
	vars PriceClose = series(priceClose());
	MACD(PriceClose,FastPeriod,SlowPeriod,SignalPeriod);
	vars MainLine = series(rMACD);
	vars SignalLine = series(rMACDSignal);
	vars Hist = series(rMACDHist);
	
	Stop = 30*PIP; // simple Stop
	TakeProfit = 120*PIP;
	
	if(crossOver(SignalLine,MainLine))
			enterLong();
	else if(crossUnder(SignalLine,MainLine))
		enterShort();
}



These are the results my testing produced.
Code:
AUDUSD D1 MACD cross compiling.................
BackTest: AUDUSD D1 MACD cross AUD/USD 2002..2013
Profit -111$  MI -1$  DD 138$  Capital 76$
Trades 233  Win 20%  Avg -6.2p  Bars 2
AR -14%  PF 0.76  SR -0.49  UI 343.7%  Error 48%

Posted By: Anonymous

Re: My Take on A Mega Script - 12/28/13 19:53

Did a little tweaking optimizing the stop and running a WFO process. The code now looks like this:
Code:
function run()
{
	set(PARAMETERS);
	StartDate = 2002;
	BarPeriod = 1440;
	LookBack = 250;
	NumWFOCycles = 10;
	
	//edge trading logic
   int FastPeriod = 12;
   int SlowPeriod = 26;
	int SignalPeriod = 9;
	
	vars PriceClose = series(priceClose());
	MACD(PriceClose,FastPeriod,SlowPeriod,SignalPeriod);
	vars MainLine = series(rMACD);
	vars SignalLine = series(rMACDSignal);
	vars Hist = series(rMACDHist);
	
	Stop = ATR(100) * optimize(1.99,1,15,0.5,0); // Adaptive stop
	
		
	if(crossOver(SignalLine,MainLine))
			reverseLong(1);
	else if(crossUnder(SignalLine,MainLine))
		reverseShort(1);
	if(ReTrain) 
	{
  		UpdateDays = -1; 
  		SelectWFO = -1; 
	}	
}


And the results are as follows.
Code:
AUDUSD D1 MACD cross run..
Profit -165$  MI -2$  DD 338$  Capital 232$
Trades 132  Win 61%  Avg -16.4p  Bars 13
AR -11%  PF 0.86  SR -0.26  UI 223.3%  Error 48%
Generate Chart - please wait... ok



My aim to go around picking simple to a little complex systems and converting them to zorro scripts. I am sure if newbies come along they will find this useful and can learn by trying to converting the strategies themselves before they look at how I went about it.
Posted By: Anonymous

Re: My Take on A Mega Script - 12/30/13 19:46

So I crossed checked the AUDUSD daily chart EA against my script by running the EA on the MT4 strategy tester and checking against the trades my script took. Looks like my script was in order and the system is just not profitable.
Posted By: DMB

Re: My Take on A Mega Script - 12/30/13 20:38

It's been interesting reading your investigation. Thanks.
Posted By: Anonymous

Re: My Take on A Mega Script - 01/03/14 18:03

So I just finished going through Schaum's Outline of Theory and Problems of Statistics and I it does feel like I took a couple of things from the book. A lot of examples to help solidify theory. Now I make my way to Analysis of Financial Time Series by Ruey S. Tsay. I am sure it ll take me atleast to make my way through this one. In the meantime, I continue with my project of translating ideas and mt4 robots to help improve my programming skills.
Today I will be trying to translate this mt4 robot, MACD Turbo v2.0. It was featured by Robopip and based on his tests it turned out to be profitable but he tested it over only 18 months, not long enough for me.
So the mt4 code is as follows;
Code:
//+------------------------------------------------------------------+
//|                                             MACD Turbo v2.0a.mq4 |
//|                                      for GBPUSD H1 re-coded 2013 |
//|                                                 Free EA based on |
//|                                                                  |
//|                                                  MACD Sample.mq4 |
//|                      Copyright © 2005, MetaQuotes Software Corp. |
//|                                       http://www.metaquotes.net/ |
//|                                                                  |
//|                                 MACD Sample - Turbo v1.0 to v2.0 |
//|                               by XeroFX - http://www.xerofx.com/ |
//|                                                                  |
//|                                         MACD Sample - Turbo v1.1 |
//|                                      re-coded by Tjipke de Vries |
//|                                                                  |
//| Free Sample Code. We disclaim all copyright interest. Thank you. |
//+------------------------------------------------------------------+
#property copyright "Copyleft - Free Sample Code - www.xerofx.com/free-ea.html - We disclaim all copyright interest."
extern string s1 = "== Basic Settings ==";
extern double StopLoss = 255;
extern double TakeProfit = 100;
extern double TrailingStop = 25;
extern double TrailingStep = 5;
extern string s2 = "== Trade Lots Size ==";
extern double Lots = 0.1;
extern string s3 = "== Signal Logic ==";
extern double MACDOpenLevel = 3;
extern double MACDCloseLevel = 2;
extern double MATrendPeriod = 24;
extern string s4 = "== Time Filters == ";
extern string UseTradingHours = "Time Control ( 1 = True, 0 = False )";
extern int    TimeControl = 1;
extern string TimeZone = "Adjust ServerTimeZone if Required";
extern int    ServerTimeZone = 0;
extern string TradingTimes = "HourStopGMT > HourStartGMT";
extern int    HourStartGMT = 8;
extern int    HourStopGMT = 20;
extern string DontTradeFriday = "Dont Trade After FridayFinalHourGMT";
extern bool   UseFridayFinalTradeTime = TRUE;
extern int    FridayFinalHourGMT = 6;
extern string s5 = "== Extra Settings ==";
extern int    Slippage = 3;
extern double MaxSpread = 4.0;
extern int    MagicNumber = 10042;
extern string TradeComment = "MACD Turbo v2.0a";
int checkorder=1;
int SlipPage;
double Points,SL,TP;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
// 4 or 5 Digit Broker Account Recognition
void HandleDigits()
{
    // Automatically Adjusts to Full-Pip and Sub-Pip Accounts
   if (Digits == 4 || Digits == 2)
     {
       SlipPage = Slippage;
       Points = Point;
     }
  
   if (Digits == 5 || Digits == 3)
     {
       SlipPage = Slippage*10;
       Points = Point*10;
     }
}
//----------------------- PRINT COMMENT FUNCTION
void subPrintDetails()
{
   string sComment   = "";
   string SP         = " ----------------------------------------\n";
   string NL         = "\n";
   string SessionActive,CurrentSpread,spread;
   
   TradeSession();
   MaxSpreadFilter();
   if(Digits == 4 || Digits == 5){spread = DoubleToStr(10000.0 * (Ask - Bid),1);}
   if(Digits == 2 || Digits == 3){spread = DoubleToStr(100.0 * (Ask - Bid),1);}
   if (TradeSession())SessionActive = "Trading...";
     else SessionActive = "Non-Trading Time";
   if (MaxSpreadFilter())CurrentSpread = " is to High";
     else CurrentSpread = " is OK";
   sComment = "MACD Turbo v2.0a" + NL;
   sComment = sComment + NL;
   sComment = sComment + "Magic Number " + DoubleToStr(MagicNumber,0) + NL;
   sComment = sComment + "StopLoss " + DoubleToStr(StopLoss,0) + " | ";
   sComment = sComment + "TakeProfit " + DoubleToStr(TakeProfit,0) + " | ";
   sComment = sComment + "TrailingStop " + DoubleToStr(TrailingStop,0) + NL;
   sComment = sComment + "Date: " + Month() +"-"+Day()+"-"+Year()+" Server Time: " + TimeToStr(TimeCurrent(), TIME_SECONDS) + NL;
   sComment = sComment + "GMT Time: " + TimeToStr((TimeCurrent()+ (( 0 - ServerTimeZone) * 3600)), TIME_SECONDS) + NL;
   sComment = sComment + "ServerTimeZone: " + ServerTimeZone + " (TimeZone)" + NL;
   sComment = sComment + SP;
   sComment = sComment + "Lot Size " + DoubleToStr(Lots,2) + NL;
   sComment = sComment + SessionActive + NL;
   sComment = sComment + "Spread: " + spread + CurrentSpread + NL;
   Comment(sComment);
}
//+------------------------------------------------------------------+
bool TradeSession() {
   int HourStartTrade;
   int HourStopTrade;
   HourStartTrade = HourStartGMT + ServerTimeZone;
   HourStopTrade = HourStopGMT + ServerTimeZone;
   if (HourStartTrade < 0)HourStartTrade = HourStartTrade + 24;
   if (HourStartTrade >= 24)HourStartTrade = HourStartTrade - 24;
   if (HourStopTrade > 24)HourStopTrade = HourStopTrade - 24;
   if (HourStopTrade <= 0)HourStopTrade = HourStopTrade + 24;
   if ((UseFridayFinalTradeTime && (Hour()>=FridayFinalHourGMT + ServerTimeZone) && DayOfWeek()==5)||DayOfWeek()==0)return (FALSE); // Friday Control
   if((TimeControl(HourStartTrade,HourStopTrade)!=1 && TimeControl==1 && HourStartTrade<HourStopTrade)
        || (TimeControl(HourStopTrade,HourStartTrade)!=0 && TimeControl==1 && HourStartTrade>HourStopTrade)
          ||TimeControl==0)return (TRUE); // "Trading Time";
    return (FALSE); // "Non-Trading Time";
}
//+------------------------------------------------------------------+
int TimeControl(int StartHour, int EndHour)
{
   if (Hour()>=StartHour && Hour()< EndHour)
      {
      return(0);
      }
return(1);
}
//+------------------------------------------------------------------+
bool MaxSpreadFilter()
  {
   RefreshRates();
     if ((Digits == 4 || Digits == 5)&&(10000.0 * (Ask - Bid) > MaxSpread))
       {return(true);}
     if ((Digits == 2 || Digits == 3)&&(100.0 * (Ask - Bid) > MaxSpread))
       {return(true);}
   else return(false);
  }
  
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int start()
{
   double MacdCurrent, MacdPrevious, SignalCurrent;
   double SignalPrevious, MaCurrent, MaPrevious;
   int cnt, ticket, total;
// initial data checks
// it is important to make sure that the expert works with a normal
// chart and the user did not make any mistakes setting external
// variables (Lots, StopLoss, TakeProfit,
// TrailingStop) in our case, we check TakeProfit
// on a chart of less than 100 bars
   if(Bars<100)
     {
      Print("bars less than 100");
      return(0);  
     }
   if(TakeProfit<10)
     {
      Print("TakeProfit less than 10");
      return(0);  // check TakeProfit
     }
// to simplify the coding and speed up access
// data are put into internal variables
   MacdCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,0);
   MacdPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,1);
   SignalCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,0);
   SignalPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,1);
   MaCurrent=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,0);
   MaPrevious=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,1);
   HandleDigits();
   subPrintDetails();
   total=OrdersTotal();
   
   if(checkorder<1)
     {
      // if no opened orders identified
      if(AccountFreeMargin()<(1000*Lots))
        {
         Print("You dont have enough money. Free Margin = ", AccountFreeMargin());
         return(0);
        }
      // check for long position (BUY) possibility
      if(!MaxSpreadFilter() && MacdCurrent<0 && MacdCurrent>SignalCurrent && MacdPrevious<SignalPrevious &&
         MathAbs(MacdCurrent)>(MACDOpenLevel*Points) && MaCurrent>MaPrevious && TradeSession())
        {
         ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,SlipPage,0,0,TradeComment,MagicNumber,0,Green);
         if(ticket>0)
           {
            if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
               {
                Print("BUY order opened : ",OrderOpenPrice());
                checkorder=checkorder+1;
               }
           }
         else Print("Error opening BUY order : ",GetLastError());
         return(0);
        }
      // check for short position (SELL) possibility
      if(!MaxSpreadFilter() && MacdCurrent>0 && MacdCurrent<SignalCurrent && MacdPrevious>SignalPrevious &&
         MacdCurrent>(MACDOpenLevel*Points) && MaCurrent<MaPrevious && TradeSession())
        {
         ticket=OrderSend(Symbol(),OP_SELL,Lots,Bid,SlipPage,0,0,TradeComment,MagicNumber,0,Red);
         if(ticket>0)
           {
            if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
               {
                Print("SELL order opened : ",OrderOpenPrice());
                checkorder=checkorder+1;
               }
           }
         else Print("Error opening SELL order : ",GetLastError());
         return(0);
        }
      return(0);
     }
   // it is important to enter the market correctly, 
   // but it is more important to exit it correctly...
if(checkorder>0)
  {
   checkorder=0;
   for(cnt=0;cnt<total;cnt++)
     {
      OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
      if(OrderSymbol()==Symbol()&& // check for symbol
         OrderMagicNumber()==MagicNumber) // check the Magic Number
        {
         if(OrderType()==OP_BUY) // go to long position
           {
            checkorder=checkorder+1;
            // check for trailing stop
            if(TrailingStop>0)
              {
               if(Bid-OrderOpenPrice()>Points*TrailingStop)
                 {
                  if(OrderStopLoss()<Bid-Points*(TrailingStop+TrailingStep))
                    {
                     OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Points*TrailingStop,OrderTakeProfit(),0,Green);
                     return(0);
                    }
                 }
              }
            // modify OrderStopLoss and OrderTakeProfit for Buy
            if(OrderStopLoss()==0 && OrderTakeProfit()==0 && (StopLoss>0||TakeProfit>0))
              {
               SL = OrderStopLoss();
               if (StopLoss>0) {SL =(OrderOpenPrice() - (StopLoss*Points));}
               TP = OrderTakeProfit();
               if (TakeProfit>0) {TP =(OrderOpenPrice() + (TakeProfit*Points));}
               OrderModify(OrderTicket(),OrderOpenPrice(),SL,TP,0,Green);
               return(0);
              }
           }
         if(OrderType()==OP_SELL) // go to short position
           {
            checkorder=checkorder+1;
            // check for trailing stop
            if(TrailingStop>0)
              {
               if((OrderOpenPrice()-Ask)>(Points*TrailingStop))
                 {
                  if((OrderStopLoss()>(Ask+Points*(TrailingStop+TrailingStep))) || (OrderStopLoss()==0))
                    {
                     OrderModify(OrderTicket(),OrderOpenPrice(),Ask+Points*TrailingStop,OrderTakeProfit(),0,Red);
                     return(0);
                    }
                 }
              }
            // modify OrderStopLoss and OrderTakeProfit for Sell
            if(OrderStopLoss()==0 && OrderTakeProfit()==0 && (StopLoss>0||TakeProfit>0))
              {
               SL = OrderStopLoss();
               if (StopLoss>0) {SL =(OrderOpenPrice() + (StopLoss*Points));}
               TP = OrderTakeProfit();
               if (TakeProfit>0) {TP =(OrderOpenPrice() - (TakeProfit*Points));}
               OrderModify(OrderTicket(),OrderOpenPrice(),SL,TP,0,Red);
               return(0);
              }
           }
        }
     }
   }
   return(0);
  }
// the end.


Lets see if I can finish today but if anyone else manages to translate it before me, you are welcome to post the code so I can compare it to my final translation.
Posted By: Anonymous

Re: My Take on A Mega Script - 01/03/14 19:31

So I did a little reading and copy and pasting gets me what I think is the zorro version of this mt4 strategy. Based on my understanding and testing it turned out to be unprofitable based on the raw code and parameters.

Code:
function hourOpen(int hourblockstart, int hourblockend)
{
	//blocks new trades between selected hours
	//uses NYSE time, including DST
	if ( (lhour(ET) >= hourblockstart) && (lhour(ET) < hourblockend) )
		return 0; //between blocked hours, do not allow trade opens
	else
		return 1; //no conditions met, allow trades by default
}

function fridayCloseTrading(int fridayfinalhourET)
{
	//blocks new open trades on fridays from the hour set
	// uses NYSE time, including DST
	if (ldow(ET) == FRIDAY && (lhour(ET)>= fridayfinalhourET))
		return 0; // during the no new trade friday period. 
	else 
		return 1; // no condition met, allow new trades by default
}

function run()
{
	StartDate = 2002;
	EndDate = 20131231;
	BarPeriod = 60;
	LookBack = 250;
	
	//edge trading logic
   int FastPeriod = 12;
   int SlowPeriod = 26;
	int SignalPeriod = 9;
	int MACDOpenLevel = 3;
	int MACDCloseLevel= 2;
	int MATrendPeriod=24;
	int OpenOrders = 2;
	int hourblockend = 3;
	int hourblockstart = 14;
	int fridayfinalhourET = 1;
	
		
	vars PriceClose = series(priceClose());
	MACD(PriceClose,FastPeriod,SlowPeriod,SignalPeriod);
	vars MainLine = series(rMACD);
	vars SignalLine = series(rMACDSignal);
	vars MA1 = series(EMA(PriceClose,MATrendPeriod));
	
	Stop = 255*PIP; // ATR(200)*5;
	Trail = 25*PIP; // ATR(200)*5;
	TakeProfit = 100*PIP;
	
	if(hourOpen(hourblockend,hourblockstart) && fridayCloseTrading(fridayfinalhourET)){
	
		if(NumOpenTotal<OpenOrders && MainLine[0]<0 && crossOver(MainLine,SignalLine) && (-1*MainLine[0])>(0.0001*MACDOpenLevel) && rising(MA1))
				reverseLong(1);
		else if(NumOpenTotal<OpenOrders && MainLine[0]>0 && crossUnder(MainLine,SignalLine) && MainLine[0]>(0.0001*MACDOpenLevel) && falling(MA1))
				reverseShort(1);
	}
//          plot("MainLine", MainLine[0], NEW, BLUE);
//				plot("SignalLine", SignalLine[0], 0, RED);
//				plot("TrendLine", MA1[0], NEW, BLACK);
}



I will go through changing some parameters tomorrow and see how it fares.
Posted By: Anonymous

Re: My Take on A Mega Script - 01/04/14 10:12

So I just changed the stops to more adaptive stops and took out the trailing stop. Set the parameter flag and trained. It now seems to be more profitable as it has been "curve fitted". This is the code I ended up with, the original EA was built for GBPUSD. It is one of the few trend following systems I have seen that might have pulled a profit in 2013. I think it has potential and I will comeback to taking it through the evaluation process once I am done with all the recommended books.
Code:
function hourOpen(int hourblockstart, int hourblockend)
{
	//blocks new trades between selected hours
	//uses NYSE time, including DST
	if ( (lhour(ET) >= hourblockstart) && (lhour(ET) < hourblockend) )
		return 0; //between blocked hours, do not allow trade opens
	else
		return 1; //no conditions met, allow trades by default
}

function fridayCloseTrading(int fridayfinalhourET)
{
	//blocks new open trades on fridays from the hour set
	// uses NYSE time, including DST
	if (ldow(ET) == FRIDAY && (lhour(ET)>= fridayfinalhourET))
		return 0; // during the no new trade friday period. 
	else 
		return 1; // no condition met, allow new trades by default
}

function run()
{
	set(PARAMETERS);
	StartDate = 2011;
	EndDate = 2013;
	BarPeriod = 60;
	LookBack = 250;
	
	//edge trading logic
   int FastPeriod = 12;
   int SlowPeriod = 26;
	int SignalPeriod = 9;
	int MACDOpenLevel = 3;
	int MACDCloseLevel= 2;
	int MATrendPeriod=24;
	int OpenOrders = 2;
	int hourblockend = 3;
	int hourblockstart = 14;
	int fridayfinalhourET = 1;
	
		
	vars PriceClose = series(priceClose());
	MACD(PriceClose,FastPeriod,SlowPeriod,SignalPeriod);
	vars MainLine = series(rMACD);
	vars SignalLine = series(rMACDSignal);
	vars MA1 = series(EMA(PriceClose,MATrendPeriod));
	
	Stop = ATR(200)*optimize(3,1,10,1); //Adaptive Stop
	Trail = ATR(200)*optimize(5,1,10,1); //Adaptive Trail
//	TakeProfit = 100*PIP;
	
	if(hourOpen(hourblockend,hourblockstart) && fridayCloseTrading(fridayfinalhourET)){
	
		if(NumOpenTotal<OpenOrders && MainLine[0]<0 && crossOver(MainLine,SignalLine) && (-1*MainLine[0])>(0.0001*MACDOpenLevel) && rising(MA1))
				reverseLong(1);
		else if(NumOpenTotal<OpenOrders && MainLine[0]>0 && crossUnder(MainLine,SignalLine) && MainLine[0]>(0.0001*MACDOpenLevel) && falling(MA1))
				reverseShort(1);
	}
//          plot("MainLine", MainLine[0], NEW, BLUE);
//				plot("SignalLine", SignalLine[0], 0, RED);
//				plot("TrendLine", MA1[0], NEW, BLACK);
}



Code:
MACD SAMPLE compiling................
BackTest: MACD SAMPLE GBP/USD 2002..2013
Profit 199$  MI 1$  DD 202$  Capital 108$
Trades 238  Win 35%  Avg +11.0p  Bars 70
AR 16%  PF 1.20  SR 0.27  UI 51.9%  Error 40%


Everyone is welcome to use it as they wish. We are in this together.
Here is the 2002-2013 growth curve.

This is the 2011-2013 growth curve.
Posted By: Anonymous

Re: My Take on A Mega Script - 01/04/14 14:17

A lot of free time on my hands today so I might as well try out some simple strategy translations. I will be looking at PZ Reversal Trend Following EA.

System Description:
Quote:

Trend following systems can vary, but principle elements remain the same. A reversal system, a very common system, has two modes: you are either long or short. It is always in the market and closes one position by opening a new one in the opposite direction.

With this MT4 Expert Advisor, you can either be long or short at any given time. You enter a long position and exit a short position if the current price closes above the highest price in the previous 100 days. You enter a short position and exit a long position if the current price drops below the lowest price in the previous 100 days.

This system should be applied to a huge variety of instruments to make sure to catch some big trends to pay for the other little losses. You should trade forex, commodities, indexes, interest rates, government bonds and even sectorial stocks. As a sidenote, Bill Dunn is a long term reversal trend follower that exploited the Japanese Yen to extreme levels in 1995 with a reversal system exactly like this one and has reaped incredible profits since then.


The MT4 code read as follows.
Code:
//+------------------------------------------------------------------+
//| PZ_ReversalTrendFollowingEA.mq4
//| --
//| You can either be long or short at any given time. You buy if the market 
//| makes a new 100-day high and sell if the market makes a new 100-day low. 
//| You are always in the market and break-even all trades as soon as possible.
//+------------------------------------------------------------------+
#property copyright "Copyright © http://www.pointzero-trading.com"
#property link      "http://www.pointzero-trading.com"
 
//---- Dependencies
#import "stdlib.ex4"
   string ErrorDescription(int e);
#import
 
//---- Constants
#define  ShortName         "PZ Reversal Trend Following EA"
#define  Shift             1
 
//---- External variables
extern string TR_Ex                    = "------- Trade period";
extern int    TradingPeriod            = 100;
extern string MM_Ex                    = "------- Money management";
extern bool   MoneyManagement          = true;
extern double RiskPercent              = 2;
extern double LotSize                  = 0.1;
extern string EA_Ex                    = "------- EA Settings";
extern int    Slippage                 = 6;
extern int    MagicNumber              = 2000;
 
//---- Internal
double   DecimalPip;
double   PBuy = EMPTY_VALUE;
double   PSell = EMPTY_VALUE;
 
//+------------------------------------------------------------------+
//| Custom EA initialization function
//+------------------------------------------------------------------+
int init()
{
   DecimalPip = GetDecimalPip();
   Comment("Copyright © http://www.pointzero-trading.com");
   return(0);
}
 
//+------------------------------------------------------------------+
//| Custom EA deinit function
//+------------------------------------------------------------------+
int deinit()
{
   return(0);
}
 
//+------------------------------------------------------------------+
//| Custom EA start function
//+------------------------------------------------------------------+
int start()
{   
   //--
   //-- Trade if trigger price is breached
   //--
   
   // Buy
   if(PBuy != EMPTY_VALUE && Bid > PBuy)
   { 
      PlaceOrder(OP_BUY, GetLotSize()); 
      PBuy = EMPTY_VALUE;
   }
   
   // Sell
   if(PSell != EMPTY_VALUE && Ask < PSell) 
   { 
      PlaceOrder(OP_SELL, GetLotSize()); 
      PSell = EMPTY_VALUE; 
   }
   
   //--
   //-- Check entry
   //--
   
   // Do not continue unless the bar is closed
   if(!IsBarClosed(0, true)) return(0);
   
   // Trading thresholds
   double rhigh  = iHigh(Symbol(), Period(), iHighest(Symbol(), Period(), MODE_HIGH, TradingPeriod, Shift+1));
   double rlow   = iLow(Symbol(), Period(), iLowest(Symbol(), Period(), MODE_LOW, TradingPeriod, Shift+1));
                        
   // Trades opened
   int l_TotalTrades_buy = GetTotalTrades(OP_BUY, MagicNumber);
   int l_TotalTrades_sell = GetTotalTrades(OP_SELL, MagicNumber);
  
   // Bars
   double CLOSE = iClose(Symbol(),0, Shift);
   double HIGH = iHigh(Symbol(),0, Shift);
   double LOW = iLow(Symbol(),0, Shift);
   
   // Check if buy conditions apply
   if(CLOSE > rhigh && l_TotalTrades_buy == 0)
   {
      // Buy
      PBuy = HIGH;
      CloseOrder(OP_SELL);
   }
   
   // Check if sell conditions apply
   if(CLOSE < rlow && l_TotalTrades_sell == 0)
   {
      // Sell
      PSell = LOW;
      CloseOrder(OP_BUY);
   }
   
   return (0);
}
 
//+------------------------------------------------------------------+
//| My functions
//+------------------------------------------------------------------+
 
/**
* Returns total opened trades
* @param    int   Type
* @param    int   Magic
* @return   int
*/
int GetTotalTrades(int Type, int Magic)
{
   int counter = 0;
   for (int i = OrdersTotal() - 1; i >= 0; i--)
   {
      if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
        Print(ShortName +" (OrderSelect Error) "+ ErrorDescription(GetLastError()));
      } else if(OrderSymbol() == Symbol() && (OrderType() == Type || Type == EMPTY_VALUE) && OrderMagicNumber() == Magic) {
            counter++;
      }
   }
   return(counter);
}
 
/**
* Places an order
* @param    int      Type
* @param    double   Lotz
* @param    double   PendingPrice
*/
void PlaceOrder(int Type, double Lotz, double PendingPrice = 0)
{
   int err;
   color  l_color;
   double l_price, l_sprice = 0;
   RefreshRates();
   
   // Price and color for the trade type
   if(Type == OP_BUY){ l_price = Ask;  l_color = Blue; }
   if(Type == OP_SELL){ l_price = Bid; l_color = Red; } 
   
   // Avoid collusions
   while (IsTradeContextBusy()) Sleep(1000);
   int l_datetime = TimeCurrent();
   
   // Send order
   int l_ticket = OrderSend(Symbol(), Type, Lotz, l_price, Slippage, 0, 0, "", MagicNumber, 0, l_color);
   
   // Rety if failure
   if (l_ticket == -1)
   {
      while(l_ticket == -1 && TimeCurrent() - l_datetime < 60 && !IsTesting())
      {
         err = GetLastError();
         if (err == 148) return;
         Sleep(1000);
         while (IsTradeContextBusy()) Sleep(1000);
         RefreshRates();
         l_ticket = OrderSend(Symbol(), Type, Lotz, l_price, Slippage, 0, 0, "", MagicNumber, 0, l_color);
      }
      if (l_ticket == -1)
         Print(ShortName +" (OrderSend Error) "+ ErrorDescription(GetLastError()));
   }
}
 
/**
* Closes desired orders 
* @param    int   Type
*/
void CloseOrder(int Type)
{
   int l_type;
    for(int i = OrdersTotal()-1; i >= 0; i--)
    {
        OrderSelect(i, SELECT_BY_POS, MODE_TRADES); l_type = OrderType();
        if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber && Type == l_type)
        { 
          if(Type == OP_BUY || Type == OP_SELL)  
          {
            if(!OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), Slippage, Gold))
               Print(ShortName +" (OrderClose Error) "+ ErrorDescription(GetLastError()));
         } else {
            if(!OrderDelete(OrderTicket()))
               Print(ShortName +" (OrderDelete Error) "+ ErrorDescription(GetLastError()));
         }
      }
   }
}
 
/**
* Calculates lot size according to risk and the weight of this trade
* @return   double
*/
double GetLotSize()
{
   // Lots
   double l_lotz = LotSize;
   
   // Lotsize and restrictions 
   double l_minlot = MarketInfo(Symbol(), MODE_MINLOT);
   double l_maxlot = MarketInfo(Symbol(), MODE_MAXLOT);
   double l_lotstep = MarketInfo(Symbol(), MODE_LOTSTEP);
   int vp = 0; if(l_lotstep == 0.01) vp = 2; else vp = 1;
   
   // Apply money management
   if(MoneyManagement == true)
      l_lotz = MathFloor(AccountBalance() * RiskPercent / 100.0) / 1000.0;
  
   // Normalize to lotstep
   l_lotz = NormalizeDouble(l_lotz, vp);
   
   // Check max/minlot here
   if (l_lotz < l_minlot) l_lotz = l_minlot;
   if(l_lotz > l_maxlot) l_lotz = l_maxlot; 
   
   // Bye!
   return (l_lotz);
}
 
/**
* Returns decimal pip value
* @return   double
*/
double GetDecimalPip()
{
   switch(Digits)
   {
      case 5: return(0.0001);
      case 4: return(0.0001);
      case 3: return(0.001);
      default: return(0.01);
   }
}
 
/**
* Checks if the bar has closed
*/
bool IsBarClosed(int timeframe,bool reset)
{
    static datetime lastbartime;
    if(timeframe==-1)
    {
        if(reset)
            lastbartime=0;
        else
            lastbartime=iTime(NULL,timeframe,0);
        return(true);
    }
    if(iTime(NULL,timeframe,0)==lastbartime) // wait for new bar
        return(false);
    if(reset)
        lastbartime=iTime(NULL,timeframe,0);
    return(true);
}


So I crawl back into my cave to see how well I can read and translate this code.
Posted By: Anonymous

Re: My Take on A Mega Script - 01/04/14 18:49

So I this is the zorro translation I came up with. Took me a little while to realise I had to compare the current price close to the previous highest in the last 100 based on the way the code is set. Learning with each day. The system seems to perform well in trending markets but not post 2008.
Code:
function run()
{
	set(TICKS);
	StartDate = 2002;
	EndDate = 2013;
	BarPeriod = 1440;
	LookBack = 200;
	
	
	
	//edge trading logic
	vars rHigh = series(HH(100)); 
	vars rLow = series(LL(100));
	vars Price = series(price());
	vars PriceClose = series(priceClose());
	vars PriceHigh = series(priceHigh());
	vars PriceLow = series(priceLow());
			
	// Pending buy order placed at the previous day High.	
	if(PriceClose[0]>rHigh[1] && NumOpenLong == 0){
		exitShort();
		Entry = PriceHigh[0];
		enterLong();
	}
	// Pending sell order placed at the previous day High.
	else if(PriceClose[0]<rLow[1]& NumOpenShort == 0){
		exitLong();
		Entry = PriceLow[0];
		enterShort();
	}
}



Code:
BackTest: PZ_ReversalTrendFollowingEA EUR/USD 2002..2013
Profit 490$  MI 4$  DD 52$  Capital 32$
Trades 11  Win 82%  Avg +585.9p  Bars 259
AR 136%  PF 9.79  SR 0.41  UI 14.5%  Error 151%


Another one to file under potential.
Posted By: Anonymous

Re: My Take on A Mega Script - 01/04/14 19:05

I see a bigger problem with that strategy. 11 years -> 11 trades. The strategy as presented looks like it was designed for long term stock investors. Try it on AAPL, GOOG... grin
Posted By: Anonymous

Re: My Take on A Mega Script - 01/04/14 20:15

@Acidburn. yeah, would really have caught those big moves on Apple and Google. But then again, one could lower the timeframe to 1H or 4H and add in some filters.
Posted By: Anonymous

Re: My Take on A Mega Script - 01/07/14 10:00

Well I am going to have to park Tsey's Analysis of Financial Time Series on the to do list. I went through the first 60 pages and I have a headache already. I will be taken time series this semester in school so might be a good idea to sit through class and work along with the book. I will therefore jump to Urban and Emilio's Trading Systems. Its a 250 page book so I should have some free time to work on more script translations.
Posted By: Anonymous

Re: My Take on A Mega Script - 02/18/14 11:58

I want to write a grid trading system similar to the Z5. I have been exploring trend following systems for awhile and I haven't had much luck with them. With the fundamental play on the EUR/CHF still on, might not be too much of a bad idea to put together a grid system that explores this market inefficiency. Who knows, in the process we might learn a thing or two about programming.
Posted By: ibra

Re: My Take on A Mega Script - 02/25/14 07:19

Hey Liftoff,

"Hucks trendcatcher", it reminds me of the same strat you presented over at babypips laugh Has it improved?
Posted By: Anonymous

Re: My Take on A Mega Script - 02/25/14 09:24

Not really. I tried different variants but they all seem to give way worse results than she keeps posting on her blog. I think she might just be faking the results.
Posted By: ibra

Re: My Take on A Mega Script - 02/27/14 15:26

Alright!

Yesterday I was messing with the srategy you presented at babypips.
I replaced the RSI with a highpass filter instead.

Code:
function run()
{
	LookBack = 200;
	Hedge = 2;
	BarPeriod = 240;
	StartDate = 20030101;
	EndDate = 20140101;
	var Threshold = 0.0;
	
	set(PARAMETERS);
	
	
	
	var Timecycle = optimize(5,1,10);
	var Scaling = optimize(2,1,3);
	
	
	var *Price = series(price());
	var *LP5 = series (LowPass(Price,Timecycle));
	var *LP10 = series(LowPass(Price, Timecycle*Scaling));
	Trail = optimize(50,25,100)*PIP;
	Stop = optimize(4,2,6) *ATR(30);

	
   var hp = optimize(50,25,75);
   var *RSI10 = series(HighPass(Price,hp));
	
	static int crossed = 0;
	
	if(crossOver(LP5,LP10))
		crossed = 3;
		
	else if (crossUnder(LP5,LP10))
		crossed = -3;
	
   if(crossed > 0 && crossOver(RSI10, Threshold))
	{
		enterLong();
		crossed = 0;
	}

	else if(crossed < 0 && crossUnder(RSI10, Threshold))
	{
		enterShort();
		crossed = 0;
		
	}
	else crossed -= sign(crossed);
	

	
	plot ("LP1", LP5[0], 0, RED);
	plot ("LP2", LP10[0], 0, BLUE);
	plot ("RSI", RSI10[0], NEW, BLACK);
	plot ("Thres", Threshold, 0, RED);
   plot ("Thres1", -Threshold, 0, RED);
}



There are pretty many optimized parameters...

Backtest looks decent (I guess) on for example EURUSD and GBPUSD.
But I don't know if I like the looks of the equity curves...
And I haven't done any WFO yet. Feel free to improve it.

Equity curve EURUSD:
http://sv.tinypic.com/view.php?pic=ifweg6&s=8

Equity curve GBPUSD:
http://sv.tinypic.com/view.php?pic=161dxsl&s=8#.Uw9Y9fl5N5E
Posted By: Anonymous

Re: My Take on A Mega Script - 03/05/14 15:42

@Ibra I haven't really looked to this system in a very long time. But I think I will play around with it tonight.
Posted By: Anonymous

Re: My Take on A Mega Script - 03/15/14 10:17

So I managed to put together a grid trading system for the EUR/CHF and it seems to be holding things together. As long as the inefficiency is prevalent in that pair it should continue to make money. Here is the code. I used the grid script that comes with Zorro and made a couple of changes.
Code:
// Grid trader (needs hedging - non-US accounts only)
 
// find all trades at a grid line
bool findTrade(var Price,var Grid,bool IsShort)
{
	for(open_trades)
		if((TradeIsShort == IsShort)
			and between(TradeEntryLimit,Price-Grid/2,Price+Grid/2))
				return true;
	return false;
}

int run() 
{
	set(TICKS);					// Test using 1 minute Bars
	StartDate = 2012;					// Start trading from 2012
	BarPeriod = 240;              // Trade the 4 Hour chart
	Hedge = 2;                    // allow long & short trades at the same time
	EntryTime = ExitTime = 500;   // close trades that have been opened for 3 months
	asset("EUR/CHF");
	var Price;							
	var Grid = 25*PIP;            // set grid siz to 25 pips
	var Close = priceClose();		// Use the price close of bars
	
// place pending trades at 5 grid lines 
// above and below the current price
	for(Price = 0; Price < Close+5*Grid; Price += Grid)
	{
// find the lowest grid line
		if(Price < Close-5*Grid) continue;
// place not more than 200 trades		
		if(NumOpenTotal + NumPendingTotal > 200) break;
// place short trades below the current price
		if(Price < Close and !findTrade(Price,Grid,true))
			enterShort(1,Price,20*Grid,Grid);  		
// place long trades above the current price
		else if(Price > Close and !findTrade(Price,Grid,false))
			enterLong(1,Price,20*Grid,Grid);
	}
}





Attached picture eurchfgrid.png
Posted By: Anonymous

Re: My Take on A Mega Script - 03/15/14 13:40

Has anyone thought of incorporating COT data into his or her automated trading?
© 2024 lite-C Forums