| AmiBroker Change Log |
CHANGES FOR VERSION 4.90.0 (as compared to 4.89.0)
CHANGES FOR VERSION 4.89.0 (as compared to 4.88.0)
CHANGES FOR VERSION 4.88.0 (as compared to 4.87.1)
CHANGES FOR VERSION 4.87.1 (as compared to 4.87.0)
CHANGES FOR VERSION 4.87.0 (as compared to 4.86.0)
CHANGES FOR VERSION 4.86.0 (as compared to 4.85.0)
Added 'every tick' RT chart refresh in Professional Edition to already
existing 1-sec and up refresh intervals
To enable 'every tick' chart refresh in Professional Edition, go to Tools->Preferences,
Intraday tab and enter ZERO (0) into "Intraday chart refresh interval" field.
(note Standard Edition won't allow to do that).
Once you enter zero, AmiBroker will refresh all charts with every new trade arriving provided that the formulasyou use execute fast enough. If not, it will dynamically adjust refresh rate to maintain maximum possible refresh rate without consuming more than 50% of CPU (on average). So for example if your charts take 0.2 sec to execute AmiBrokerwill refresh them on average 2.5 times per second.
Note: built-in Windows Performance chart shows cumulated CPU consumption for all processes, to display PER-PROCESS CPU load use SysInternals free software http://www.sysinternals.com/Utilities/ProcessExplorer.html
MDI tabs implemented
AFL: Added GetPerformanceCounter( bReset = False ) function
SYNTAX: GetPerformanceCounter( bReset = False )
RETURNS: Number
GetPerformanceCounter retrieves the current value of the high-resolution performance counter. Returned value is in milliseconds. Resolution is upto 0.001 ms (1 microsecond).The value of high-resolution counter represents number of milliseconds from either system start (boot) or from last counter reset.To reset the counter you need to call GetPerformanceCounter function with bReset parameter set to True. Note that reseting counters inside one formula does not affect counters in other formulas.Since returned values are very large (time in milliseconds since system start is usually quite large), for precise measurements of single function or small function block execution times it is strongly recommended to reset counter at the beginning of the block so floating point resolution (7 digits) does not affect the precision of measurement. Example:
GetPerformanceCounter(True); //
reset counter to zero
for(
i = 0; i < 1000;
i++ )
{
k = sin( i
);
}
elapsed=GetPerformanceCounter();
"Time [ms] = "+elapsed;
The code above shows that 1000 iterations of sin() calculation takes about
1.7 milliseconds. Note that call to the GetPerformanceCounter() has overhead
of about 0.015 ms (15 microseconds)
elapsed=GetPerformanceCounter();
StrFormat("Time
since system start %.0f days, %.0f hours, %.0f minutes, %.0f seconds,
%.0f milliseconds ",
floor(elapsed/(24*60*60*1000)),
floor( elapsed/(60*60*1000)
) % 24,
floor( elapsed/(60*1000)
) % 60,
floor( elapsed/1000 )
% 60,
elapsed % 1000 );
It can be also used in trading system automation to measure time in milliseconds between various events (just subtract values returned by GetPerformanceCounter() during two different events)
Caveat: this function relies on Windows API QueryPerformanceCounter function and CPU RTDSC instruction and it may yield to inaccurrate results if you have multiple-core processor and AMD's "Cool and Quiet" enabled in BIOS or other CPU clock stepping technologies enabled. If this applies to you, you may check Microsoft hotfix to this problem at: http://support.microsoft.com/?id=896256
Fixed crash that sometimes occurred when chart using RequestTimedRefresh() was closed
Added "Cancel" button to "Do you want to save database: Yes/No" dialog that appears on AB exit when database is modified
Added registry key for controlling built-in exception handling.
If you are 3rd party developer working with Visual C++ debugger and wanting exceptions to be caught by Visual Studio debugger instead of AmiBroker's built-in crash recovery system contact AmiBroker support and we will provide instructions how to disable it.
AFL: atan2( y, x ) implemented
atan2 returns the arctangent of y/x. If x is 0, atan returns 0. If both
parameters of atan2 are 0, the function returns 0. While atan returns a
value in the range –PI/2 to PI/2 radians; atan2 returns a value in
the range –PI to PI radians, using the signs of both parameters to
determine the quadrant of the return value.
AFL: FFT( array, size = 0 ) function implemented
FFT( array, len = 0 )
performs FFT (Fast Fourier Transform) on last 'len' bars of the array,
if len is set to zero, then FFT is performed
on entire array. len parameter must be even.
Result:
function returns array which holds FFT bins for first 'len' bars. There
are len/2 FFT complex bins returned,
where bin is a pair of numbers (complex number): first is real part of
the complex number and second number
is the imaginary part of the complex number.
result = FFT( array, 256 );
where:
0th bin (result[0] and result[1]) represents DC component,
1st bin (result[1 ] and result[2]) represents real and imaginary parts
of lowest frequency range
and so on upto result[ len - 2 ] and result[ len - 1 ]
remaining elements of the array are set to zero.
FFT bins are complex numbers and do not represent real amplitude and
phase. To obtain amplitude and
phase from bins you need to convert inside the formula. The following code
snipplet does that:
ffc = FFT(data,Len);
for( i = 0;
i < Len - 1;
i = i + 2 )
{
amp[ i ] = amp[ i + 1 ]
= sqrt(ffc[ i ]^ 2 + ffc[
i + 1 ]^2);
phase[ i ] = phase[ i + 1 ]
= atan2( ffc[ i + 1],
ffc[ i ] );
}
IMPORTANT note: input array for FFT must NOT contain any Null values.
Use Nz() function to convert Nulls to zeros
if you are not sure that input array is free from nulls.
Example formula:
SetBarsRequired(100000,100000);
Len = Param("FFT
Length", 1024, 64, 10000, 10 );
Len = Min( Len, BarCount );
x = BarIndex();
x1 = x - BarCount +
Len;
input = C;
a = LastValue( LinRegIntercept(
input, Len - 1 )
);
b = LastValue( LinRegSlope(
input, Len - 1 )
);
Lr = a + b * x1;
data = input - Lr;// de-trending
ffc = FFT(data,Len);
for( i = 0;
i < Len - 1; i
= i + 2 )
{
amp[ i ] = amp[ i + 1 ]
= sqrt(ffc[ i ]^ 2 + ffc[
i + 1 ]^2);
phase[ i ] = phase[ i + 1 ]
= atan2( ffc[ i + 1],
ffc[ i ] );
}
auto = ParamToggle("Auto
dominant cycle", "No|Yes", 1 );
sbar = Param( "Which
FFT bin", 1, 0, 50 );
skipbin1 = ParamToggle("Skip
1st FFT bin", "No|Yes", 1 );
if(
auto )
{
sbar = int( LastValue(ValueWhen(
amp == LastValue(Highest( IIf(
skipbin1 AND x < 4, 0 ,
amp ) )), x / 2 )) );
}
fv = Status("firstvisiblebar");
thisbar = Ref( int(x/2)
== sbar, -fv);
Plot( Ref(amp,-fv),
"amplitude (bin " + Ref( int(x/2),
-fv ) +")", IIf(
thisbar, colorRed, colorBlack ),styleArea);
Plot( IIf( BarCount - BarIndex() < Len,
data, Null )
,
"de-trended input ("+Len+" bars)", colorOrange, styleLeftAxisScale );
Plot( cos(
phase[ sbar * 2 ]
+ (sbar) * x1 * 2 * 3.1415926 /
Len ),
"
dominant cycle "+ Len/(sbar) + "(" +
sbar + " bin) bars", colorBlue, styleOwnScale );
GraphZOrder=1;
GraphXSpace = 10;
Fixed: pre-defined color table in broker.prefs sometimes got corrupted
Repainting of RT quote window is now flicker-free on Windows XP and higher
Symbol->Organize assignments, added ability to remove multiple symbols at once from watch list, index and favourite categories
CHANGES FOR VERSION 4.85.0 (as compared to 4.84.0)
mydatenum = DateTimeConvert( 0, DateTime()
);// - this returns DateNum mytimenum = DateTimeConvert( 1, DateTime()
); // - returns timenum mydatetime = DateTimeConvert( 2, DateNum(), TimeNum()
); mydatetime = DateTimeConvert( 2, DateNum()
);// get modification
date string of portfolio.afl file
fgetstatus("formulas\\Equity\\portfolio.afl",1,0);CHANGES FOR VERSION 4.84.0 (as compared to 4.83.1)
Status("redrawaction")if( Status("redrawaction")
==1 )
{
_TRACE("\nTIMED
REFRESH"+Now());
}
RequestTimedRefresh(1);
CHANGES FOR VERSION 4.83.1 (as compared to 4.83.0)
CHANGES FOR VERSION 4.83.0 (as compared to 4.82.0)
SetOption("HoldMinDays", 30 ); //
set minimum holding period to 30 calendar days
SetOption("EarlyExitDays", 90 ); //
set penalty period to 90 calendar daysPositionScore = ..your normal score..
// if market timing signal goes negative close
all posiitons
PositionScore = IIf(
MarketTimingSignal < 0, scoreExitAll, PositionScore ); SetChartBkGradientFill( ParamColor("BgTop", colorWhite),ParamColor("BgBottom", colorLightYellow));CHANGES FOR VERSION 4.82.0 (as compared to 4.81.1)
outBuffer = ""; // global output string buffer
function output( string )
{
outBuffer = outBuffer + string + "\n";
}
AB = new ActiveXObject( "Broker.Application");
Docs = AB.Documents;
DocsQty = Docs.Count;
for( i = 0; i < DocsQty; i++ )
{
Doc = Docs( i );
output( "Document " + i + " name : " + Doc.Name );
Windows = Doc.Windows;
WinsQty = Windows.Count;
for( j = 0; j < WinsQty; j++ )
{
Win = Windows( j );
output( " Window " + j + " Selected tab " + Win.SelectedTab );
}
}
WScript.echo( outBuffer );
WScript.echo( "Now will add one window" );
Doc = Docs( 0 );
Windows = Doc.Windows;
NewWindow = Windows.Add();
WScript.echo( "and close it" );
NewWindow.Close();
CHANGES FOR VERSION 4.81.1 (as compared to 4.81.0)
CHANGES FOR VERSION 4.81.0 (as compared to 4.80.2)
CHANGES FOR VERSION 4.80.2 (as compared to 4.80.1)
CHANGES FOR VERSION 4.80.1 (as compared to 4.80.0)
CHANGES FOR VERSION 4.80.1 (as compared to 4.80.0)
CHANGES FOR VERSION 4.80.0 (as compared to 4.79.0)
CHANGES FOR VERSION 4.79.0 (as compared to 4.78.1)
SetOption("HoldMinBars", 127 );
Buy=BarIndex()==0;
Sell=1;
// even if sell signals are generated each day,
//they are ignored until bar 128Buy = Cross(MACD(),Signal());
Sell = Cross(Signal(),MACD());
Filter = Buy OR Sell;
AddColumn( IIf( Buy,
Asc("B"), Asc("S")), "Signal", formatChar );
Filter = 1;
AddColumn(Close, "Close", 1.2, colorDefault, ColorRGB(255, 0, 0)
); // this
works
AddColumn(Close, "Close", 1.2, ColorRGB(0, 0, 255), ColorRGB(255, 0, 0)); // this
works
AddColumn(Close, "Close", 1.2, colorBlue, ColorRGB(255, 0, 0)); //
this works in 4.79, but didn't in previous versions
AddTextColumn(" ", " ");
AddColumn(Close, "Close", 1.2, ColorRGB(255, 0, 0), colorDefault); // this
works
AddColumn(Close, "Close", 1.2, ColorRGB(255, 0, 0), ColorRGB(0, 0, 255)
); // this
works
AddColumn(Close, "Close", 1.2, ColorRGB(255, 0, 0), colorBlue); //
this works in 4.79, but didn't in previous versions
AB = new ActiveXObject("Broker.Application");AA
= AB.Analysis;
// sort by date/time column
AA.SortByColumn( 1, False, False );
// add secondary sort column (see last argument
= True)
AA.SortByColumn( 2, False, True ); AB = new ActiveXObject("Broker.Application");
AB.Visible = True;
WScript.Sleep(1000);
AB.Visible = False;
WScript.Sleep(1000);
AB.Visible = True;
WScript.Sleep(1000);
AB.Quit();CHANGES FOR VERSION 4.78.1 (as compared to 4.78.0)
CHANGES FOR VERSION 4.78.0 (as compared to 4.77.0)
Filter=1;
for( i = 0;
i < 256; i = i
+ 16 )
AddColumn( C, "C"+i, 1.2, colorDefault, ColorHSB(
( BarIndex() + i )
% 256, 255-i, 255 )
);
// these two new
options can be set on per-symbol basis
// how many bars (trading days)
// an early exit (redemption) fee is applied
SetOption("EarlyExitBars", 128 );
// early redemption fee (in percent)
SetOption("EarlyExitFee", 2 );// how to set it up on per-symbol basis?
// it is simple - use 'if' statement
if( Name()
== "SYMBOL1" )
{
SetOption("EarlyExitBars", 128 );
SetOption("EarlyExitFee", 2 );
}
if( Name()
== "SYMBOL2" )
{
SetOption("EarlyExitBars", 25 );
SetOption("EarlyExitFee", 1 );
}
CHANGES FOR VERSION 4.77.0 (as compared to 4.76.0)
bo.AddCustomMetric( "Somestat", 100*kr, Null, Null, 4 ); //
5th parameter controls number of decimal places
Plot(C,"Price", colorBlack, styleLine );
Plot(MA(C,20),"MA20", colorRed );
Buy=Cross( C, MA(C,20 )
);
Sell= Cross( MA( C, 20 ), C );
dist = 1.5*ATR(10);
for( i = 0;
i < BarCount;
i++ )
{
if( Buy[i]
) PlotText( "Buy\n@" + C[
i ], i, L[
i ]-dist[i], colorGreen );
if( Sell[i]
) PlotText( "Sell\n@" + C[
i ], i, H[
i ]+dist[i], colorRed, colorYellow );
}
PlotShapes( Buy * shapeUpArrow + Sell * shapeDownArrow, IIf( Buy, colorGreen, colorRed )
);CHANGES FOR VERSION 4.76.0 (as compared to 4.75.2)
// This is sample formula that allows
// to open multiple, separate positions on the
same symbol
// without averaging effect (i.e. each position
on the same
// symbol is completely independent).
//
// Sample code is provided for trading one symbol
// Enter symbol you want to trade below
Symbol = "MSFT";
Buy=Sell=Short=Cover=0; //
real rules are defined inside custom backtest proc
SetCustomBacktestProc(""); //
enable custom backtest
if( Status("action")
== actionPortfolio )
{
// actual backtest routine
// (low-level)
bo = GetBacktesterObject();
SetForeign(
Symbol );
// make sure to calculate actual buy
and buyprice arrays for symbol we need to backtest
Buy = 1; //
For testing purposes just enter new position every bar
BuyPrice = Open;
RestorePriceArrays();
// actual backtest loop
bo.PreProcess();
for(
i = 1; i < BarCount;
i++ )
{
// first update
backtest stats and handle stops
bo.UpdateStats( i, 0 );
bo.HandleStops( i );
bo.RawTextOutput("Bar " +
i );
if( Buy[
i - 1 ] ) //
if buy signal in previous bar
{
bo.EnterTrade( i, Symbol, True, BuyPrice[
i ], 500 /*
$5000 into one trade */);
}
for(
OpenPos = bo.GetFirstOpenPos(); OpenPos; OpenPos = bo.GetNextOpenPos() )
{
//
exit positions if their age is > 5 bars and they are profitable
if(
OpenPos.BarsInTrade > 5 AND OpenPos.GetProfit() > 0 )
{
//
HERE IS A NEW PART !!!
//
WE ARE PASSING HANDLE instead of ticker symbol
//
THIS ENSURES PROPER OPERATION even if we have multiple positions of the same
//
stock
bo.ExitTrade(
i, OpenPos.Handle, OpenPos.GetPrice( i, "O" )
);
}
}
bo.RawTextOutput("Number
of open positions: " + bo.GetOpenPosQty() );
bo.UpdateStats( i, 2 );
}
bo.PostProcess();
}
CHANGES FOR VERSION 4.75.2 (as compared to 4.75.1)