Australian (ASX) Stock Market Forum

Creating a 32 bit "C" library of TA functions for use with other software

Joined
12 February 2014
Posts
138
Reactions
25
Thought I'd start a new thread on TA (Technical Analysis) functions written in "C" that can be used by other 32 bit software. The 32 bit software I hopefully demonstrate in later posts are 32 bit Perl, Excel 2003 and Metatrader 4, but probably could be extended to say 32 bit versions of Python, Ruby, Maple, Mathematica, R, Metastock, Amibroker, MathLab, WealthLab etc. Creating a library is useful because you should expect the same output results given the same input data for say a moving average no matter what software calls your functions.

What I've done is written some basic moving average "C" code (SMA,EMA,SMMA,LWMA) using the free codeblocks IDE (Integrated Development Environment) that comes with the free C/C++ compiler and used this for my library. In later posts, I explain in detail, the steps involved in creating libraries for use with other software. These steps are:

1) Install codeblocks IDE with free C/C++ compiler
2) Start a new project and compile "C" files written by me to create a 32 bit "C" static link library called "libtal.a"
3) Create a "C++" test project (console application) with "main.cpp" that links to the library functions created in "libtal.a"
4) Create a 32 bit Windows DLL (dynamic link library) that links to the library functions created in "libtal.a"
5) Test 32 bit Windows DLL with 32 bit software packages Perl and Excel 2003.
6) Test 32 bit Windows DLL with MT4 (Metatrader 4).
7) Creating a 32 bit Amibroker DLL that links to my library functions created in libtal.a

Special Note: All work done in the 6 steps described above was carried out on a 32 bit Windows XP platform.

1) Installing codeblocks IDE with free C/C++ compiler

To start off with, you will need to go to the following website

http://www.codeblocks.org/

Navigate to downloads/binaries and download the latest codeblocks with mingw. As of 23/Feb/2015, the latest is 13.12 and this is the one I'll be using for this thread. So now we download the file "codeblocks-13.12mingw-setup.exe" and install codeblocks. This installation contains both the IDE and the free 32 bit C/C++ compiler. The 32 bit C/C++ compiler is what is needed to compile my project code.

When you have successfully installed codeblocks, it should look something like this when you open it up:

01_01_CB_Inst.PNG
 
2) Start a new project and compile "C" files written by me to create a 32 bit "C" static link library called "libtal.a"

The first thing we need to do is create a Directory/Folder to where we want to store our Projects. All my project files are stored in the following directory:

D:\Dev\TA

In codeblocks, Select File/New/Project, then Select Static Library (may need to scroll down) like so:

02_01_CB_talSLL.PNG

Click Go
Click Next if it says "Skip this page next time".
Now click browse button "..." and select where your project files will be stored (i.e. "D:\Dev\TA").
In the Project title field type "tal" and take note of how the other fields are updated. Your dialog box should look something like this:

02_02_CB_talSLL.PNG

Click Next
Make sure "Create Release configuration" is checked and uncheck "Create Debug configuration". You can create a Debug version later if you want too.
Click Finish

Now close codeblocks (save if it asks you to) and navigate in Windows explorer to where the Project files (including the default "main.c") were created. In my case "D:\Dev\TA\tal".
Delete the default "main.c" that was created by codeblocks.
Copy my attached files (below) to this location and remove .txt extension from all attached files.

Now open codeblocks and then open your project (File/Open). The Project file name is tal.cbp (as seen in previous diagram). A quick way is to double click on tal.cbp in Windows Explorer.
In the Projects Pane, expand the tree by clicking on all the plus signs "+" where the word "Workspace" is located.
Right click on "tal" and select Add files (or you could select "tal" and then menu option Project/Add Files), then add the 2 new files "tal.c" and "tal.h" (Hold down Ctrl key).
Right click on "main.c" and select Remove file from project as we deleted it.
Double click (or right click/open tal.c) on tal.c in the tree and the code should be displayed on the right.
Select Menu Option Build/Build and now your codeblocks project should look something like this:

02_03_CB_talSLL.PNG

