Highlights of version 6.93
Highlights of version 6.92
Highlights of version 6.91
Highlights of version 6.90
1. Download x64 WebView2 component from Microsoft
https://developer.microsoft.com/en-us/microsoft-edge/webview2/
2. In AmiBroker go to Tools->Preferences, "Miscellaneous" tab and turn ON the option "Use Chromium/Edge (WebView2) for Web Research"
3. Restart AmiBroker
Highlights of version 6.40
Version 6.40 brings lots of new functionality especially with regards to the formula language and performance . There are hundreds of new features and changes to existing functionality as compared to version 6.30, listed in detail in "Release Notes" document in AmiBroker directory. Below is just a short list of few of them:
To enable QuickGFX experimental tech go to Tools->Preferences, "Miscellaneous" tab,
click "Experimental: Use QuickGFX render" and press "Apply" or "OK"
You can see when it is enabled, chart timing footnote (when enabled) will
say "QuickGFX render ...ms" instead of "GDI render ...ms"
This is PROFESSIONAL edition feature only. Users of Standard version would need to purchase upgrade in order to use this feature.
Highlights of version 6.30
Version 6.30 brings lots of new functionality especially with regards to the formula language and performance . There are hundreds of new features and changes to existing functionality as compared to version 6.20, listed in detail in "Release Notes" document in AmiBroker directory. Below is just a short list of few of them:
18 new AFL functions were added to allow creation of user-definable on-chart graphical user interfaces.
- GuiButton - create on-chart button control (AFL 4.30)
- GuiCheckBox - creates on-chart checkbox control (AFL 4.30)
- GuiDateTime - creates on-chart date-time picker control (AFL 4.30)
- GuiEdit - create on-chart edit control (AFL 4.30)
- GuiEnable - enables or disables on-chart control (AFL 4.30)
- GuiGetCheck - get checked state of control (AFL 4.30)
- GuiGetEvent - get GUI event (AFL 4.30)
- GuiGetText - get text from on-chart control (AFL 4.30)
- GuiGetValue - get numeric value of on-chart control (AFL 4.30)
- GuiRadio - creates on-chart radio button control (AFL 4.30)
- GuiSetCheck - set checked state of on-chart control (AFL 4.30)
- GuiSetFont - set the font for on-chart control (AFL 4.30)
- GuiSetRange - set slider control range (AFL 4.30)
- GuiSetText - set text value of on-chart control (AFL 4.30)
- GuiSetValue - set numeric value of on-chart control (AFL 4.30)
- GuiSetVisible - shows or hides on-chart control (AFL 4.30)
- GuiSlider - creates on-chart slider control (AFL 4.30)
- GuiToggle - create on-chart toggle button control (AFL 4.30)
Why do we stay with old compiler in 32-bit version?
- New compiler does not produce code compatible with older operating systems (XP or earlier). Old compiler offers 100% compatibility with all Windows versions
- New compiler requires modern CPUs
Exact performance improvement is function dependent and hardware dependent. Many functions are faster by 30-50% but in some cases such as Min()/Max() functions as large as 8x speed up can be observed in 64-bit version.
Highlights of version 6.20
Version 6.20 brings lots of new functionality especially with regards to system testing. There are hundreds of new features and changes to existing functionality as compared to version 6.10, listed in detail in "Release Notes" document in AmiBroker directory. Below is just a short list of few of them:
Highlights of version 6.10
Version 6.10 brings lots of new functionality especially with regards to system testing. There are hundreds of new features and changes to existing functionality as compared to version 6.00, listed in detail in "Release Notes" document in AmiBroker directory. Below is just a short list of few of them:
Highlights of version 6.00
Version 6.00 brings lots of new functionality especially with regards to system testing. There are hundreds of new features and changes to existing functionality as compared to version 5.90, listed in detail in "Release Notes" document in AmiBroker directory. Below is just a short list of few of them:
Highlights of version 5.90
In addition to completely new functionality this version focuses on speed improvements and enhancements of existing functionality. There are hundreds of new features and changes to existing functionality as compared to version 5.80, listed in detail in "Release Notes" document in AmiBroker directory. Below is just a short list of few of them:
Highlights of version 5.80
In addition to completely new functionality this version focuses on incremental improvements and enhancements of existing functionality. There are hundreds of new features and changes to existing functionality as compared to version 5.70, listed in detail in "Release Notes" document in AmiBroker directory. Below is just a short list of few of them:
Highlights of version 5.70
In addition to completely new functionality this version focuses on incremental improvements and enhancements of existing functionality. There are 116 new features and changes to existing functionality as compared to version 5.60, listed in detail in "Release Notes" document in AmiBroker directory. Below is just a short list of few of them:
Highlights of version 5.60
Highlights of version 5.50
Highlights of version 5.40
Highlights of version 5.30
Highlights of version 5.20
Highlights of version 5.10
Highlights of version 5.00
CHANGES FOR VERSION 6.10.0 (as compared to 6.09.0)
CHANGES FOR VERSION 6.09.0 (as compared to 6.08.0)
CHANGES FOR VERSION 6.08.0 (as compared to 6.07.0)
Now when you hover the mouse over @link command you will see the underline
that indicates it is clickable.
It reacts to DOUBLE CLICK (not single click). When you double click it
linked document will be open
@link command can open web pages, local files (both relative and absolute
paths are supported) with Windows-registered program
to open given file type. So if you use
/// @link something.doc
then MS word would be used.
/// @link test.xls
would open test.xls in Excel.
Relative paths refer to AmiBroker working directory.
Html files are open with default browser, txt files are usually open with
Notepad (or whatever application you use).
If file does not exist then you will get an error message.
CHANGES FOR VERSION 6.07.0 (as compared to 6.06.0)
Compression is done by removing repeated values from the sequence as repeated
values
are restored when doing StaticVarGet.
Compression is NOT compatible with non-aligned mode of StaticVarGet.
If compressed array is retrieved by StaticVarGet with align=False, then
repeated values found in original array would not be retrieved.
Turning compression on slows down StaticVarSet (as it needs to do some
extra processing), but does not affect performance of other functions,
so StaticVarGet is equally fast with or without compression.
CHANGES FOR VERSION 6.06.0 (as compared to 6.05.0)
GfxFillSolidRect( 0, 0, pw, ph, colorBlack );
CHANGES FOR VERSION 6.05.0 (as compared to 6.04.0)
CHANGES FOR VERSION 6.04.0 (as compared to 6.03.0)
CHANGES FOR VERSION 6.03.0 (as compared to 6.02.0)
Breakpoints currently work with:
a) regular statements (that end with semicolon). For multi-line statements
place breakpoint at the beginning line of the statement
b) for loops
c) while loops
d) do-while loops (you need to place breakpoint where 'while' clause is
located, it won't break at the 'do' line as it essentially is no-op, if
you want to break at the beginning
of do, just place breakpoint on first statement inside { block }
d) if statements
e) return statements
f) switch/case statements
g) break statements
Breakpoints that you place on other lines, won't trigger. The AFL editor won't allow to place breakpoint on empty line, or line that beginnins with // comment or sole brace
x = "test" +
" second row" +
" third row";
But if you put two statements in single line like this:
x = 1; y = 2;
Then this line would be treated as two steps (each expression x =1; and y=2; separately).
Keyboard shortcuts:
Step Over F10
Step Into F11
CHANGES FOR VERSION 6.02.0 (as compared to 6.01.0)
m = Matrix( 10, 10, 0 );
// do something with matrix
if( m )
{
// some code
}
is equivalent to
if( NOT IsNull(
m[ 0 ][ 0 ] )
)
{
// some code
}
KeepAll flag when it is set to true emulates the behavior of AddToComposite.
It keeps all values that are already present, so if data holes exists in
current symbol,
the bars that are present in static variable but not present in current
symbol remain untouched.
When KeepAll is set to false then only bars that are present in current
symbol are kept. Any other bars that were present in static variable but
not present in currently
processed symbols are removed. That is what normally happens with StaticVarSet().
In fact when KeepAll is set to False, StaticVarAdd can be seen as the
following pseudo code:
EnterCriticalSection
x = Nz( StaticVarGet( "name" ) ); // read exisiting value (and
convert Nulls to zero)
x += Nz( value ); // add value to existing
StaticVarSet( "name", x ); // store updated value
LeaveCriticalSection
The function can be used to create composites like this:
if( status("stocknum")
== 0 )
{
// remove any earier composite values
StaticVarRemove("~Composite");
}
StaticVarAdd( "~Composite", MACD() > Signal()
);
Buy = 0;
NOTES:
1. StaticVarAdd automatically converts all Nulls to zeros (as AddToComposite
does).
2. If you want to replace AddToComposite with StaticVarAdd, keep in mind
that by default AddToComposite skips symbols in group 253. This is done
so composite symbols
are not added to themselves. If you have composite symbols in your database
and want to skip symbols in group 253 you can use
if( GroupID() != 253 ) StaticVarAdd("~Composite", values );
3. Thanks to extensive code tuning, StaticVarAdd generally offers better
performance than AddToComposite which was already blazing fast. Single
threaded StaticVarAdd may be twice as fast as ATC. With 8 threads running
StaticVarAdd may be 4x as fast (it does not scale as much as naive person
may think, because critical section limits performance due to lock contention).
To illustrate the amount of fine tuning applied it can be said that first
'straightforward' version of StaticVarAdd was actually 20 times slower
than ATC.
4. Be careful when using "quickafl" as StaticVarAdd would not
increase 'required bars' (as ATC does), so if you want to actually add
all bars and quick afl is turned on in analysis, it is better to add SetBarsRequired(sbrAll,
sbrAll)
order = Param( "n-th
Order", 10, 1, 16, 1 );
length = 60;
lvb = BarCount - 1;
fvb = lvb - length;
yy = Matrix( length + 1, 1, 0 );
xx = Matrix( length + 1,
order + 1, 1 );
yy = MxSetBlock( yy, 0,
length, 0, 0, Ref( C,
fvb ) );
x = BarIndex() - length/2;
for( j = 1;
j <= order; j++ )
{
xx = MxSetBlock( xx, 0,
length, j, j, x ^ j );
}
xxt = MxTranspose( xx );
aa = MxSolve( xxt @ xx, xxt ) @ yy;
//aa = MxInverse( xxt @ xx ) @ xxt @ yy; // alternative
way
if( aa ) // check
if matrix is not null (so solution exists)
{
rr = Null; // store the fit in
rr
for( i = fvb;
i <= lvb; i++ )
{
rr[i] = aa[0][0];
for(
j = 1; j <= order; j++ )
{
rr[i] += aa[j][0]
* x[ i - fvb ] ^ j;
}
}
if( IsNan(
rr[ fvb ] ) )
{
// our polynomial
yields infinite or not-a-number result due to overflow/underflow
Title = "Polyfit
failed. The order of polynomial is too High";
}
else
{
SetChartOptions( 0, chartShowDates );
SetBarFillColor( IIf( C > O, ColorRGB( 0, 75, 0 ), IIf( C <= O, ColorRGB( 75, 0, 0 ), colorLightGrey )
) );
Plot( rr, "rr", colorWhite, styleLine | styleThick);
}
}
else
{
Title = "Matrix is singular. The order
of polynomial is too high";
}
Plot( C, "", IIf( C > O, ColorRGB( 0, 255, 0 ), IIf( C <= O, ColorRGB( 255, 0, 0 ), colorLightGrey )
), styleDots | styleNoLine );
CHANGES FOR VERSION 6.01.0 (as compared to 6.00.0)
"slow" method uses Laplace expansion
" fast" method uses LU decomposition
" Slow" method for small matrices (1x1, 2x2, 3x3, 4x4) is actually
faster than "fast", equally fast for matrix 5x5 and
slower than "fast" method for matrices larger than 5x5
For this reason "auto" method uses "fast" LU method only for matrices larger than 5x5
LU decomposition is fast but subject to higher numerical errors. "Slow" method
is slower yet produces much more reliable results.
For example Octave/MatLab that use LU decomposition would say that determinant
of singular matrix like this
{ {16, 2, 3, 13}, { 5, 11, 10, 8}, {9, 7, 6, 12}, {4, 14, 15, 1 } }
is -1.4495e-012 due to roundoff errors of LU method.
If you want to calculate determinant using fast (LU decomposition) method, call MxDet with fast parameter set to 2.
CAVEAT: Laplace method has complexity of O(N!) and for this reason, even
if you use method = 1, the maximum dimension for this method is limited
to 10x10.
Matrices larger than that are always calculated using LU method
z = Matrix( 2, 20, 0 );
// first row
z = MxSetBlock( z, 0, 0, 0, 19, Close );
// second row
z = MxSetBlock( z, 1, 1, 0, 19, RSI( 5 ) );
printf("Matrix z\n");
printf( MxToString( z ) );
x = MxGetBlock( z, 0, 1, 0, 19, True );
printf("Items are now in regular array (data series):\n" );
for( i = 0; i < 20; i++ )
printf( NumToStr( x[ i ] ) + "\n" );
z = MxGetBlock( z, 0, 1, 0, 1 ); // retrieve upper 2x2 submatrix
printf("Upper submatrix z\n");
printf( MxToString( z ) );
Note: the function creates new matrix as a result (so source matrix is unaffected unless you do the assignment of the result back to the original variable)
Example 1:
// Create a matrix 6x6
// and fill 4x4 interior (except edges with consecutively increasing numbers)
y = Matrix( 6, 6, 0 );
y = MxSetBlock( y, 1, 4, 1, 4, Cum(1));
printf("Matrix y\n");
printf( MxToString( y ) );
Example 2:
// Create a matrix 2 rows x 20 columns and fill rows 0, 1 with first 20
values of Close and RSI(5) arrays respectively
z = Matrix( 2, 20, 0 );
// first row
z = MxSetBlock( z, 0, 0, 0, 19, Close );
// second row
z = MxSetBlock( z, 1, 1, 0, 19, RSI( 5 ) );
printf("Matrix z\n");
printf( MxToString( z ) );
B can also be a matrix,with each of its column representing different
vector B. This way single call to MxSolve can solve several systems with
same matrix A but different right hand vectors.
If B is a matrix NxM then MxSolve will produce result also having NxM cells
with each column representing single solution.
Example 1:
A = MxFromString("[ 1, 1, 1, 1; 0, 2, 5, -1; 2, 5, -1, 1; 2, 2, 2,
1 ]");
B = MxFromString("[ 7; -5; 28; 13 ]" ); // single vertical vector
B
printf( "Solving A * X = B\n" );
printf("Matrix A\n");
printf( MxToString( A ) );
printf("\nMatrix B\n");
printf( MxToString( B ) );
X = MxSolve( A, B );
printf("\nSolution X\n");
Example 2:
A = MxFromString("[ 1, 1, 1, 1; 0, 2, 5, -1; 2, 5, -1, 1; 2, 2, 2,
1 ]");
B = MxFromString("[ 7, 14 ; -5, -10; 28, 56; 13, 26 ]" ); //
2 right-hand side vertical vectors
printf( "Solving A * X = B\n" );
printf("Matrix A\n");
printf( MxToString( A ) );
printf("\nMatrix B\n");
printf( MxToString( B ) );
X = MxSolve( A, B );
printf("\nSolutions X\n");
printf( MxToString( X ) ); // two solutions
(Highly) Technical note about numerical precision:
Despite the fact that both MxSolve and MxInverse use double precision
arithmetic solving/inverting matrices is subject to numerical precision
of double IEEE
and for example zero result may come up as something like 1.4355e-16 (0.0000000000000001)
due to the fact that double precision is still limited in accuracy (16
digits).
The result of
X = MxInverse( A ) @ B;
although mathematically the same as solving the system of equations, would
yield slightly different result because if you do the inverse the returned
matrix is converted back
to single precision and matrix product is performed with single precision.
When you use MxSolve you are performing all calcs using 64-bit (double)
precision and
only end result is converted back to single precision. So for example polynomial
fit code works better with MxSolve than MxInverse
// Least Squares Polynomial Fit test
order = Param( "n-th Order", 15, 1, 25, 1 );
length = 60;
lvb = BarCount - 1;
fvb = lvb - length;
yy = Matrix( length + 1, 1, 0 );
xx = Matrix( length + 1,
order + 1, 1 );
yy = MxSetBlock( yy, 0,
length, 0, 0, Ref( C,
fvb ) );
x = BarIndex() - length/2;
for( j = 1;
j <= order; j++ )
{
xx = MxSetBlock( xx, 0,
length, j, j, x ^ j );
}
xxt = MxTranspose( xx );
aa = MxSolve( xxt @ xx, xxt ) @ yy;
//aa = MxInverse( xxt @ xx ) @ xxt @ yy; // alternative
way
rr = Null; // store the fit in rr
for( i = fvb; i <= lvb; i++
)
{
rr[i] = aa[0][0];
for( j = 1;
j <= order; j++ )
{
rr[i] += aa[j][0]
* x[ i - fvb ] ^ j;
}
}
SetChartOptions( 0, chartShowDates );
SetBarFillColor( IIf( C > O, ColorRGB( 0, 75, 0 ), IIf( C <= O, ColorRGB( 75, 0, 0 ), colorLightGrey )
) );
Plot( rr, "rr", colorWhite, styleLine | styleThick);
Plot( C, "", IIf( C > O, ColorRGB( 0, 255, 0 ), IIf( C <= O, ColorRGB( 255, 0, 0 ), colorLightGrey )
), styleDots | styleNoLine );
// example
m = MxFromString("[ 9, 5, 6; 8, 7, 3 ]");
printf( MxToString( m ) + "\n\n" );
printf("%g, %g\n\n", MxGetSize( m, 0 ), MxGetSize( m, 1 ) );
m2 = MxSort( m, 0 ) ;
printf( MxToString( m2 ) + "\n\n" );
m3 = MxSort( m, 1 ) ;
printf( MxToString( m3 ) + "\n\n" );
Hint: if you want to sort columns instead you can Transpose/Sort rows/Transpose back.
m = MxFromString("[ 9, 1, 6; 40, 30, 20; 8, 7, 3; 3, 5, 1 ]");
printf("Input matrix\n");
printf( MxToString( m ) + "\n\n" );
printf("Rows %g, Cols %g\n\n", MxGetSize( m, 0 ), MxGetSize( m, 1 ) );
printf("Sorting every row separately\n");
m2 = MxSort( m, 0 ) ;
printf( MxToString( m2 ) + "\n\n" );
printf("Sorting every column separately\n");
m3 = MxSort( m, 1 ) ;
printf( MxToString( m3 )+ "\n\n");
printf("Sorting rows by contents of first column\n");
m4 = MxSortRows( m, True, 0 ) ;
printf(MxToString( m4 )+ "\n\n");
printf("Sorting rows by contents of second column\n");
m5 = MxSortRows( m, True, 1 ) ;
printf(MxToString( m5 )+ "\n\n");
CHANGES FOR EARLIER VERSIONS ARE DOCUMENTED IN RELEASE NOTES DOCUMENT THAT YOU CAN FIND IN AMIBROKER INSTALLATION FOLDER.