How to pass a DATE_TIME_INT, instead of a VAR_FLOAT back to Amibroker

Hi

I am trying to write a small C++ function that will call the Amibroker DateTimeToStr() function. I will use it in an AFL plugin, NOT in a DATA plugin.

What I am missing is how to pass a DATE_TIME_INT, instead of a VAR_FLOAT back to Amibroker. Here is the code I came up with :

// bi : Barindex
string ABDateTimeToStr(int bi)
{
unsigned long long *dateArray = gSite.GetDateTimeArray();

    AmiVar args[ 2 ];

    args[ 0 ].type = VAR_FLOAT;   // How do I pass a DATE_TIME_INT, instead of a VAR_FLOAT ? 
    args[ 0 ].val = dateArray[bi];

    args[ 1 ].type = VAR_FLOAT;
    args[ 1 ].val = 3;

    AmiVar result = gSite.CallFunction("DateTimeToStr", 2, args );

return result.string;
}

Right now it returns this, instead of the correct date/time:
2018-11-29 00:00:00

PS: I have read this topic How do I correctly obtain date / time of a given bar that is comparable and took all I could understand.

If you looked at what DateTime() function returns you would see that it returns array of floats (32-bit values). These values however are not really numbers. DateTime in AFL is a 32-bit bitfield value with proprietary encoding. It has entirely different encoding than DATE_TIME_INT (which is 64-bit).

As I wrote in this thread: How do I correctly obtain date / time of a given bar that is comparable

You need to use function like _DT() or StrToDateTime to generate 32-bit float representing (datetime) value that you could pass as argument to CallFunction (or return from your function)

As I wrote many times: don't write DLLs. They are NOT needed unless you are doing some multiply nested loops.

Hi Tomasz

I am sorry, I do not understand.

In that other thread, you suggested that the correct path is to use

Approach one: Use gSite.GetDateTimeArray

Now you are saying to use DateTime() which is :

Approach two : Use gSite.CallFunction and retrieve values of built in AFL function, DateTime

As I understand I have a 64bit representation of the DateTime value in dateArray[bi]. All I need to do it convert this to 32 bit to pass it to Amibroker.

_DT() takes a string, so how would I use it?

ok, the following worked, this must be Approach two!

// bi : Barindex
string ABDateTimeToStr(int bi)
{
    AmiVar result = gSite.AllocArrayResult();

    AmiVar args[ 0 ];

    args[ 0 ].type = VAR_FLOAT;  
    args[ 0 ].val = 0;

    result = gSite.CallFunction("DateTime", 0, args );
    
    AmiVar argsB[ 2 ];

    argsB[ 0 ].type = VAR_FLOAT; 
    argsB[ 0 ].val = result.array[bi];

    argsB[ 1 ].type = VAR_FLOAT;
    argsB[ 1 ].val = 3;

    AmiVar resultB = gSite.CallFunction("DateTimeToStr", 2, argsB );

    return resultB.string;
}

Questions:

  1. Datetime() takes 0 arguments. I made args[ 0 ] which still has one cell. Is there a better way to construct an argument list that contains no arguments?

  2. I would still like to know how I could have made the gSite.GetDateTimeArray() approach work.

1 Like

Doesn't this work?

result = gSite.CallFunction("DateTime", 0, NULL);

For what it is worth, the other thread answers totally different question. He asked about easiest way to READ the value in human-readable seconds, minutes, etc(separate fields having clear human-readable interpretation) thus much LONGER (64bit DATE_TIME_INT). You are asking what values to use when you PASS values or RETURN from AFL function. That is fundamentally different. The values you pass to AFL are encoded/packed, not human readable, and they are floats (32bit)/array of floats.

I can't see any loops in your code that you were posting on this forum. DLLs should ONLY be used for multiple nested loops and nothing else, as only multiple nested loops would benefit from compiling into DLL. It makes no sense to rewrite large non-looping portions of AFL into DLL. When you do this it is not faster, it is SLOWER than AFL. It is also much more error prone. There are just countless of things in C/C++ code that can be written incorrectly and lead to crashes, instability, increased memory consumption, poor performance, lack of backward/forward compatibility with past/future versions and all kind of problems. Even your casting (implicit casting char * to STL string) shows that you are relying on very inefficient mechanism.

I can not stress that more: DLLs should NOT be used by regular user to rewrite formulas. The DLL interface is solely for:

  1. developing data plugins

  2. time-critical looping-intensive code (multiply nested loops with billions of iterations) when there is absolutely no array-based alternative (which is 0.01% of all coding cases, which means that only handful of AmiBroker users worldwide would ever need that). And I really mean time-critical. Something that makes difference in hours/days not microseconds.

3 Likes

Yes, perfect!

Thank you @Tomasz. I always value your opinion and advice. I will favor DLLs much less in the future.

Anyway, the code you saw is for exporting variables to a txt file, for debugging purposes. My real plugin is mostly FOR loops, for some custom version of the ZIG function.