In Windows explorer navigate to ...\bin\Release Folder and you should see the file "libtal.a". For me it is in "D:\Dev\TA\tal\bin\Release". This is the library file containing the compiler code for all my moving averages functions and will be used in the projects following.

Building a project compiles all non-compiled or changed (since last compiled) source files and creates the library. If we only want to check the open file for errors then we should choose menu option Build\Compile. You cannot execute any of the code (by selecting Build\Run) yet as all we have done is create a library. We need to create an exe file from this library (next project).

Note: Please remove .txt extension from all attached files.
 

Attachments

  • tal.h.txt
    2 KB · Views: 65
  • tal.c.txt
    9 KB · Views: 57
3) Create a "C++" test project (console application) with "main.cpp" that links to the library functions created in "libtal.a"

To avoid confusing projects for now, lets close the project tal (saving changes if asked) by right clicking on tal and selecting close project. Make sure you save changes (if asked) as the changes involved adding my files.

Select File/New/Project, then select Console Application as we now want to test the lib functions by building a basic console executable file (.exe) that runs in the command line.
Click Go
Click Next if it says "Skip this page next time".
Select "C++" and click Next.
Now click browse button "..." and select the same Folder as last project for storing your project files (i.e. "D:\Dev\TA"). When we enter a different Project title a new sub-directory will be created under that name.
In the Project title field type "taltest". Your dialog box should look something like this:

03_01_CB_taltest.PNG

Click Next
Make sure "Create Release configuration" is checked and uncheck "Create Debug configuration".
Click Finish

Now close codeblocks (save if it asks you to) and navigate in Windows explorer to where the Project files (including the default "main.cpp") were created. In my case "D:\Dev\TA\taltest".
Delete the default "main.cpp" that was created by codeblocks.
Copy my attached file (main.cpp.taltest.txt) below to this location and rename the file to main.cpp.

Now open up Project file taltest.cbp in codeblocks. There is no need to add file main.cpp to the project because it was already added by default. We could say that we just modified the file.

In the Projects Pane, expand the tree by clicking on all the plus signs "+" where the word "Workspace" is located.
Double click (or right click/open main.cpp) on main.cpp in the tree and the code should be displayed on the right.
Select Build/Compile and notice you will get the error message "tal.h: No such file or directory". This is because at the top of the file main.cpp we have the statement:

#include "tal.h"

"tal.h" is the header file containing function prototype declarations of my static link library and we have not told the compiler where to find it. So to correct the problem,

Select "Project/Build Options"
Select taltest in the tree as we want this to apply to all builds (only 1 in this case).
Select tab Search directories
Select tab Compiler
click Add at the bottom and type "..\tal" like so:

03_02_CB_taltest.PNG

Click ok
Click ok

Alternatively you could of edited main.cpp and changed code to #include "..\tal\tal.h", which is fine, but if this was a large project, you would have to edit a lot of files and if the original "tal" project path changed, then you would have to edit all the files again. Not such a problem in this case.

".." means go back a directory from the current working directory so we go from "D:\Dev\TA\taltest" to "D:\Dev\TA". We do things this way because hard coding the directory path is a bad idea for obvious reasons.

Select Build/Compile and everything seems okay from a compiler point of view :)
Select Build/Build and we seem to get a lot of undefined reference errors. This is because we haven't told the linker where the library functions are stored (in "libtal.a"). So here is what we need to do:

Select "Project/Build Options"
Select Release in the tree as we want this to apply to release builds because libtal.a is built as a release build. If we wanted debug builds then we would have to also create a debug library in previous project.
Select tab Linker settings
click Add at the bottom and type "..\tal\bin\Release\libtal.a" like so:

03_03_CB_taltest.PNG

Click ok
Click ok

Select Build/Build and we should get success. That is, no compiler errors, no linker errors and an executable file created in directory ...\bin\Release called taltest.exe :)

