如何从Amibroker

时间:2015-09-19 07:12:19

标签: c# c++ trading algorithmic-trading

需要测试用于日间交易的替代工具。要获取NSE的日内实时数据,某些vendors正在销售Amibroker的数据插件。要从 Amibroker 中获取数据,我打算使用 AFL (Amibroker公式语言)。 AFL中的以下code为每个符号创建一次 .csv 文件。但是要使用实时数据,我需要在一天内连续将传入数据附加到.csv文件。如何在不崩溃/重载 Amibroker 的情况下完成这项工作?

// created a directory on your C drive named AmiBroker data backup
dayhours = paramtoggle("Day hours only", "No|Yes");
fmkdir("c:\\AmiBackup\\");
setbarsrequired(100000,100000);
lname = Name(); // gets the name of the symbol
// note: if you have names with invalid characters like / you must rename the
file before you try to create a name 
// add an IF line for each symbol you need to rename
if (lname == "ER2U8-GLOBEX-FUT") lname = "ER2U8";

fh = fopen( "c:\\AmiBackup\\" + lname + ".csv", "w"); 
if( fh ) 
{ 
    if(interval() == inDaily OR interval() == inMonthly OR interval() == inweekly)
    {
        fputs( "Ticker,Date,Open,High,Low,Close,Volume \n", fh ); 
        for( i = 0; i < BarCount; i++ ) 
        { 
            y = Year(); 
            m = Month(); 
            d = Day(); 
            fputs( Name() + "," , fh );
            ds = StrFormat("%02.0f-%02.0f-%02.0f,", m[ i ], d[ i ], y[ i ] ); 
            fputs( ds, fh ); 
            qs = StrFormat("%.4f,%.4f,%.4f,%.4f,%.0f\n", O[ i ],H[ i ],L[ i ],C[ i
],V[ i ] ); 
            fputs( qs, fh ); 
            if(i == 65500 or i == 130000 or i == 196500 or i == 262000)
            {
                fclose( fh ); 
                if(i == 65500  ) fh = fopen( "c:\\AmiBackup\\" + lname + " A.csv", "w"); 
                if(i == 130000 ) fh = fopen( "c:\\AmiBackup\\" + lname + " B.csv", "w"); 
                if(i == 196500 ) fh = fopen( "c:\\AmiBackup\\" + lname + " C.csv", "w"); 
                if(i == 262000 ) fh = fopen( "c:\\AmiBackup\\" + lname + " D.csv", "w"); 
            }
        }
    }
    else // intraday so add time field
    {
        fputs( "Ticker,Date,Time,Open,High,Low,Close,Volume \n", fh ); 
        y = Year(); 
        m = Month(); 
        d = Day(); 
        r = Hour();
        e = Minute();
        n = Second();

        for( i = 1; i < BarCount; i++ ) 
        { 
            if (dayhours and lastvalue(timenum()) >= 92900 and lastvalue(timenum()) <=
161500)
            { 
                fputs( Name() + "," , fh );
                ds = StrFormat("%02.0f-%02.0f-%02.0f,", m[ i ], d[ i ], y[ i ] ); 
                fputs( ds, fh ); 

                ts = StrFormat("%02.0f:%02.0f:%02.0f,", r[ i ],e[ i ],n[ i ] ); 
                fputs( ts, fh ); 

                qs = StrFormat("%.4f,%.4f,%.4f,%.4f,%.0f\n", O[ i ],H[ i ],L[ i ],C[ i
],V[ i ] ); 
                fputs( qs, fh ); 
            }
            else
            { 
                fputs( Name() + "," , fh );
                ds = StrFormat("%02.0f-%02.0f-%02.0f,", m[ i ], d[ i ], y[ i ] ); 
                fputs( ds, fh ); 

                ts = StrFormat("%02.0f:%02.0f:%02.0f,", r[ i ],e[ i ],n[ i ] ); 
                fputs( ts, fh ); 

                qs = StrFormat("%.4f,%.4f,%.4f,%.4f,%.0f\n", O[ i ],H[ i ],L[ i ],C[ i
],V[ i ] ); 
                fputs( qs, fh ); 
            }
            if(i == 65500 or i == 130000 or i == 196500 or i == 262000)
            {
                fclose( fh ); 
                if(i == 65500  ) fh = fopen( "c:\\AmiBackup\\" + lname + " A.csv", "w"); 
                if(i == 130000 ) fh = fopen( "c:\\AmiBackup\\" + lname + " B.csv", "w"); 
                if(i == 196500 ) fh = fopen( "c:\\AmiBackup\\" + lname + " C.csv", "w"); 
                if(i == 262000 ) fh = fopen( "c:\\AmiBackup\\" + lname + " D.csv", "w"); 
            }
        } 
    }
    fclose( fh ); 
} 

