I managed to port the regression indicator. The syntax was very unfamiliar to me at first but it is so logical and structured that it took no time at all to figure it out.
I performed a rudimentary benchmark on the execution speed (during backtest) and found a 64% increase with the Lazarus dll as opposed to iCustom()!!
7bit, I followed the instructions you gave on changing the compiler options to produce a smaller .dll file. What I am interested in is not necessarily small size, but fast execution speed.
Are there any other compiler settings I should know about to produce a faster-computing .dll file?
I am quite impressed with the speed increase as it is, but of course I thirst for more!
.. a question:
I realize that MT4 won't integrate with a 64bit dll, but can't I make a 32bit dll act as a middle man to pass data between MT4 and the 64bit dll? Then I could possibly squeeze out more processing power.
Also, how does processor parallelization play in? I know a single instance of MT4 can only use 1 processor core; can this limitation be avoided with free pascal?
If anyone is interested, here is the i-Regr port to free pascal that I made. It returns the current bar's regression, the last bar's regression, and the standard deviation coefficient, by reference to the array "vars." Any tips to speed it up would be greatly appreciated!
Lazarus code:
MQL4 code:
I performed a rudimentary benchmark on the execution speed (during backtest) and found a 64% increase with the Lazarus dll as opposed to iCustom()!!
7bit, I followed the instructions you gave on changing the compiler options to produce a smaller .dll file. What I am interested in is not necessarily small size, but fast execution speed.
Are there any other compiler settings I should know about to produce a faster-computing .dll file?
I am quite impressed with the speed increase as it is, but of course I thirst for more!
.. a question:
I realize that MT4 won't integrate with a 64bit dll, but can't I make a 32bit dll act as a middle man to pass data between MT4 and the 64bit dll? Then I could possibly squeeze out more processing power.
Also, how does processor parallelization play in? I know a single instance of MT4 can only use 1 processor core; can this limitation be avoided with free pascal?
If anyone is interested, here is the i-Regr port to free pascal that I made. It returns the current bar's regression, the last bar's regression, and the standard deviation coefficient, by reference to the array "vars." Any tips to speed it up would be greatly appreciated!
Lazarus code:
Inserted Code
library regression;
Uses Math;
{$mode objfpc}{$H+}
type
TCandle = packed record
time: LongInt; // POSIX timestamp
open,
high,
low,
close,
volume: Double;
end;
THistory = array[0..MaxLongInt div SizeOf(TCandle) - 1] of TCandle;
PHistory = ^THistory;
TBuffer = array[0..MaxLongInt div SizeOf(Double) - 1] of Double;
PBuffer = ^TBuffer;
TVal = array[0..2] of Double;
PVal = ^TVal;
var i0: LongInt = 0;
const
EMPTY_VALUE = $7FFFFFFF;
function regression(history: PHistory; period: LongInt; degree: LongInt; index: LongInt; var vals: PVal): Double;
var
sum: Double;
i: LongInt;
ai: array[0..9,0..9] of double;
b: array[0..9] of double;
x: array[0..9] of double;
sx: array[0..19] of double;
ip: LongInt;
p: LongInt;
n: LongInt;
f: LongInt;
ii: LongInt;
jj: LongInt;
kk: LongInt;
ll: LongInt;
nn: LongInt;
sq: Double;
qq: Double;
mm: Double;
tt: Double;
mi: LongInt;
fx: array of Double;
begin
if index < period then exit(EMPTY_VALUE);
if period < 1 then exit(history^[index].Close);
sum := 0;
ip:=period;
p:=ip;
sx[1] :=p+1;
nn := degree+1;
SetLength(fx,p+1);
mi := 1;
for mi:=1 to nn*2-2 do
begin
sum:=0;
for n:=i0 to i0+p do
begin
sum := sum+ power(n,mi);
end;
sx[mi+1]:=sum;
end;
for mi:=1 to nn do
begin
sum:=0.00000;
for n:=i0 to i0+p do
begin
if (mi = 1) then sum:= sum+ history^[index-n].Close
else sum:= sum+ (history^[index-n].Close * power(n,mi-1));
end;
b[mi]:=sum;
end;
for jj:=1 to nn do
begin
for ii:=1 to nn do
begin
kk:=ii+jj-1;
ai[ii,jj]:=sx[kk];
end
end;
for kk:=1 to nn-1 do
begin
ll:=0;
mm:=0;
for ii:=kk to nn do
begin
if (Abs(ai[ii,kk])>mm) then
begin
mm:=Abs(ai[ii,kk]);
ll:=ii;
end;
end;
if ll=0 then exit(EMPTY_VALUE) else
begin
if ll<>kk then
begin
for jj:=1 to nn do
begin
tt:=ai[kk,jj];
ai[kk,jj]:=ai[ll,jj];
ai[ll,jj]:=tt;
end;
tt:=b[kk];
b[kk]:=b[ll];
b[ll]:=tt;
end;
end;
for ii:=kk+1 to nn do
begin
qq:=ai[ii,kk]/ai[kk,kk];
for jj:=1 to nn do
begin
if jj=kk then ai[ii,jj]:=0
else ai[ii,jj]:=ai[ii,jj]-qq*ai[kk,jj];
end;
b[ii]:=b[ii]-qq*b[kk];
end;
end;
x[nn]:=b[nn]/ai[nn,nn];
for ii:=nn-1 Downto 1 do
begin
tt:=0;
for jj:=1 to nn-ii do
begin
tt:=tt+ai[ii,ii+jj]*x[ii+jj];
x[ii]:=(1/ai[ii,ii])*(b[ii]-tt);
end;
end;
for n:=i0 to i0+p do
begin
sum:=0;
for kk:=1 to degree do
begin
sum:=sum+x[kk+1]*power(n,kk);
end;
fx[n]:=x[1]+sum;
end;
sq:=0.0;
for n:=i0 to i0+p do
begin
sq:=sq+power(history^[index-n].Close-fx[n],2);
end;
sq:=sqrt(sq/(p+1));
vals^[0] := fx[0];
vals^[1] := fx[1];
vals^[2] :=sq;
end;
procedure updateBuffer(history: PHistory; bars: LongInt; degree: LongInt; period: LongInt; vals: PVal); stdcall;
begin
regression(history, period, degree, bars-1, vals);
end;
exports
updateBuffer;
begin
end. MQL4 code:
Inserted Code
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_color1 Red
#property indicator_color2 Red
#property indicator_color3 Red
#import "regression.dll"
void updateBuffer(double &history[][6],int bars, int degree, int period, double &vals[3]);
#import
extern int period=40;
extern double kstd =1;
extern int degree = 1;
double buffer[];
double up[];
double dn[];
double history[][6]; // this will later point to the complete chart history
int init(){
// set up the indicator buffer
SetIndexStyle(0, DRAW_LINE);
SetIndexBuffer(0, buffer);
SetIndexLabel(0, "Regression");
SetIndexStyle(1, DRAW_LINE);
SetIndexBuffer(1, up);
SetIndexLabel(1, "Regression + STD");
SetIndexStyle(2, DRAW_LINE);
SetIndexBuffer(2, dn);
SetIndexLabel(2, "Regression - STD");
ArrayCopyRates(history, NULL, 0);
}
int start(){
double vals[3];
updateBuffer(history, Bars, degree, period, vals); //populate array "vals" with regression values.
buffer[0] = vals[0]; //vals[0] is regression's value at current bar
up[0] = vals[0]+(vals[2]*kstd); //vals[1] is regression's value at last bar
dn[0] = vals[0]-(vals[2]*kstd); //vals[2] is the standard deviation value prior to multiplication by kstd (raw std value)
} Attached File(s)