Select Build/Run. The command line console will open up and you will see my library code being tested from function main() in "main.cpp". At the bottom of function main() you will see that we are outputting results of function calls to my library. Arrays src1f[] and src1d[] contain same fixed array values specified below main() in functions SetInputArrayFloat() and SetInputArrayDouble() respectively. Whilst arrays smaf[] and smad[] contain the simple moving average values of src1f[] and src1d[] respectively. You can play around with other variables by changing smaf and smad to emaf and emad respectively. The main purpose of the console application is to test the library so that if you make a change in the library, you can best check for errors here before updating more interesting projects like DLL's in my next post.

Please remove .taltest.txt extension
 

Attachments

  • main.cpp.taltest.txt
    37.4 KB · Views: 43
4) Create a 32 bit Windows DLL (dynamic link library) that links to the library functions created in "libtal.a"

Again, to avoid confusing projects for now, lets close the project taltest (saving changes if asked) by right clicking on taltest and selecting close project. Make sure you save changes (if asked) as the changes involved adding my files.

Select File/New/Project, then select Dynamic Link Library.
Click Go
Click Next if it says "Skip this page next time".

Now click browse button "..." and select the same Folder as last project for storing your project files (i.e. "D:\Dev\TA").
In the Project title field type "actal32". Your dialog box should look something like this:

04_01_CB_actal32dll.PNG

Click Next
Make sure "Create Release configuration" is checked and uncheck "Create Debug configuration".
Click Finish

Now close codeblocks (save if it asks you to) and navigate in Windows explorer to where the Project files (including the default "main.cpp") were created. In my case "D:\Dev\TA\actal32".
Delete the default files "main.cpp" and "main.h" that was created by codeblocks.
Copy my attached files main.cpp.taldll.txt, main.h.taldll.txt below to this location and rename the files to main.cpp and main.h.

Now open up project file actal32.cbp in codeblocks. There is no need to add files to the project as they were already created by default.

In the Projects Pane, expand the tree by clicking on all the plus signs "+" where the word "Workspace" is located.

Double click (or right click/open main.cpp) on main.cpp in the tree and the code should be displayed on the right. All that I have done here is added a wrapper function for each of my functions in my static link library and called the corresponding function in my static link library.
Double click (or right click/open main.h) on main.h in the tree and the code should be displayed on the right. As you can see in my declarations, I have added 2 key words: DLL_EXPORT and WINAPI. Early on in the code we force #define DLL_EXPORT __declspec(dllexport), which is required by microsoft dlls when exporting functions from a dll. The WINAPI is just a macro for __stdcall which tells the compiler the rules that apply for pushing arguments onto the stack and getting a return value. This needs to be done for standard 32 bit Windows applications to be able to communicate with dlls.

As with the previous project/post, you are going to need to setup where to find the include file "tal.h" and library "libtal.a". Please follow the steps in last post for this as they are exactly the same.

After that, Select Build/Build and we should get success and a dll file created in directory ...\bin\Release called actal32.dll. We are not finished yet, because the dll contains mangled function names. If you look in ...\bin\Release\libactal32.def you will see the following:

