TA-Lib / ta-lib-python

Python wrapper for TA-Lib (http://ta-lib.org/).
http://ta-lib.github.io/ta-lib-python
Other
9.49k stars 1.74k forks source link

Error when creating new indicator #524

Open hhashim1 opened 2 years ago

hhashim1 commented 2 years ago

I am creating a new indicator and have copied parts from BBANDS. I am getting an error on one of the variables and I cannot seem to figure out why I am getting this error. Can you @mrjbq7 or @trufanov-nok can either of you help plz?

tempBuffer2 is the one that is causing the issue.

I am trying to have an equivalent of the following line of code:

def rawRelVol = (volume - Average(volume, length)) / StDev(volume, length);

Here is my code:


   /* Insert TA function code here. */
    ENUM_DECLARATION(RetCode) retCode;
    double periodTotal, tempReal;
    int i, outIdx, trailingIdx, lookbackTotal;
    ARRAY_REF(tempBuffer1);
    ARRAY_REF(tempBuffer2);
    //double rawRelVol;

    /* Calculate moving average. */
    retCode = FUNCTION_CALL(SMA)(startIdx, endIdx, inVolume,
        optInTimePeriod, outBegIdx, outNBElement, tempBuffer1);

    if ((retCode != ENUM_VALUE(RetCode, TA_SUCCESS, Success)) || ((int)VALUE_HANDLE_DEREF(outNBElement) == 0))
    {
        VALUE_HANDLE_DEREF_TO_ZERO(outNBElement);
        return retCode;
    }

    /* Calculate the Standard Deviation */
    retCode = FUNCTION_CALL(STDDEV)((int)VALUE_HANDLE_DEREF(outBegIdx), endIdx, inVolume,
        optInTimePeriod, 1.0,
        outBegIdx, outNBElement, tempBuffer2);

    if (retCode != ENUM_VALUE(RetCode, TA_SUCCESS, Success))
    {
        VALUE_HANDLE_DEREF_TO_ZERO(outNBElement);
        return retCode;
    }

    tempReal = (inVolume - tempBuffer1);
    tempReal = tempReal / tempBuffer2;

Here is the screenshot: image

trufanov-nok commented 2 years ago

I guess he's on linux and the lib is in the /usr/lib/libta_lib.so.0.0.0

hhashim1 commented 2 years ago

Here are the directories that I have in the usr/lib folder

image

mrjbq7 commented 2 years ago
$ nm /usr/lib/libta_lib.so | grep TA_RVSTDEV

This may be getting past the scope of debugging we should be doing on this project's issues...

hhashim1 commented 2 years ago

Ok, so I deleted my RVSTDEV.c file and removed all the references from the talib library and also from ta-lib-wrapper. No errors anymore.

image

I need to add everything again but I want yall to look over my code to see if I missed anything. Here is RVSTDEV.c code - https://pastebin.com/LZ6iESy9

Here are all of the references in the talib library


############table_r.c

/* RVSTDEV BEGIN */
static const TA_InputParameterInfo * TA_RVSTDEV_Inputs[] =
{
  &TA_DEF_UI_Input_Price_V,
  NULL
};

static const TA_OutputParameterInfo* TA_RVSTDEV_Outputs[] =
{
  &TA_DEF_UI_Output_Real,
  NULL
};

static const TA_OptInputParameterInfo* TA_RVSTDEV_OptInputs[] =
{   
    &TA_DEF_UI_TimePeriod_50_MINIMUM2,
    NULL 
};

static const TA_InputParameterInfo* TA_RVSTDEV_StructParams[] = { NULL };

DEF_FUNCTION(RVSTDEV,                     /* name */
    TA_GroupId_VolumeIndicators, /* groupId */
    "Relative Volume St Dev", /* hint */
    "RvStdev",                         /* CamelCase name */
    0                              /* flags */
);
/* RVSTDEV END */

####### ta_frame.c

/* Generated */ TA_RetCode TA_RVSTDEV_FramePP( const TA_ParamHolderPriv *params,
/* Generated */                           int            startIdx,
/* Generated */                           int            endIdx,
/* Generated */                           int           *outBegIdx,
/* Generated */                           int           *outNBElement )
/* Generated */ {
/* Generated */    return TA_RVSTDEV(
/* Generated */                 startIdx,
/* Generated */                 endIdx,
/* Generated */                 params->in[0].data.inPrice.volume, /* inVolume */
/* Generated */                 params->optIn[0].data.optInInteger, /* optInTimePeriod*/
/* Generated */                 outBegIdx, 
/* Generated */                 outNBElement, 
/* Generated */                 params->out[0].data.outReal /*  outReal */ );
/* Generated */ }
/* Generated */ unsigned int TA_RVSTDEV_FramePPLB( const TA_ParamHolderPriv *params )
/* Generated */ {
/* Generated */    return TA_RVSTDEV_Lookback(params->optIn[0].data.optInInteger /* optInTimePeriod*/ );
/* Generated */ }

####### ta_frame.h

/* Generated */ TA_RetCode TA_RVSTDEV_FramePP( const TA_ParamHolderPriv *params,
/* Generated */                           int            startIdx,
/* Generated */                           int            endIdx,
/* Generated */                           int           *outBegIdx,
/* Generated */                           int           *outNBElement )
;
/* Generated */ unsigned int TA_RVSTDEV_FramePPLB( const TA_ParamHolderPriv *params )
;

######## ta_func.h

/*
 * TA_RVSTDEV - Relative Volume St Dev
 * 
 * Input  = Volume
 * Output = double
 * 
 * Optional Parameters
 * -------------------
 * optInTimePeriod:(From 2 to 100000)
 *    Number of period
 * 
 * 
 */
TA_LIB_API TA_RetCode TA_RVSTDEV( int    startIdx,
                                  int    endIdx,
                                             const double inVolume[],
                                             int           optInTimePeriod, /* From 2 to 100000 */
                                             int          *outBegIdx,
                                             int          *outNBElement,
                                             double        outReal[] );

TA_LIB_API TA_RetCode TA_S_RVSTDEV( int    startIdx,
                                    int    endIdx,
                                               const float  inVolume[],
                                               int           optInTimePeriod, /* From 2 to 100000 */
                                               int          *outBegIdx,
                                               int          *outNBElement,
                                               double        outReal[] );

TA_LIB_API int TA_RVSTDEV_Lookback( int           optInTimePeriod );  /* From 2 to 100000 */

Here are the references in ta-lib-wrapper


####### _func.pxi

@wraparound(False)  # turn off relative indexing from end of lists
@boundscheck(False) # turn off bounds-checking for entire function
def RVSTDEV( np.ndarray volume not None , int timeperiod=2**31 ):
    """ RVSTDEV(volume[, timeperiod=?])

    Relative Volume Standard Deviation (Volume Functions)

    Inputs:
        prices: ['volume']
    Parameters:
        timeperiod: 50
    Outputs:
        rvstdev
    """
    cdef:
        np.npy_intp length
        int begidx, endidx, lookback
        TA_RetCode retCode
        int outbegidx
        int outnbelement
        np.ndarray outReal
    volume = check_array(volume)
    length = volume.shape[0]
    begidx = check_begidx1(length, <double*>(volume.data))
    endidx = <int>length - begidx - 1
    lookback = begidx + lib.TA_RVSTDEV_Lookback( timeperiod )
    outReal = make_double_array(length, lookback)
    retCode = lib.TA_RVSTDEV( 0 , endidx , <double *>(volume.data)+begidx, timeperiod , &outbegidx , &outnbelement , <double *>(outReal.data)+lookback )
    _ta_check_success("TA_RVSTDEV", retCode)
    return outReal

######## _ta_lib.pxd

    TA_RetCode TA_RVSTDEV(int startIdx, int endIdx, const double inVolume[], int optInTimePeriod, int *outBegIdx, int *outNBElement, double outReal[])
    int TA_RVSTDEV_Lookback(int optInTimePeriod)

####### _stream.pxi

@wraparound(False)  # turn off relative indexing from end of lists
@boundscheck(False) # turn off bounds-checking for entire function
def stream_RVSTDEV( np.ndarray volume not None , int timeperiod=2**31 ):
    """ RVSTDEV(volume[, timeperiod=?])

    Relative Volume Standard Deviation (Volume Functions)

    Inputs:
        prices: ['volume']
    Parameters:
        timeperiod: 50
    Outputs:
        rvstdev
    """
    cdef:
        np.npy_intp length
        TA_RetCode retCode
        double* volume_data
        int outbegidx
        int outnbelement
        double outReal
    volume = check_array(volume)
    volume_data = <double*>volume.data
    length = volume.shape[0]
    outReal = NaN
    retCode = lib.TA_RVSTDEV( <int>(length) - 1 , <int>(length) - 1 , volume_data, timeperiod , &outbegidx , &outnbelement , &outReal )
    _ta_check_success("TA_RVSTDEV", retCode)
    return outReal 
hhashim1 commented 2 years ago
$ nm /usr/lib/libta_lib.so | grep TA_RVSTDEV

This may be getting past the scope of debugging we should be doing on this project's issues...

Since I dont have RVSTDEV anymore in the library, I dont get any output.

mrjbq7 commented 2 years ago

Since I dont have RVSTDEV anymore in the library, I dont get any output.

Yes, but you wanted it in the library so that we could fix the "unknown symbol" error in the python build? Reverting it of course will make it still not work?

hhashim1 commented 2 years ago

Ok, so I deleted my RVSTDEV.c file and removed all the references from the talib library and also from ta-lib-wrapper. No errors anymore.

image

I need to add everything again but I want yall to look over my code to see if I missed anything. Here is RVSTDEV.c code - https://pastebin.com/LZ6iESy9

Here are all of the references in the talib library


############table_r.c

/* RVSTDEV BEGIN */
static const TA_InputParameterInfo * TA_RVSTDEV_Inputs[] =
{
  &TA_DEF_UI_Input_Price_V,
  NULL
};

static const TA_OutputParameterInfo* TA_RVSTDEV_Outputs[] =
{
  &TA_DEF_UI_Output_Real,
  NULL
};

static const TA_OptInputParameterInfo* TA_RVSTDEV_OptInputs[] =
{   
    &TA_DEF_UI_TimePeriod_50_MINIMUM2,
    NULL 
};

static const TA_InputParameterInfo* TA_RVSTDEV_StructParams[] = { NULL };

DEF_FUNCTION(RVSTDEV,                     /* name */
    TA_GroupId_VolumeIndicators, /* groupId */
    "Relative Volume St Dev", /* hint */
    "RvStdev",                         /* CamelCase name */
    0                              /* flags */
);
/* RVSTDEV END */

####### ta_frame.c

/* Generated */ TA_RetCode TA_RVSTDEV_FramePP( const TA_ParamHolderPriv *params,
/* Generated */                           int            startIdx,
/* Generated */                           int            endIdx,
/* Generated */                           int           *outBegIdx,
/* Generated */                           int           *outNBElement )
/* Generated */ {
/* Generated */    return TA_RVSTDEV(
/* Generated */                 startIdx,
/* Generated */                 endIdx,
/* Generated */                 params->in[0].data.inPrice.volume, /* inVolume */
/* Generated */                 params->optIn[0].data.optInInteger, /* optInTimePeriod*/
/* Generated */                 outBegIdx, 
/* Generated */                 outNBElement, 
/* Generated */                 params->out[0].data.outReal /*  outReal */ );
/* Generated */ }
/* Generated */ unsigned int TA_RVSTDEV_FramePPLB( const TA_ParamHolderPriv *params )
/* Generated */ {
/* Generated */    return TA_RVSTDEV_Lookback(params->optIn[0].data.optInInteger /* optInTimePeriod*/ );
/* Generated */ }

####### ta_frame.h

/* Generated */ TA_RetCode TA_RVSTDEV_FramePP( const TA_ParamHolderPriv *params,
/* Generated */                           int            startIdx,
/* Generated */                           int            endIdx,
/* Generated */                           int           *outBegIdx,
/* Generated */                           int           *outNBElement )
;
/* Generated */ unsigned int TA_RVSTDEV_FramePPLB( const TA_ParamHolderPriv *params )
;

######## ta_func.h

/*
 * TA_RVSTDEV - Relative Volume St Dev
 * 
 * Input  = Volume
 * Output = double
 * 
 * Optional Parameters
 * -------------------
 * optInTimePeriod:(From 2 to 100000)
 *    Number of period
 * 
 * 
 */
TA_LIB_API TA_RetCode TA_RVSTDEV( int    startIdx,
                                  int    endIdx,
                                             const double inVolume[],
                                             int           optInTimePeriod, /* From 2 to 100000 */
                                             int          *outBegIdx,
                                             int          *outNBElement,
                                             double        outReal[] );

TA_LIB_API TA_RetCode TA_S_RVSTDEV( int    startIdx,
                                    int    endIdx,
                                               const float  inVolume[],
                                               int           optInTimePeriod, /* From 2 to 100000 */
                                               int          *outBegIdx,
                                               int          *outNBElement,
                                               double        outReal[] );

TA_LIB_API int TA_RVSTDEV_Lookback( int           optInTimePeriod );  /* From 2 to 100000 */

Here are the references in ta-lib-wrapper


####### _func.pxi

@wraparound(False)  # turn off relative indexing from end of lists
@boundscheck(False) # turn off bounds-checking for entire function
def RVSTDEV( np.ndarray volume not None , int timeperiod=2**31 ):
    """ RVSTDEV(volume[, timeperiod=?])

    Relative Volume Standard Deviation (Volume Functions)

    Inputs:
        prices: ['volume']
    Parameters:
        timeperiod: 50
    Outputs:
        rvstdev
    """
    cdef:
        np.npy_intp length
        int begidx, endidx, lookback
        TA_RetCode retCode
        int outbegidx
        int outnbelement
        np.ndarray outReal
    volume = check_array(volume)
    length = volume.shape[0]
    begidx = check_begidx1(length, <double*>(volume.data))
    endidx = <int>length - begidx - 1
    lookback = begidx + lib.TA_RVSTDEV_Lookback( timeperiod )
    outReal = make_double_array(length, lookback)
    retCode = lib.TA_RVSTDEV( 0 , endidx , <double *>(volume.data)+begidx, timeperiod , &outbegidx , &outnbelement , <double *>(outReal.data)+lookback )
    _ta_check_success("TA_RVSTDEV", retCode)
    return outReal

######## _ta_lib.pxd

    TA_RetCode TA_RVSTDEV(int startIdx, int endIdx, const double inVolume[], int optInTimePeriod, int *outBegIdx, int *outNBElement, double outReal[])
    int TA_RVSTDEV_Lookback(int optInTimePeriod)

####### _stream.pxi

@wraparound(False)  # turn off relative indexing from end of lists
@boundscheck(False) # turn off bounds-checking for entire function
def stream_RVSTDEV( np.ndarray volume not None , int timeperiod=2**31 ):
    """ RVSTDEV(volume[, timeperiod=?])

    Relative Volume Standard Deviation (Volume Functions)

    Inputs:
        prices: ['volume']
    Parameters:
        timeperiod: 50
    Outputs:
        rvstdev
    """
    cdef:
        np.npy_intp length
        TA_RetCode retCode
        double* volume_data
        int outbegidx
        int outnbelement
        double outReal
    volume = check_array(volume)
    volume_data = <double*>volume.data
    length = volume.shape[0]
    outReal = NaN
    retCode = lib.TA_RVSTDEV( <int>(length) - 1 , <int>(length) - 1 , volume_data, timeperiod , &outbegidx , &outnbelement , &outReal )
    _ta_check_success("TA_RVSTDEV", retCode)
    return outReal 

@mrjbq7 @trufanov-nok any thoughts on this?

hhashim1 commented 2 years ago

Since I dont have RVSTDEV anymore in the library, I dont get any output.

Yes, but you wanted it in the library so that we could fix the "unknown symbol" error in the python build? Reverting it of course will make it still not work?

I added everything again and I have the error of undefined symbol: TA_RVSTDEV

Here is the screenshot for the command you asked me to run. image

mrjbq7 commented 2 years ago

Hmm, question - we package the "compiled Cython" as C files, perhaps we need to make sure you regenerate those with the new definitions?

Can you try this in the ta-lib-wrapper?

$ make cython

# build in-place

Another idea, is perhaps there needs to be a _stream.pxi version generated using generate_stream.py, since when this initializes, it looks for all the defined funcs and binds stream versions of them.

mrjbq7 commented 2 years ago

Let's also verify that the compiled python module is linking against the expected TA-Lib C library:

$ cd ta-lib-wrapper

# on a mac
$ otool -L talib/_ta_lib*.so

# on a linux
$ ldd talib/_ta_lib*.so
hhashim1 commented 2 years ago

Let's also verify that the compiled python module is linking against the expected TA-Lib C library:

$ cd ta-lib-wrapper

# on a mac
$ otool -L talib/_ta_lib*.so

# on a linux
$ ldd talib/_ta_lib*.so

image

hhashim1 commented 2 years ago

Let's also verify that the compiled python module is linking against the expected TA-Lib C library:

$ cd ta-lib-wrapper

# on a mac
$ otool -L talib/_ta_lib*.so

# on a linux
$ ldd talib/_ta_lib*.so

image

@mrjbq7 @trufanov-nok any thoughts?

trufanov-nok commented 2 years ago

Could you share whole your code for ta-lib and wraper? I'll try to build it on my PC.

trufanov-nok commented 2 years ago

Also, could you try to launch python3 and import ta-lib from other folder than wrapper's sorce code folder?

hhashim1 commented 2 years ago

I tried from root and its still the same. Do you want me to send you the RVSTDEV code only or all of the accomping code?

image

hhashim1 commented 2 years ago

ta_RVSTDEV.zip

table_r.c

/* RVSTDEV BEGIN */
static const TA_InputParameterInfo* TA_RVSTDEV_Inputs[] =
{
  &TA_DEF_UI_Input_Price_V,
  NULL
};

static const TA_OutputParameterInfo* TA_RVSTDEV_Outputs[] =
{
  &TA_DEF_UI_Output_Real,
  NULL
};

static const TA_OptInputParameterInfo* TA_RVSTDEV_OptInputs[] =
{
  &TA_DEF_UI_TimePeriod_50_MINIMUM2,
  NULL
};

DEF_FUNCTION(RVSTDEV,                        /* name */
    TA_GroupId_VolumeIndicators,  /* groupId */
    "Relative Volume Standard Deviation",  /* hint */
    "Rvstdev",                      /* CamelCase name */
    TA_FUNC_FLG_UNST_PER        /* flags */
);
/* RVSTDEV END */

ta_frames.c


/* Generated */ {
/* Generated */    return TA_RVSTDEV(
/* Generated */                 startIdx,
/* Generated */                 endIdx,
/* Generated */                 params->in[0].data.inPrice.volume, /* inVolume */
/* Generated */                 params->optIn[0].data.optInInteger, /* optInTimePeriod*/
/* Generated */                 outBegIdx, 
/* Generated */                 outNBElement, 
/* Generated */                 params->out[0].data.outReal /*  outReal */ );
/* Generated */ }
/* Generated */ unsigned int TA_RVSTDEV_FramePPLB( const TA_ParamHolderPriv *params )
/* Generated */ {
/* Generated */    return TA_RVSTDEV_Lookback(params->optIn[0].data.optInInteger /* optInTimePeriod*/ );
/* Generated */ }

ta_frames.h

/* Generated */ TA_RetCode TA_RVSTDEV_FramePP( const TA_ParamHolderPriv *params,
/* Generated */                           int            startIdx,
/* Generated */                           int            endIdx,
/* Generated */                           int           *outBegIdx,
/* Generated */                           int           *outNBElement )
;
/* Generated */ unsigned int TA_RVSTDEV_FramePPLB( const TA_ParamHolderPriv *params )
;

_func.pxi


@wraparound(False)  # turn off relative indexing from end of lists
@boundscheck(False) # turn off bounds-checking for entire function
def RVSTDEV( np.ndarray volume not None , int timeperiod=-2**31 ):
    """ RVSTDEV(volume[, timeperiod=?])

    Relative Volume Standard Deviation (Volume Indicators)

    Inputs:
        volume: (any ndarray)
    Parameters:
        timeperiod: 50
    Outputs:
        real
    """
    cdef:
        np.npy_intp length
        int begidx, endidx, lookback
        TA_RetCode retCode
        int outbegidx
        int outnbelement
        np.ndarray outreal
    volume = check_array(volume)
    length = volume.shape[0]
    begidx = check_begidx1(length, <double*>(volume.data))
    endidx = <int>length - begidx - 1
    lookback = begidx + lib.TA_RVSTDEV_Lookback( timeperiod )
    outreal = make_double_array(length, lookback)
    retCode = lib.TA_RVSTDEV( 0 , endidx , <double *>(volume.data)+begidx , timeperiod , &outbegidx , &outnbelement , <double *>(outreal.data)+lookback )
    _ta_check_success("TA_RVSTDEV", retCode)
    return outreal 

_ta_lib.pxd


    TA_RetCode TA_RVSTDEV(int startIdx, int endIdx, const double inVolume[], int optInTimePeriod, int *outBegIdx, int *outNBElement, double outReal[])
    int TA_RVSTDEV_Lookback(int optInTimePeriod)

_stream.pxi


@wraparound(False)  # turn off relative indexing from end of lists
@boundscheck(False) # turn off bounds-checking for entire function
def stream_RVSTDEV( np.ndarray volume not None , int timeperiod=-2**31 ):
    """ RVSTDEV(volume[, timeperiod=?])

    Relative Strength Index (Momentum Indicators)

    Inputs:
        volume: (any ndarray)
    Parameters:
        timeperiod: 50
    Outputs:
        real
    """
    cdef:
        np.npy_intp length
        TA_RetCode retCode
        double* volume_data
        int outbegidx
        int outnbelement
        double outreal
    volume = check_array(volume)
    volume_data = <double*>volume.data
    length = volume.shape[0]
    outreal = NaN
    retCode = lib.TA_RVSTDEV( <int>(length) - 1 , <int>(length) - 1 , volume_data , timeperiod , &outbegidx , &outnbelement , &outreal )
    _ta_check_success("TA_RVSTDEV", retCode)
    return outreal 

@trufanov-nok here is all of the code

trufanov-nok commented 2 years ago

i meant the zips with whole folders of code

hhashim1 commented 2 years ago

oh all of talib and talibwrapper?

trufanov-nok commented 2 years ago

yes

hhashim1 commented 2 years ago

Wrapper - https://file.io/J55R6ed0CUQc LIbrary - https://file.io/ZAgye5WpLQsn

trufanov-nok commented 2 years ago

I've downloaded the Library but the Wrapper zip is seems to already expire. Could you reupload it?

hhashim1 commented 2 years ago

Try this https://file.io/YfpvtmIb1Tyi

trufanov-nok commented 2 years ago

I was able to build both and access to RVSTDEV from python, so the problem must be in environment.

Screenshot_20220630_005836

hhashim1 commented 2 years ago

I was able to build both and access to RVSTDEV from python, so the problem must be in environment.

Screenshot_20220630_005836

The name of the function in your copy is different. Your screenshot says RCSTDEV. My function was called RVSTDEV. Do you have one with a similar name or did you change the name?

trufanov-nok commented 2 years ago

I just made a mistake when call it. Then I call it with a right name.

hhashim1 commented 2 years ago

Oh sorry...I didnt see that.

hhashim1 commented 2 years ago

What do you suggest for how to fix this?

trufanov-nok commented 2 years ago

find all libta_lib files on your linux machine with `sudo find / -iname "libta_lib"` and list the results

hhashim1 commented 2 years ago

image


root@aa3bed537114:/# sudo find / -iname "libta_lib*"
/usr/lib/libta_lib.a
/usr/lib/libta_lib.so
/usr/lib/libta_lib.so.0
/usr/lib/libta_lib.so.0.0.0
/usr/lib/libta_lib.la
find: ‘/proc/21033/map_files’: Permission denied
/ta-lib/src/.libs/libta_lib.a
/ta-lib/src/.libs/libta_lib.la
/ta-lib/src/.libs/libta_lib.lai
/ta-lib/src/.libs/libta_lib.so
/ta-lib/src/.libs/libta_lib.so.0
/ta-lib/src/.libs/libta_lib.so.0.0.0
/ta-lib/src/libta_lib.la
trufanov-nok commented 2 years ago

What says sudo find / -iname "_ta_lib.cpython*.so" ?

hhashim1 commented 2 years ago

image

trufanov-nok commented 2 years ago

you copied it wrong or something..

hhashim1 commented 2 years ago

Sorry I had a quote at the end. This list goes on though. Rest of the list is permission denied because its on the Windows drive.

image

hhashim1 commented 2 years ago

@trufanov-nok I got it to work. I renamed my function and compiled it again and it seems to be working. I think it was just getting confused with STDDEV. I renamed my function to RVSTDDEV instead RVSTDEV

hhashim1 commented 2 years ago

@trufanov-nok I need to get a couple of indicators coded and its over my head. Are you able to help me get these indicators done in talib? I will pay you for it.

hhashim1 commented 2 years ago

@trufanov-nok thats great. Thank you. I will email you. You can delete your email address from the comment above now. I have copied it.

trufanov-nok commented 2 years ago

I've just passed the whole way from making a new indicator to adding it to the python's wrapper so I can write a little guide about that:

  1. Regarding addition of a new indicator to the TA-Lib library written in C language pls refer to this description: https://github.com/trufanov-nok/ta-lib-rt/wiki/Adding-new-TA-function
    and this thread. It's pretty relevant to original TA-Lib sourcecode.

Just note that the archive of ta-lib sources which are automatically downloaded by the wrapper when it's installed via pip isn't suitable for a new indicator addition bcs of lacking some files. So you'll need a dump of a whole latest sourcecode trunk from sourceforge. This have some consequences which will be shown later.

  1. After successful creation of a new C indicator and compilation of a C library, one need to install it with make install or something like that. Read in console and remember there include/ta-lib/ta_func.h is stored.
  2. Doublecheck that your new indicator is declared in this ta_func.h header. If it's not - you did something wrong in the C code.
  3. Find any other ta_func.h files in default folders of your system and delete them, bcs TA-lib's wrapper will automatically search this header in your system using default paths. If it find an old one before reach up-to-date one - it won't get any info about your new indicator. The default folders are '/usr/include', '/usr/local/include', '/opt/include', '/opt/local/include', '/opt/homebrew/include', 'c:\ta-lib\c\include'.
  4. Get the latest sources of TA-Lib's wrapper for python from this github project. The package in system repositories won't work and you'll need exactly the latest sources as they contain some fixes.
  5. Uninstall all other python wrappers of TA-lib with pip uninstall ta-lib. Execute it a few times until it report that no any TA-Lib packages are installed.
  6. In python's wrapper folder edit files ./tools/generate_func.py and ./tools/generate_stream.py. In both comment out (with #) lines from talib import abstract then comment out:
    func_info = abstract.Function(shortname).info
    defaults, documentation = abstract._get_defaults_and_docs(func_info)

    then add after them:

    func_info = []
    defaults = []
    documentation = []

This will disable usage of TA-Lib's python package in these scripts for generation of documentation for indicators. It won't work anyway as scripts will parse your new ta_func.h, and will try to get a documentation for a new indicator which is unknown yet for the wrapper installed in the system. And according to the 6 I advised to uninstall all wrappers anyway, so it won't work.

  1. Launch python3 tools/generate_func.py. This will print a lot of text (which is actually a new content of a _func.pxi) to the console. Check the last lines. If there are any errors - most probably you failed to perform step 7. If __TA_FUNCTION_NAMES__ is empty (__TA_FUNCTION_NAMES__ = []) - script can't find any ta_func.h file. If it contains a list of indicators names, but there is no your new one - then script catch ups some old ta_func.h and you failed step 4.

  2. If everything is okay, overwrite files talib/_func.pxi and talib/_stream.pxi with a new content generated by these scripts, with:

    python3 tools/generate_func.py > talib/_func.pxi
    python3 tools/generate_stream.py > talib/_stream.pxi
  3. Unfortunately there are few other files that need to be patched to add info about your new indicator. And there is no script to autopatch them. These are declarations in _ta_lib.pxd and (optionally) groups description in __init__.py.
    Also, TA-Lib's wrapper is designed to be used with an old version of TA-Lib 0.4.24, while sourceforge's trunk contain 0.4.25. It has 3 more indicators than previous one. Which means that along with your new indicator you'll need to add the info about these 3. Indicators are: ACCBANDS, AVGDEV, IMI. Scripts will grab their description from ta_func.h and update talib/_func.pxi and talib/_stream.pxi, but following is still need to be added into _ta_lib.pxd manually:

    TA_RetCode TA_ACCBANDS(int startIdx, int endIdx, const double inHigh[], const double inLow[], const double inClose[], int optInTimePeriod, int *outBegIdx, int *outNBElement, double outRealUpperBand[], double outRealMiddleBand[], double outRealLowerBand[])
    int TA_ACCBANDS_Lookback(int optInTimePeriod)
    TA_RetCode TA_AVGDEV(int startIdx, int endIdx, const double inReal[], int optInTimePeriod, int *outBegIdx, int *outNBElement, double outReal[])
    int TA_AVGDEV_Lookback(int optInTimePeriod)
    TA_RetCode TA_IMI(int startIdx, int endIdx, const double inOpen[], const double inClose[], int optInTimePeriod, int *outBegIdx, int *outNBElement, double outReal[])
    int TA_IMI_Lookback(int optInTimePeriod)

    Do not forget to add definitions of the function for your new indicator there too.

  4. Perform python3 setup.py build. In case of any errors check the messages. If it's about your new indicator - the problem is on step 10.

  5. Perform sudo python3 setup.py install to install the wrapper binary. Launch python3 and execute import talib to check if everything is ok. DO NOT DO THIS FROM WRAPPERS SOURCECODE FOLDER - it won't work as python will try to load a local copy and fail. You may print a list of talib functions available from python side with talib.__TA_FUNCTION_NAMES__ and get its version with talib.__version__ to make sure wrapper loads the right wrapper and library.

  6. Revert the changes made at step 7 and repeat steps 9-12 again to generate .pxi files with additional documentation and correct default values. Note: step 12 is mandatory to be done before 13.