Buy = 1;

2 个答案:

答案 0 :(得分:1)

摆脱你的for循环。 Amibroker每次更新图表时都会运行AFL,因此对于那些for循环,每次图表更新时(当有新报价出现时),您都会浏览数据库中的每个栏,因此您拥有的栏数越多,更高的内存使用率。您可以设置i = 0来引用当前条。我只是脱离了头脑。如果你没有做对,并且不介意写一个C#dll,请告诉我,我会发布代码。

答案 1 :(得分:1)

没问题。

我有想法从

做到这一点

https://adamprescott.net/2012/04/05/net-vb6-interop-tutorial/

您要做的是创建一个类库。创建一个接口和一个实现该接口的类。在你的情况下,它将是这样的:

namespace AmiCOMLib
{
    [ComVisible(true)]
    public interface IMyInterop
    {
        [DispId(1)]
        void SendQuotes(string quoteString);
    }//end interface  

    [ComVisible(true)]
    public class AmiCOM
    {
        public void SendQuotes(string quoteString)
        { 
            //process string here and save as CSV
        }
    }
  }

您可以将引号字符串作为逗号分隔的字符串发送(就像我通常对长字符串所做的那样)并将其拆分到DLL中或使用许多参数发送。

接下来,您将准备注册您的DLL。如果DLL和Amibroker在同一台机器上,您可以使用Build Events,否则,您可以创建批处理文件。第一次运行它时,首先运行寄存器部分(注释掉注销代码)。每次我重新编译我的DLL,我运行取消注册然后注册代码。我不确定是否有必要,但无论如何我都是这样做的。目标路径可以是您想要的任何文件夹,例如,我在C:\驱动器上使用一个文件夹。检查regasm所在的文件夹,因为它与不同的.NET版本不同(这是4.5)。

构建活动代码

"%WinDir%\Microsoft.NET\Framework\v4.0.30319\regasm" /tlb /unregister "$(TargetPath)"

echo UNREGISTERED

"%WinDir%\Microsoft.NET\Framework\v4.0.30319\regasm" /tlb /codebase "$(TargetPath)"

echo REGISTERED

xcopy "$(TargetPath)" "<folder where you want DLL to be copied to>" /D /Y

批处理文件

ECHO OFF

ECHO We're first going to unregister, then register AmiCOMLib

ECHO UnRegistering AmiCOMLib

"C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm" "C:\ATS\AmiCOMLib.dll" /unregister 

ECHO UNREGISTERED

PAUSE

"C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm" "C:\ATS\AmiCOMLib.dll" /tlb /codebase

ECHO REGISTERED

PAUSE

最后,我不记得为什么,但无论如何我都是这样做的,我签署了集会。在属性&gt;下签名&gt;检查&#34;签署组件&#34;。我只选择默认值,它看起来像assemblyName.dll.snk。

要使用它,在你的AFL中,首先你要创建一个静态对象(编译器会抱怨它,但是使用静态对象意味着它被创建一次并共享,而不是创建很多时间和你的记忆 - 你可以忽略它,我从来没有使用它的记忆问题):

AmiComObj = CreateStaticObject("AmiCOMLib.AmiCOM"); //note format is namespace.class
quoteString = Name() + "," + close; //or, for example, what you have in your fputs
AmiComObj.SendQuotes(quoteString);

我个人使用这种方法来检查每个滴答的某些条件,所以我知道它适用于实时应用。

希望这会给你一些想法。

祝你好运。

Sethmo