(Note: If you can't find the .def file, you may need to go to menu option Project/Properties, select tab Build targets and check "Create .DEF exports file" then Build/Rebuild.)

EXPORTS
TAL_EMA2_DLL@16 @1
TAL_EMA_DLL@16 @2
TAL_GetNullVal_DLL@0 @3
TAL_Init_DLL@8 @4
TAL_LWMA_DLL@16 @5
TAL_Reverse_DLL@8 @6
TAL_SMA_DLL@16 @7
TAL_SMMA_DLL@16 @8
TAL_SetNullVal_DLL@8 @9
TAL_Shift_DLL@12 @10

which contains funny function names and to fix the problem we need to do the following:

Select "Project/Build Options"
Select actal32 in the tree.
Select Linker settings
Click on the Other linker options text box and type the following "-Wl,--add-stdcall-alias". It should look like this:

04_02_CB_actal32dll.PNG

Click ok

Select Build/Rebuild. Rebuild is needed as no source files were changed.
If you look in ...\bin\Release\libactal32.def you will see the following:

EXPORTS
TAL_EMA2_DLL = TAL_EMA2_DLL@16 @1
TAL_EMA2_DLL@16 @2
TAL_EMA_DLL = TAL_EMA_DLL@16 @3
TAL_EMA_DLL@16 @4
TAL_GetNullVal_DLL = TAL_GetNullVal_DLL@0 @5
TAL_GetNullVal_DLL@0 @6
TAL_Init_DLL = TAL_Init_DLL@8 @7
TAL_Init_DLL@8 @8
TAL_LWMA_DLL = TAL_LWMA_DLL@16 @9
TAL_LWMA_DLL@16 @10
TAL_Reverse_DLL = TAL_Reverse_DLL@8 @11
TAL_Reverse_DLL@8 @12
TAL_SMA_DLL = TAL_SMA_DLL@16 @13
TAL_SMA_DLL@16 @14
TAL_SMMA_DLL = TAL_SMMA_DLL@16 @15
TAL_SMMA_DLL@16 @16
TAL_SetNullVal_DLL = TAL_SetNullVal_DLL@8 @17
TAL_SetNullVal_DLL@8 @18
TAL_Shift_DLL = TAL_Shift_DLL@12 @19
TAL_Shift_DLL@12 @20

Notice we now have a dll with unmangled function names in it like TAL_EMA_DLL. This is what's needed to require function calls from standard 32 bit applications like excel 2003.

To get a better understanding (and you don't have to do this because the dll has been created) you could download the Dependency Walker from http://www.dependencywalker.com/ and view the dll contents from that. Here is what I get when I look at the dll functions through Dependency Walker:

04_03_CB_actal32dll.PNG

A common mistake that I have made in the past is not update the prototype dll function declarations in main.h when I make a change to the main.cpp function arguments and this gives garbage function names when a build is run. Dependency Walker is a good tool for checking these types of errors.

Now close project actal32 (saving changes if asked) by right clicking on taltest and selecting close project. Make sure you save changes (if asked) as the changes involved adding my files.

Please remove .taldll.txt extension from all attached files.
 

Attachments

  • main.h.taldll.txt
    1.3 KB · Views: 43
  • main.cpp.taldll.txt
    2 KB · Views: 41
5) Test 32 bit Windows DLL with 32 bit software packages Perl and Excel 2003.

Now to test the dll created from the project in the previous post, navigate to where your created dll file "actal32.dll" is and place the below attachments (removing .txt extension) into this directory like so:

05_01_CB_actal32dlltest.PNG

Ofcourse you need 32 bit Perl installed to run actal32test.pl and excel 2003 or above installed to run actal32test.xls.

When you run the Perl script from the command line, you will get the following:

05_02_CB_actal32dlltestPERL.GIF

and here are the results of output.csv when you open it up in a spreadsheet application such as excel:

05_03_CB_actal32dlltestPERL.PNG

When you open up actal32test.xls (Enabling Macros) in excel and click Run TA Macros, here is the result:

05_04_CB_actal32dlltestEXCEL..PNG

Wow same results :)
 
Please remove .txt extension from attached Perl script actal32test.pl.txt
 

Attachments

  • actal32test.pl.txt
    22 KB · Views: 20
  • actal32test.xls
    79 KB · Views: 23
6) Test 32 bit Windows DLL with MT4 (Metatrader 4).

Obviously, to test DLLs with MT4, you need to install MT4. So assuming you have, please place the attached file acMA.mq4 in your ...\MQL4\Indicators folder and your newly created dll file actal32.dll in your ...\MQL4\Libraries folder like so:

06_01_CB_actal32dlltestMT4.PNG

Before we apply the indicator, we need to allow DLL imports from menu option Tools/Options then Expert Advisors tab. Now open up a chart and place my indicator (from Navigator pane) on it and you should see an options dialog like this (Click on Inputs tab):

06_02_CB_actal32dlltestMT4.PNG

Select/Enter your options, click ok and indicator should be placed on the chart like so:

06_03_CB_actal32dlltestMT4.PNG

