Hello Tomasz,
thanks for the heads up.
Floor () doesn´t do want I want: rounding down if
first digit is smaller than 5, rounding up if it´s equal to or bigger than
5.
Anyway, I found the flaw in my code but I don´t
know how to correct it:
In regular AFL code, I use the following to compute
"ATRExpLag". Then I round it to the 3rd digit ("ATRExpLagRounded"). Thereafter,
I create an artificial ticker, labeled "test" to be later able to call it in
CBT:
for ( i = 1; i < BarCount; i++ )
// here, the Average True Range (20 days) is
coded by using a loop
{
trhelp[i]= Max(High[i]-Low[i],High[i]-Close[i-1]); //trhelp is a helping variable for calculating ATRcombined.
ATR() function cannot be used.
TRcombined[i]= Max(Close[i-1]-Low[i],trhelp[i]);
//TRcombined is the actual TrueRange.
ATRExpLag[i]=ATRExpLag [i- 1]+ (TRcombined[i]-ATRExpLag[i-1])/x; // This is the 20-day expon. moving average of the ATR
}
ATRExpLagRounded= round(ATRExpLag*1000)/1000; //here, I round on the 3rd digit.
test= AddToComposite(ATRExpLagRounded, "~ATRExpLagRounded_"+Name(), "V",
atcFlagDefaults | atcFlagEnableInBacktest);
Here comes the CBT part. When I run an Exploration
to see what´s in "test", it always returns "1"
instead of the values it got from "ATRExpLagRounded". But it should hold the
values of "ATRExpLagRounded", right?! Incidentally, I introduced "y" to be able
to use previous days values for ATRExpLagRounded except for the first day
(otherwhise value would be out of range). The "-200-sharesize" thing works fine
though:
for (sig = bo.GetFirstSignal(i); sig; sig = bo.GetNextSignal(i))
{ // Loop through all signals at this
bar
// Long trades
ATRexRounded = Foreign("~ATRExpLagRounded_"+sig.Symbol,
"V");
// Get symbol's AtrExpLagRounded
array
ATRex = ATRexRounded[i]; // Reference a
value in the array
{
if
(i<=0)
y=ATRexRounded[i];
else
y=ATRexRounded[i- 1];
}
if
(sig.IsEntry() && sig.IsLong()) //
Process long entries
{
sharesize=round(((Heat*bo.cash)/(y*ATRmultiplier))/250)*250; // i.e. computing # of shares/contracts
//
sig.possize=sharesize*sig.price;
//Sharesize formula needs to be modified
for stocks if lot size differs!!
sig.possize=-2000 - sharesize; // i.e. setting back # of shares into signal object!!
Possize must be < "-2000"
// to mean # of shares (see
"Setpositionsize")!!
bo.EnterTrade(i, sig.Symbol, True,
sig.Price, sig.PosSize);
----- Original Message -----
Sent: Wednesday, July 22, 2009 7:33
PM
Subject: Re: [amibroker] Still - using
CBT the first time
Use floor() function instead of round().
Best regards, Tomasz
Janeczko amibroker.com
----- Original Message -----
Sent: Wednesday, July 22, 2009 7:17
PM
Subject: [amibroker] Still - using CBT
the first time
Hello all,
I intend to use CBT to compute proprietary
position size (number shares instead of percentage of equity or amount of
money) as I wrote before.
Now that AB has been told (thru assistance of
Bruce, Mike and TJ ) to use "number of shares", I still don´t know why it
doesn´t output the proper size:
The formula for computing sharesize is as follows
(entire code see further below):
sharesize=round(((Heat*bo.cash)/(y*ATRmultiplier))/250)*250
According to my data, I read for a specific
day
where y=3.115 ATR
multiplier=5 heat=0.1 bo.cash=1000000.00
which should result in a sharesize of 6,500. But
instead, AB computes a sharesize of 6,750. Thus, I´m off by one unit of 250
lots.
Maybe it´s due to the calculation of y? Could
someone please help me with this? It probably caused by the AB´s rounding
but I just can´t figure it out.
If so, I will provide the data for the S&P
contract I use so that the results I get could be
reproduced.
Thanks very much
Markus
- - - - - - - - - - - - - - - - - - - - - - - - -
-
/ *Setting different options to clarify
or override backtester settings*/
//SetOption("InitialEquity", 1000000.00);
SetOption ("UsePrevBarEquityForPosSizing", True);
//SetOption("MinShares", 250);
SetOption ("CommissionMode", 2); //$$ per trade
SetOption ("Marginrequirement", 100);
SetOption ("InterestRate",0); // account doesn´t earn interest for
cash balance!
SetTradeDelays ( 1, 1, 1, 1 );
//RoundLotSize = 250;
Heat= 0.1; // provided by ED
ATRMultiplier= 5; //provided by
ED
TC150= 150;
TC15= 15;
n= 20;
// Time Constant used in ATR lag
computation
x=(n+ 1)/2;
/ * Calculation of TC150 EMA and TC15
EMA*/
SetBarsRequired ( sbrAll,
sbrAll );
EMA150[ 0]=Close[0];
EMA15[ 0]=Close[0];
for ( i = 1; i < BarCount; i++ )
{
EMA150[i]=EMA150[i- 1]+(Close[i]-EMA150[i-1])*2/(TC150+1);
EMA15[i]=EMA15[i- 1]+(Close[i]-EMA15[i-1])*2/(TC15+1);
}
/* Controlling trade price*/
BuyPrice=Open+(High-Open)/ 2; //i.e. 50% slippage
SellPrice = Open-( Open- Low)/ 2; //i.e. 50% slippage
/*Trading rules and optimization*/
Buy= Cum(1)>=25 AND Cross(EMA15, EMA150);
Sell= Cross(EMA150, EMA15);
/* Graphic output*/
Plot (EMA150, "My expon. Lag 150",
colorGreen, styleLine);
Plot (EMA15, "My expon. Lag 15",
colorRed, styleLine);
Plot (Close, "Bar Chart",
colorBlue, styleBar);
EMA15 = Optimize("EMASlow", 50, 1, 150, 1 );
EMA150 = Optimize("EMAFast", 150, 20,400, 1);
Buy = ExRem( Buy, Sell ); // to exclude redundant signals
Sell = ExRem( Sell, Buy );// to exclude redundant signals
/* Position sizing - volatility based*/
trhelp[ 0]=0; // trhelp is being
initialized
TRcombined[ 0]=0; // TRcombined is being
initialized
ATRExpLag[ 0]=High[0]-Low[0]; // ATRExpLag is being initialized; seed value is
the 1st day´s high-low range per Ed´s definition
for ( i = 1; i < BarCount; i++ )
// here, the Average True Range (20 days)
is coded by using a loop
{
trhelp[i]= Max(High[i]-Low[i],High[i]-Close[i-1]); //trhelp is a helping variable for calculating
ATRcombined. ATR() function cannot be used.
TRcombined[i]= Max(Close[i-1]-Low[i],trhelp[i]);
//TRcombined is the actual TrueRange.
ATRExpLag[i]=ATRExpLag [i- 1]+
(TRcombined[i]-ATRExpLag[i-1])/x; // This is the 20-day expon. moving average of the
ATR
}
ATRExpLagRounded= round(ATRExpLag*1000)/1000; //here, I round on the 3rd digit.
AddToComposite (ATRExpLagRounded,
"~ATRExpLagRounded_"+Name(), "V", atcFlagDefaults |
atcFlagEnableInBacktest);
Filter = GroupID() != 253; // Exclude "group
253" in which composites are being saved/
SetCustomBacktestProc ("");
if (Status("action") ==
actionPortfolio)
{
bo = GetBacktesterObject(); // Get backtester
object
bo.PreProcess(); // Do
pre-processing
bo.cash= 1000000; // muß das hier stehen oder im indexierten loop; dann aber wäre doch
bei jeder iteration das
// initial equity UND DAMIT auch das
old cash immer wieder 1000000.00!!??
My_total_equity= 0;
Value_open_positions= 0;
Heat= 0.1;
ATRmultiplier= 5;
for (i = 0; i < BarCount; i++) //
Loop through all bars
{
for (sig = bo.GetFirstSignal(i); sig; sig =
bo.GetNextSignal(i))
{ // Loop through all signals at this
bar
// Long trades
ATRexRounded = Foreign("~ATRExpLagRounded_"+sig.Symbol, "V"); // Get symbol's
AtrExpLagRounded array
ATRex = ATRexRounded[i]; //
Reference a value in the array
{
if (i<=0)
y=ATRexRounded[i];
else
y=ATRexRounded[i- 1];
}
if (sig.IsEntry() && sig.IsLong()) // Process long entries
{
sharesize= round(((Heat*bo.cash)/(y*ATRmultiplier))/250)*250; // i.e. computing # of shares/contracts
//
sig.possize=sharesize*sig.price;
//Sharesize formula needs to be
modified for stocks if lot size differs!!
sig.possize=- 2000 - sharesize; // i.e.
setting back # of shares into signal object!! Possize must be <
"-2000"
// to mean # of shares (see
"Setpositionsize")!!
bo.EnterTrade(i, sig.Symbol, True, sig.Price,
sig.PosSize);
// wird hier die
cash position durch Eingehen des Trades bereits autom. auf neuen Stand
gebrachtoder muß das eigens codiert werden?
//Das mittels
addcustometric (cash position prüfen)!
// oder müßten die
Adcustommetric erst nach sämtl. long- und short signalen
stehen??
/*
trade.AddCustomMetric("initial equity", initial_equity); //zur
Kontrolle und graphische Aufbereitung
trade.AddCustomMetric("Cash position", bo.cash);
trade.AddcustomMetric("Position size [shares]",
trade.shares);
trade.AddCustomMetric("Position Value", sig.possize);
*/
}
else
{ if (sig.IsExit() && sig.IsLong()) // Process long exits (cover longs)
//die position size
muß doch hier nicht angegeben werden, da vom system bekannt,
oder?
bo.ExitTrade(i, sig.Symbol, sig.Price);
// Achtung, daß bei
Exits die Cash position korrekt ausgewiesen wird, oder ob man das manuell
codieren muß
}
// bo.HandleStops(i); // Process
programmed stops or applystop at this bar
} // End of for loop over signals at
this bar
bo.UpdateStats(i, 1); // Update MAE/MFE
stats for bar
bo.UpdateStats(i, 2); // Update stats at
bar's end
} // End of for loop over
bars
bo.PostProcess(); // Do
post-processing
/*AddToComposite( My_total_equity, "~~~My_total_equity", "X",
atcFlagEnableInPortfolio | atcFlagDefaults );
AddToComposite( trade.shares,"~~~Position size [shares]", "X",
atcFlagEnableInPortfolio | atcFlagDefaults );
AddToComposite( sig.possize, "~~~Position Value", "X",
atcFlagEnableInPortfolio | atcFlagDefaults );
AddToComposite( bo.cash, "~~~Cash position", "X",
atcFlagEnableInPortfolio | atcFlagDefaults );
AddToComposite( Value_open_positions, "~~~Value of open positions",
"X", atcFlagEnableInPortfolio | atcFlagDefaults );
*/
}
/ * Exploration output*/
AddColumn (ATRExpLagRounded,"ATRExpLagRounded",1.5);
__._,_.___
**** IMPORTANT PLEASE READ ****
This group is for the discussion between users only.
This is *NOT* technical support channel.
TO GET TECHNICAL SUPPORT send an e-mail directly to
SUPPORT {at} amibroker.com
TO SUBMIT SUGGESTIONS please use FEEDBACK CENTER at
http://www.amibroker.com/feedback/
(submissions sent via other channels won't be considered)
For NEW RELEASE ANNOUNCEMENTS and other news always check DEVLOG:
http://www.amibroker.com/devlog/
__,_._,___
|