1 registered members (7th_zorro),
1,390
guests, and 2
spiders. |
Key:
Admin,
Global Mod,
Mod
|
|
|
Re: My Take on A Mega Script
[Re: ]
#434706
12/24/13 15:25
12/24/13 15:25
|
liftoff
Unregistered
|
liftoff
Unregistered
|
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.
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 helpfulYes WFO; Yes oversample; Yes maxtrades; Yes all param optimizing; Yes best modifier(s); Yes emodeso 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 reinvestmentYes rolling WFO; Yes oversample; Yes maxtrades; Yes all param optimizing; Yes modifier(s); Yes emode; Yes reinvestSo 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 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:
//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:
if (reinvestprofits && MarginLong>0) Margin = MarginLong; else if(is(TRADEMODE)) Lots = -1;
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 assetsYes WFO; Yes oversample; Yes maxtrades; Yes all param optimizing; Yes best modifier(s); Yes emode; No reinvestAt 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.
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 3bYes WFO; Yes oversample; Yes maxtrades; Yes all param optimizing; Yes best modifier(s); Yes emode; Yes reinvest; Yes multi-asset loopSo at this point I turn on reinvestment and test.
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.
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.
|
|
|
|