You can view the mq4 source code if you want with the MetaQuotes Language Editor.

Hopefully all this works :)
 

Attachments

  • acMA.mq4
    15.3 KB · Views: 29
LOL - that all looks a little complex. :D

Not for a systems developer; if you're a professional, it's bread 'n' butter stuff.

I commend you, ajcode, for offering open code. :xyxthumbs
Among our thousands of members, you may well find a few kindred spirits.
"kindred" I might be too; but sadly too old to start on a new project like that.
 
7) Creating a 32 bit Amibroker DLL that links to my library functions created in libtal.a

Before we create an Amibroker DLL, lets start with gaining knowledge from background reading described between the asterisks borders below.

********************************************************************************
First, download the Amibroker Development Kit (ADK) and have a read of section 2 (AFL plugins) in adk.html (from extracting ADK.zip file).

After reading section 2 (AFL plugins) and looking at source code in "Sample\Functions.cpp", let us consider the following Amibroker DLL code:

FunctionTag gFunctionTable[] = {
"TestFn9", { VTestFn9, 4, 3, 2, 0, NULL }
};

This to me means the following:

"TestFn9" is the function that is to be called from inside Amibroker (AFL code) and "VTestFn9" is it's corresponding DLL function.

In Amibroker (AFL code) we would be calling a function with 4 float arrays, followed by 3 strings and 2 floats like so:

x = TestFn9(float array, float array, float array, float array, string, string, string, float, float)

where float array could be something like open,high,low,close,
a string here is just an array of single byte characters that are null terminated (i.e. ending with '\0'),
and a float is just a single float value.

We know this from the defined AmiVar structure:

typedef struct AmiVar
{
___int type;
___union
___{
______float val;
______float *array;
______char *string;
______void *disp;
___};
} AmiVar;

The return value is also an AmiVar variable which could be any of the above defined union types from an Amibroker interface perspective.

Now all Amibroker DLL function code must have the same 2 defined arguments, so function VTestFn9 has to look something like this:

AmiVar VTestFn9(int NumArgs, AmiVar *ArgsTable)
{
AmiVar result;
.
. // Function Code
.
return result;
}

So in the above example, when Amibroker AFL code calls function "TestFn9", I believe the following takes place in "VTestFn9":

NumArgs = 9
ArgsTable[0].array contains 1st argument which is an array of floats.
ArgsTable[1].array contains 2nd argument which is an array of floats.
ArgsTable[2].array contains 3rd argument which is an array of floats.
ArgsTable[3].array contains 4th argument which is an array of floats.
ArgsTable[4].string contains 5th argument which is an array of chars.
ArgsTable[5].string contains 6th argument which is an array of chars.
ArgsTable[6].string contains 7th argument which is an array of chars.
ArgsTable[7].val contains 8th argument which is a float.
ArgsTable[8].val contains 9th argument which is a float.

One final note here is that Amibroker uses float arrays, so if my library code is to be called, I have to call the float versions and not the usual double versions. No problems there :)
********************************************************************************

The process for creating a 32 bit Amibroker DLL is the same as for creating a standard Windows DLL in step 4 (Create a 32 bit Windows DLL), but you only have to go up to the part that says Select Build/Build after setting the header path for "tal.h" and location of "libtal.a".

So the only changes I need to talk about are the Sample Amibroker files added to the project, which can be best explained from a picture and some small modifications to the files. So after you download ADK.zip and create a DLL project in codeblocks (Project title say "amital32") in the same directory location as your other projects (i.e. "D:\Dev\TA"), you need to copy and add the following files from the (extracted ADK.zip) Sample directory:

Important: Please use my "Functions.cpp" (removing .amitaldll.txt extension) attached below instead of the one from the (extracted ADK.zip) Sample directory as this contains the wrapper code for my library functions in "libtal.a".

07_01_CB_amital32dll.PNG

Like the previous DLL, we want to use dllexporting, so in "Plugin.h", just before #ifdef _USRDLL, please type the following:

#ifndef _USRDLL /* Force dllexporting */
#define _USRDLL
#endif

In "plugin.cpp", you may want to also change the Plugin & Vendor names like so:

#define PLUGIN_NAME "AmiTal32"
#define VENDOR_NAME "AussieStockForum"

After that, you should be able to Select menu option Build/Build without error.

So basically, if you were using a 32 bit version of Amibroker, you could call my functions (defined in "Functions.cpp") like so:

astr = HelloWorld0(); // assigns astr the value "Hello World".
ret = ACSNV1(nv); // sets a null value for say the start of a moving average.
sma = ACSMA2(priceArray,period); // call a simple moving average given a period.
ma = ACMA3(priceArray,period,matype); // same as ACSMA2 but option to choose the type of moving average (i.e. 1=SMA,2=EMA,3=SMMA,4=LWMA).

Note: The number in front of the function name is actually the number of arguments the function has :).

Cheers,

Andrew.
 

Attachments

  • Functions.cpp.amitaldll.txt
    3.8 KB · Views: 49
Whilst the above Functions.cpp is quite fine for Amibroker use, for the benefit of ASF members, I have made some slight semantic changes to better serve as a template for other Amibroker DLL projects. These changes include comment changes, checking memory allocation was successful in VHelloWorld0() and making sure that valid float values are converted to integers. For example, when you assign a float variable the value 16,777,217.0, which is way less than the value of MAX_INT (2,147,483,647), it is represented as 16,777,216 (1 less) and when you convert it to an int variable, that int variable is assigned the value 16,777,216 (1 less). So it cannot be guaranteed that a float can be represented as an integer correctly passed this value (2^24). This is unfortunately the limitation on floats:(

Luckily we can deal with integers and doubles in DLL code :)

The attached file contains my changes to Functions.cpp.

Cheers,

Andrew.
 

Attachments

  • Functions.cpp.amitaldll2.txt
    4.4 KB · Views: 39
8) Test 32 bit Windows DLL created in step 4 with 32 bit PYTHON :xyxthumbs

Assuming you have 32 bit Python installed, to test the dll created in step 4 with Python, navigate to where your created dll file "actal32.dll" is and place the below attachment (removing .txt extension) into this directory like so:

08_01_CB_actal32dlltest.PNG

When you run the Python script from the command line, you will get the following:

08_02_CB_actal32dlltestPYTHON.GIF

and here are the results of output.csv when you open it up in a spreadsheet application such as excel:

08_03_CB_actal32dlltestPYTHON.PNG

This agrees with the other results displayed in Step 5. Not bad for my first ever Python script :xyxthumbs

Please remove .txt extension from attached Python script actal32test.py.txt
 

Attachments

  • actal32test.py.txt
    20.9 KB · Views: 24
7) Creating a 32 bit Amibroker DLL that links to my library functions created in libtal.a

The process for creating a 32 bit Amibroker DLL is the same as for creating a standard Windows DLL in step 4 (Create a 32 bit Windows DLL), but you only have to go up to the part that says Select Build/Build after setting the header path for "tal.h" and location of "libtal.a".
.
.
.
Like the previous DLL, we want to use dllexporting, so in "Plugin.h", just before #ifdef _USRDLL, please type the following:

#ifndef _USRDLL /* Force dllexporting */
#define _USRDLL
#endif

.
.
.

There seems to be some confusion in my above Amibroker post. When I say the steps are the same as in 4), I mean replace the files main.cpp and main.h with downloaded amibroker files (e.g. Plugin.xxx, etc.). Also, before you compile/build, you need to make the above change "#ifndef _USRDLL" etc., otherwise you will get compile errors like:

error function 'int getplugininfo(plugininfo*)' definition is marked dllimport

We need to do this so that the compiler knows we are exporting functions from the dll. Amibroker will then import these functions. I should of made this more clearer (My bad). If you consider yourself a novice programmer and have got this far, then give yourself a pat on the back because this is pretty complicated stuff. Having said that, you still need to learn how to program in c/c++, but you can always look up doc on the web to easily improve your skills and knowledge in that department.

I guess most people put DLL's in the too hard basket, but it's really just a configuration setup to get you going. Once you create a sample DLL and output say "Hello World" in the calling application (eg., Amibroker, Excel, Python, Perl etc.), then all you need to do is learn to code in C/C++ and know a little bit about the calling application.

Cheers,

Andrew.
 
2) Start a new project and compile "C" files written by me to create a 32 bit "C" static link library called "libtal.a"

For the sake of Amibroker DLL performance reasons, I have attached file tal.c.2.txt, which is to be used in place of tal.c.txt file in the 2nd step (static link library). You just need to remove the ".2.txt" extension to compile and re-build the library libtal.a. Then from this you can re-build the Amibroker DLL amital32.dll.

As you are aware, Amibroker uses floats (not doubles) when dealing with price arrays such as close[]. Originally what I was doing was converting the float arrays to double arrays to keep the accuracy in the calculations and then converting the resulting double arrays back to floats. This is very time consuming and is embarrassing when comparing the timed results to afl code as proved by people who have followed my thread. The attached file does the calculations in floats and you should hopefully see a more respectable performance :). Could easily be made more efficient, but this will do for now :cool:.
 

Attachments

  • tal.c.2.txt
    13 KB · Views: 37
Hi,
i test this amazing work on amibroker .
because time on amibroker was affected by various parameters(click of mouse example) i sets a refresh of 0.1 sec on the top of every formula code on afl(even those that call the libraries).

to be sure that every formula of libraries (old and new)was affected alike i create a copy of the program and i changed the name of the calling functions i use so to charge into amibroker 2 plugin that call different libraries, one for the first slower and one for last (modified) faster .
in this way I was able to upload to video 3 instances at the same time, they do the same thing but in a different way (afl, old library and the new improved)

tested on daily timeframe data EOD

//---code for moving averages MA, EMA, SMMA on amibroker
RequestTimedRefresh( 1 , False );
Plot(MA(C,20),"",colorBlue,styleLine);
Plot(EMA(C,20),"",colorRed,styleLine);
// ---SMMA
MA_Period=Param("Period", 20, 1);
ssma = MA(C, MA_Period);
for(i=MA_Period+1; i<BarCount; i++)
{
iSum = ssma[i-1]*(MA_Period-1)+Close;
ssma = iSum/MA_Period;
}
Plot(ssma, "SSMA", colorYellow, styleLine);
//-----------------------------------------------


//---code for moving averages MA, EMA, SMMA on amibroker calling libraries
//--- first library slow

RequestTimedRefresh( 1 , False );
nv=0;
priceArray=C;
period=20;
astr = HelloWorld0(); // assigns astr the value "Hello World".
ret = ACSNV1(nv); // sets a null value for say the start of a moving average.
sma = ACSMA2(priceArray,period); // call a simple moving average given a period.
MAn = ACMA3(priceArray,period,2);
MAn1 = ACMA3(priceArray,period,3);
Plot(sma,astr,colorBlue,styleLine);
Plot(MAn,"sec",colorRed,styleLine);
Plot(MAn1,"sec1",colorYellow,styleLine);

//----modified lines for last Quick library simpli changed from ACSMA2 to ACSMA22 and 3 to 33
sma = ACSMA22(priceArray,period); // call a simple moving average given a period.
MAn = ACMA33(priceArray,period,2);
MAn1 = ACMA33(priceArray,period,3);
//-----------------------
visually and in value the indicators are identical ...
but as times of executions there are some new :

total time 0.0056 sec,afl exec time 3.8ms (setup 0.3ms) (67%), # extra bars 30, fwd 0 - old library
total time 0.0026 sec,afl exec time 0.7ms (setup 0.2ms) (26%), # extra bars 110, fwd 0 - AFL code
total time 0.0024 sec,afl exec time 0.4ms (setup 0.2ms) (15%), # extra bars 30, fwd 0 - new library

and if i rise the period to video 13 years daily data

total time 0.0397 sec,afl exec time 35.8ms (setup 0.5ms) (90%), # extra bars 30, fwd 0 - old library
total time 0.0073 sec,afl exec time 3.4ms (setup 0.4ms) (46%), # extra bars 110, fwd 0 - AFL code
total time 0.0048 sec,afl exec time 0.6ms (setup 0.3ms) (13%), # extra bars 30, fwd 0 - new library

so the new code on C++ external library it's faster than afl code and the oldest library.
and this code is very simple, not elaborate calculations, simple moving averages.


AJcode you're a myth ! thanks for your help !
 
Thanks Andrew,

created a 64bit dll using Visual Studio / 64bit Amibroker. Everything worked a treat and was up and running in an hour or so. Definately saved me a lot of messing around time

Cheers
 
Creating a 64 bit "C" library of TA functions for use with other software

Thanks for your input folks. Wow works on VS 64 bit. That's got to attract attention :D.

For those wanting to install the free 64 bit compiler for Codeblocks, you need to first download the stand alone 32 bit Codeblocks IDE (no compiler) "codeblocks-13.12-setup.exe" and then install that on your 64 bit computer.

Then you need to download and install a 64 bit free compiler such as "mingw-w64-install.exe" from I think "http://mingw-w64.org/" or "Sourceforge".

When Codeblocks and compiler are both installed, you need to configure the compiler settings in Codeblocks under Menu option "Settings/Compiler". You basically need to tell Codeblocks where your compiler executables are installed. The diagram below shows an example of configuring the mingw-w64 compiler:

09_01_CB_Config1.png

One other thing you need to configure for mingw-64 is (-static) shown in the following diagram:

09_02_CB_Config2.png

Which includes libs such as "libgcc_s_seh-1", "zzlibstdc++-6" and "zzlibwinpthread-1". I think from memory, these are the mandatory libraries that are needed to build your programs.

I did this a while ago so if I've misssed a few steps, please feel free to add extra comments/thoughts.

Note: You do not need to do that extra step when creating regular dlls, because I think there is only one calling convention when programming in 64 bit.

Cheers,

Andrew.
 
Thanks Andrew. This thread really made a difference in my system development workflow.

Got an error when building amital32 using the GNU GCC Compiler:
C++ warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]​

Sorted it out with changing the following in the Plugin.h file (change in bold):

typedef struct FunctionTag
{
const char *Name; // was char *Name
FunDesc Descript;
} FunctionTag;​

I have no idea what I'm doing so please correct me if I've done more harm than good.

Regards
Johan
 
Thanks Andrew. This thread really made a difference in my system development workflow.

Got an error when building amital32 using the GNU GCC Compiler:
C++ warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]​

Sorted it out with changing the following in the Plugin.h file (change in bold):

typedef struct FunctionTag
{
const char *Name; // was char *Name
FunDesc Descript;
} FunctionTag;​

I have no idea what I'm doing so please correct me if I've done more harm than good.

Regards
Johan

Hi Johan,

That looks fine to me. "HelloWorld0", "ACSNV1", "ACSMA2", "ACMA3" are all string constants and shouldn't be allowed to be modified (hence the warning). By putting "const char *Name", you are telling the compiler that Name is constant and the compiler will generate an error if someone tries to change the contents of Name in gFunctionTable[].

So if somewhere in the code someone decides to do something like this:

gFunctionTable[0].Name[0] = 'a'; which changes "HelloWorld0" to "aelloWorld0",

then the original compile would let that slip and allow it (with your warning above), which is considered poor programming :(.

Your change (good programming :)) "const char *Name" when compiled would generate an actual error like:

error: assignment of read-only location '* gFunctionTable[0].FunctionTag::Name'

Warnings are different to errors. Executable Code (exe's,dll's,etc.) can still be generated with compiler warnings, but not with errors.

Glad this thread has made a difference :xyxthumbs.

Cheers,

Andrew.
 
Ihave problem when built tal.c .Please help me how to fix this.
-------------- Build: Debug in tal (compiler: GNU GCC Compiler)---------------

Linking stage skipped (build target has no object files to link)
Nothing to be done (all items are up-to-date).
 
Top