/*********************************************************************
* Copyright (c) 2005 The MetaStock Forum Crew. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by MetaStock Forum Crew
* (http://forum.equis.com)."
*
* THIS SOFTWARE IS PROVIDED BY THE METASTOCK FORUM CREW "AS IS" AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE METASTOCK FORUM CREW OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
//------------------------------------------------------------------------
//Do not touch any of this paragraph / INCLUDES
//------------------------------------------------------------------------
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <float.h>
#include "MSXStruc.h"
#include "msfl.h"
#include <ctime> // For Random Function
#include <fstream> //For GlobalVar Function
#ifdef __cplusplus
extern "C" {
#endif
//------------------------------------------------------------------------
//Do not touch any of this paragraph / LOAD-UNLOAD
//------------------------------------------------------------------------
BOOL WINAPI DllMain ( HANDLE a_hModule,
DWORD a_fdwReason,
LPVOID a_lpReserved )
{BOOL l_bRtrn = TRUE;
switch (a_fdwReason)
{
case DLL_PROCESS_ATTACH:
break;
case DLL_PROCESS_DETACH:
break;
default:
break;
}
return l_bRtrn;}
//------------------------------------------------------------------------
//********************* MSXInfo - Copyright Info**************************
//
// You need to change the number of functions available here
//
// 1) Latch Patrick Nouvion
// 2) DateRange Patrick Nouvion / Updated by Wabbit
// 3) VarRef Patrick Nouvion
// 4) VarHHV Patrick Nouvion
// 5) VarLLV Patrick Nouvion
// 6) VarSUM Patrick Nouvion
// 7) VarHHVBARS Patrick Nouvion
// 8) VarLLVBARS Patrick Nouvion
// 9) VarMOV Patrick Nouvion
// 10) VarRSI Patrick Nouvion
// 11) VarMOM Patrick Nouvion
// 12) VarCMO Patrick Nouvion
// 13) CustomIndex Patrick Nouvion
// 14) TD Combo Patrick Nouvion
// 15) Custom SAR Patrick Nouvion
// 16) Random Patrick Nouvion
// 17) GlobalVar Patrick Nouvion
//-------------------------------------------------------------------------------------------------------
//------------------- COPYRIGHT INFO ------------------------------------------------------------------
BOOL __stdcall MSXInfo (MSXDLLDef *a_psDLLDef)
{ strncpy (a_psDLLDef->szCopyright, "MetaStock Forum Crew 2005",
sizeof(a_psDLLDef->szCopyright)-1);
a_psDLLDef->iNFuncs = 17;//NUMBER OF FUNCTIONS MAKE SURE TO CHANGE THIS NUMBER WHEN ADDING A FUNCTION
a_psDLLDef->iVersion = MSX_VERSION;
return MSX_SUCCESS;}
//------------------------------------------------------------------------
//***************** MSXNthFunction - Function Info************************
//
//You need to change the function name and its description here
//
//
// Case 0 = Function 1 = Latch
// Case 1 = Function 2 = DateRange
// Case 2 = function 3 = VarRef
// Case 3 = function 4 = VarHHV
// Case 4 = function 5 = VarLLV
// Case 5 = function 6 = VarSUM
// Case 6 = function 7 = VarHHVBARS
// Case 7 = function 8 = VarLLVBARS
// Case 8 = function 9 = VarMOV
// Case 9 = function 10 = VarRSI
// Case 10 = function 11 = VarMOM
// Case 11 = function 12 = VarCMO
// Case 12 = function 13 = CustomIndex
// Case 13 = function 14 = TDCOMBO
// Case 14 = function 15 = CSAR
// Case 15 = function 16 = Random
// Case 16 = function 17 = GlobalVar
//
//------------------------------------------------------------------------
BOOL __stdcall MSXNthFunction (int a_iNthFunc, MSXFuncDef *a_psFuncDef)
{
int l_bRtrn = MSX_SUCCESS;
switch (a_iNthFunc) {
case 0:
strcpy (a_psFuncDef->szFunctionName, "Latch"); //Function Name
strcpy (a_psFuncDef->szFunctionDescription, "Latch Function"); //Function Desc
a_psFuncDef->iNArguments =4; // # of Arguments
break;
case 1:
strcpy (a_psFuncDef->szFunctionName, "DateRange"); //Function Name
strcpy (a_psFuncDef->szFunctionDescription, "Is true only between the range"); //Function Desc
a_psFuncDef->iNArguments = 2; // # of Arguments
break;
case 2:
strcpy (a_psFuncDef->szFunctionName, "VarREF"); //Function Name
strcpy (a_psFuncDef->szFunctionDescription, " Variable Ref Function"); //Function Desc
a_psFuncDef->iNArguments = 2; // # of Arguments
break;
case 3:
strcpy (a_psFuncDef->szFunctionName, "VarHHV"); //Function Name
strcpy (a_psFuncDef->szFunctionDescription, " Variable HHV Function"); //Function Desc
a_psFuncDef->iNArguments = 2; // # of Arguments
break;
case 4:
strcpy (a_psFuncDef->szFunctionName, "VarLLV"); //Function Name
strcpy (a_psFuncDef->szFunctionDescription, " Variable LLV Function"); //Function Desc
a_psFuncDef->iNArguments = 2; // # of Arguments
break;
case 5:
strcpy (a_psFuncDef->szFunctionName, "VarSUM"); //Function Name
strcpy (a_psFuncDef->szFunctionDescription, " Variable SUM Function"); //Function Desc
a_psFuncDef->iNArguments = 2; //# of Arguments
break;
case 6:
strcpy (a_psFuncDef->szFunctionName, "VarHHVBARS"); //Function Name
strcpy (a_psFuncDef->szFunctionDescription, " Variable HHVBARS Function"); //Function Desc
a_psFuncDef->iNArguments = 2; //# of Arguments
break;
case 7:
strcpy (a_psFuncDef->szFunctionName, "VarLLVBARS"); //Function Name
strcpy (a_psFuncDef->szFunctionDescription, " Variable LLVBARS Function"); //Function Desc
a_psFuncDef->iNArguments = 2; //# of Arguments
break;
case 8:
strcpy (a_psFuncDef->szFunctionName, "VarMOV"); //Function Name
strcpy (a_psFuncDef->szFunctionDescription, " Variable MA Function"); //Function Desc
a_psFuncDef->iNArguments = 3; //# of Arguments
break;
case 9:
strcpy (a_psFuncDef->szFunctionName, "VarRSI"); //Function Name
strcpy (a_psFuncDef->szFunctionDescription, " Variable RSI Function"); //Function Desc
a_psFuncDef->iNArguments = 2; //# of Arguments
break;
case 10:
strcpy (a_psFuncDef->szFunctionName, "VarMOM"); //Function Name
strcpy (a_psFuncDef->szFunctionDescription, " Variable MOMENTUM Function"); //Function Desc
a_psFuncDef->iNArguments = 2; //# of Arguments
break;
case 11:
strcpy (a_psFuncDef->szFunctionName, "VarCMO"); //Function Name
strcpy (a_psFuncDef->szFunctionDescription, " Variable CMO Function"); //Function Desc
a_psFuncDef->iNArguments = 2; //# of Arguments
break;
case 12:
strcpy (a_psFuncDef->szFunctionName, "CustomIndex"); //Function Name
strcpy (a_psFuncDef->szFunctionDescription, "Custom Index"); //Function Desc
a_psFuncDef->iNArguments =3; //# of Arguments
break;
case 13:
strcpy (a_psFuncDef->szFunctionName, "TDCOMBO"); //Function Name
strcpy (a_psFuncDef->szFunctionDescription, "TD COMBO"); //Function Desc
a_psFuncDef->iNArguments = 0; //# of Arguments
break;
case 14:
strcpy (a_psFuncDef->szFunctionName, "CSAR"); //Function Name
strcpy (a_psFuncDef->szFunctionDescription, "Custom SAR Indicator"); //Function Desc
a_psFuncDef->iNArguments = 3; // # of Arguments
break;
case 15:
strcpy (a_psFuncDef->szFunctionName, "Random"); //Function Name
strcpy (a_psFuncDef->szFunctionDescription, "Random Value"); //Function Desc
a_psFuncDef->iNArguments = 2; // # of Arguments
break;
case 16:
strcpy (a_psFuncDef->szFunctionName, "GlobalVar"); //Function Name
strcpy (a_psFuncDef->szFunctionDescription, "Global Variables"); //Function Desc
a_psFuncDef->iNArguments = 0; // # of Arguments
break;
//If I wanted to add a new function I would write
// case X:
// strcpy (a_psFuncDef->szFunctionName, "FunctionX"); //Function Name
// strcpy (a_psFuncDef->szFunctionDescription, "X Function"); //Function Desc
// a_psFuncDef->iNArguments = 0; // # of args in function //# of Arguments
// break;
//----------------------DEFAULT RESULT - DO NOT CHANGE-------------------
//--------------------- This will help MSXTest find errors in your code--
default:
l_bRtrn = MSX_ERROR;
break;
}
return l_bRtrn;
}
//------------------------------------------------------------------------
//***************MSXNthArg - Function Arguments Info**********************
//
// You need to change the number of arguments per functions available here
// You will also define these arguments
//
//------------------------------------------------------------------------
BOOL __stdcall MSXNthArg (int a_iNthFunc,
int a_iNthArg,
MSXFuncArgDef *a_psFuncArgDef)
{
BOOL l_bRtrn = MSX_SUCCESS;
switch (a_iNthFunc) {
case 0: // This refers to the Latch Function
switch (a_iNthArg) {
case 0: // Latch 1st Argument
a_psFuncArgDef->iArgType = MSXDataArray;
strcpy (a_psFuncArgDef->szArgName, "LE");
break;
case 1: // Latch 2nd Argument
a_psFuncArgDef->iArgType = MSXDataArray;
strcpy (a_psFuncArgDef->szArgName, "LX");
break;
case 2: // Latch 3rd Argument
a_psFuncArgDef->iArgType = MSXDataArray;
strcpy (a_psFuncArgDef->szArgName, "SE");
break;
case 3: // Latch 4th Argument
a_psFuncArgDef->iArgType = MSXDataArray;
strcpy (a_psFuncArgDef->szArgName, "SX");
break;
default:
l_bRtrn = MSX_ERROR;
break;
}
break;
case 1: // This refers to the Date Range Function
switch (a_iNthArg) {
case 0: // FirstDate
a_psFuncArgDef->iArgType = MSXDataArray;
strcpy (a_psFuncArgDef->szArgName, "FirstDate");
break;
case 1: // LastDate
a_psFuncArgDef->iArgType = MSXDataArray;
strcpy (a_psFuncArgDef->szArgName, "LastDate");
break;
default:
l_bRtrn = MSX_ERROR;
break;
}
break;
case 2: // This refers to the VarREF Function
switch (a_iNthArg) {
case 0: // VarVal
a_psFuncArgDef->iArgType = MSXDataArray;
strcpy (a_psFuncArgDef->szArgName, "Data Array");
break;
case 1: // VarPer
a_psFuncArgDef->iArgType = MSXDataArray;
strcpy (a_psFuncArgDef->szArgName, "Variable Period");
break;
default:
l_bRtrn = MSX_ERROR;
break;
}
break;
case 3: // This refers to the VarHHV Function
switch (a_iNthArg) {
case 0: // VarVal
a_psFuncArgDef->iArgType = MSXDataArray;
strcpy (a_psFuncArgDef->szArgName, "Data Array");
break;
case 1: // VarPer
a_psFuncArgDef->iArgType = MSXDataArray;
strcpy (a_psFuncArgDef->szArgName, "Variable Period");
break;
default:
l_bRtrn = MSX_ERROR;
break;
}
break;
case 4: // This refers to the VarLLV Function
switch (a_iNthArg) {
case 0: // VarVal
a_psFuncArgDef->iArgType = MSXDataArray;
strcpy (a_psFuncArgDef->szArgName, "Data Array");
break;
case 1: // VarPer
a_psFuncArgDef->iArgType = MSXDataArray;
strcpy (a_psFuncArgDef->szArgName, "Variable Period");
break;
default:
l_bRtrn = MSX_ERROR;
break;
}
break;
case 5: // This refers to the VarSUM Function
switch (a_iNthArg) {
case 0: // VarVal
a_psFuncArgDef->iArgType = MSXDataArray;
strcpy (a_psFuncArgDef->szArgName, "Data Array");
break;
case 1: // VarPer
a_psFuncArgDef->iArgType = MSXDataArray;
strcpy (a_psFuncArgDef->szArgName, "Variable Period");
break;
default:
l_bRtrn = MSX_ERROR;
break;
}
break;
case 6: // This refers to the VarHHVBARS Function
switch (a_iNthArg) {
case 0: // VarVal
a_psFuncArgDef->iArgType = MSXDataArray;
strcpy (a_psFuncArgDef->szArgName, "Data Array");
break;
case 1: // VarPer
a_psFuncArgDef->iArgType = MSXDataArray;
strcpy (a_psFuncArgDef->szArgName, "Variable Period");
break;
default:
l_bRtrn = MSX_ERROR;
break;
}
break;
case 7: // This refers to the VarLLVBARS Function
switch (a_iNthArg) {
case 0: // VarVal
a_psFuncArgDef->iArgType = MSXDataArray;
strcpy (a_psFuncArgDef->szArgName, "Data Array");
break;
case 1: // VarPer
a_psFuncArgDef->iArgType = MSXDataArray;
strcpy (a_psFuncArgDef->szArgName, "Variable Period");
break;
default:
l_bRtrn = MSX_ERROR;
break;
}
break;
case 8: // This refers to the VarMOV Function
switch (a_iNthArg) {
case 0: // VarVal
a_psFuncArgDef->iArgType = MSXDataArray;
strcpy (a_psFuncArgDef->szArgName, "Data Array");
break;
case 1: // VarPer
a_psFuncArgDef->iArgType = MSXDataArray;
strcpy (a_psFuncArgDef->szArgName, "Variable Period");
break;
case 2:
a_psFuncArgDef->iArgType = MSXCustom; // CustomType
a_psFuncArgDef->iNCustomStrings = 8;
strcpy (a_psFuncArgDef->szArgName, "Method");
break;
default:
l_bRtrn = MSX_ERROR;
break;
}
break;
case 9: // This refers to the VarRSI Function
switch (a_iNthArg) {
case 0: // VarVal
a_psFuncArgDef->iArgType = MSXDataArray;
strcpy (a_psFuncArgDef->szArgName, "Data Array");
break;
case 1: // VarPer
a_psFuncArgDef->iArgType = MSXDataArray;
strcpy (a_psFuncArgDef->szArgName, "Variable Period");
break;
default:
l_bRtrn = MSX_ERROR;
break;
}
break;
case 10: // This refers to the VarMOM Function
switch (a_iNthArg) {
case 0: // VarVal
a_psFuncArgDef->iArgType = MSXDataArray;
strcpy (a_psFuncArgDef->szArgName, "Data Array");
break;
case 1: // VarPer
a_psFuncArgDef->iArgType = MSXDataArray;
strcpy (a_psFuncArgDef->szArgName, "Variable Period");
break;
default:
l_bRtrn = MSX_ERROR;
break;
}
break;
case 11: // This refers to the VarCMO Function
switch (a_iNthArg) {
case 0: // VarVal
a_psFuncArgDef->iArgType = MSXDataArray;
strcpy (a_psFuncArgDef->szArgName, "Data Array");
break;
case 1: // VarPer
a_psFuncArgDef->iArgType = MSXDataArray;
strcpy (a_psFuncArgDef->szArgName, "Variable Period");
break;
default:
l_bRtrn = MSX_ERROR;
break;
}
break;
case 12: // This refers to the CustomIndex Function
switch (a_iNthArg) {
case 0: // Path
a_psFuncArgDef->iArgType = MSXString;
strcpy (a_psFuncArgDef->szArgName, "Path");
break;
case 1:
a_psFuncArgDef->iArgType = MSXCustom; // CustomType
a_psFuncArgDef->iNCustomStrings = 10;
strcpy (a_psFuncArgDef->szArgName, "Price Array");
break;
case 2:
a_psFuncArgDef->iArgType = MSXCustom; // CustomType
a_psFuncArgDef->iNCustomStrings = 4;
strcpy (a_psFuncArgDef->szArgName, "Method");
break;
default:
l_bRtrn = MSX_ERROR;
break;
}
break;
case 14: //This refers to the CSAR function
switch (a_iNthArg) {
case 0:
a_psFuncArgDef->iArgType = MSXDataArray;
strcpy (a_psFuncArgDef->szArgName, "Data Array");
break;
case 1:
a_psFuncArgDef->iArgType = MSXDataArray; // Numeric
strcpy (a_psFuncArgDef->szArgName, "Step");
break;
case 2:
a_psFuncArgDef->iArgType = MSXDataArray; // Numeric
strcpy (a_psFuncArgDef->szArgName, "Maximum");
break;
default:
l_bRtrn = MSX_ERROR;
break;
}
break;
case 15: //This refers to the CSAR function
switch (a_iNthArg) {
case 0:
a_psFuncArgDef->iArgType = MSXDataArray; // Numeric
strcpy (a_psFuncArgDef->szArgName, "Min");
break;
case 1:
a_psFuncArgDef->iArgType = MSXDataArray; // Numeric
strcpy (a_psFuncArgDef->szArgName, "Max");
break;
default:
l_bRtrn = MSX_ERROR;
break;
}
break;
default:
l_bRtrn = MSX_ERROR;
break;
}
return l_bRtrn;
}
//****************CUSTOM STRING DECLARATION*******************************
BOOL __stdcall MSXNthCustomString (int a_iNthFunc,
int a_iNthArg,
int a_iNthString,
MSXFuncCustomString *a_psCustomString)
{
BOOL l_bRtrn = MSX_SUCCESS;
a_psCustomString->szString[0] = '\0';
a_psCustomString->iID = -1;
typedef struct {
char *szString;
int iID;
} LocalStringElement;
LocalStringElement l_sTheStrings[] = {
{"Simple",0},{"S",0},{"Triangular",1},{"T",1},{"Weighted",2},{"W",2},{"Exponential",3},{"E",3}
};
LocalStringElement CustomIndexPrice[] = {
{"Open", 0}, {"O", 0},
{"High", 1}, {"H", 1},
{"Low", 2}, {"L", 2},
{"Close", 3}, {"C", 3},
{"Volume", 4}, {"V", 4}
};
LocalStringElement CustomIndexMethod[] = {
{"Summation", 0}, {"Sum", 0},
{"Index", 1}, {"I", 1}
};
switch (a_iNthFunc) {
case 8:
switch (a_iNthArg) {
case 2:
if(a_iNthString >= 0 && a_iNthString < 11) {
strncpy (a_psCustomString->szString, l_sTheStrings[a_iNthString].szString,
sizeof(a_psCustomString->szString)-1);
a_psCustomString->iID = l_sTheStrings[a_iNthString].iID;
}
break;
default:
l_bRtrn = MSX_ERROR;
break;
}
break;
case 12:
switch (a_iNthArg) {
case 1:
if(a_iNthString >= 0 && a_iNthString < 11) {
strncpy (a_psCustomString->szString, CustomIndexPrice[a_iNthString].szString,
sizeof(a_psCustomString->szString)-1);
a_psCustomString->iID = CustomIndexPrice[a_iNthString].iID;
}
break;
case 2:
if(a_iNthString >= 0 && a_iNthString < 5) {
strncpy (a_psCustomString->szString, CustomIndexMethod[a_iNthString].szString,
sizeof(a_psCustomString->szString)-1);
a_psCustomString->iID = CustomIndexMethod[a_iNthString].iID;
}
break;
default:
l_bRtrn = MSX_ERROR;
break;
}
break;
default:
l_bRtrn = MSX_ERROR;
break;
}
return l_bRtrn;
}
// ****************DO NOT CHANGE ANYTHING HERE*****************************
// This local utility function is used to help ensure that no overflows
// or underflows will occur during calcuations. The MSXTest program
// Stress Test function will call your DLL with a wide range of values,
// including positive and negative values of FLT_MAX and FLT_MIN.
// Perform all intermediate calculations using doubles and then force the
// results into the range of a float.
// Locally defined macros are used to avoid compiler definition differences
// ************************************************************************
#define MSXMax(a,b) (((a) > (b)) ? (a) : (b))
#define MSXMin(a,b) (((a) < (b)) ? (a) : (b))
double ForceFloatRange (double a_lfDbl)
{
if (a_lfDbl > 0.0)
{
a_lfDbl = MSXMin (a_lfDbl, double(FLT_MAX)); // make sure positive number <= FLT_MAX
a_lfDbl = MSXMax (a_lfDbl, double(FLT_MIN)); // make sure pos number >= FLT_MIN
}
else
{
if (a_lfDbl < 0.0)
{
a_lfDbl = MSXMax (a_lfDbl, double(-FLT_MAX)); // make sure neg number >= -FLT_MAX
a_lfDbl = MSXMin (a_lfDbl, double(-FLT_MIN)); // make sure neg number <= -FLT_MIN
}
}
return a_lfDbl;
}
//********************************START LATCH FUNCTION **********************
BOOL __stdcall Latch (const MSXDataRec *a_psDataRec,
const MSXDataInfoRecArgsArray *a_psDataInfoArgs,
const MSXNumericArgsArray *a_psNumericArgs,
const MSXStringArgsArray *a_psStringArgs,
const MSXCustomArgsArray *a_psCustomArgs,
MSXResultRec *a_psResultRec)
{
BOOL l_bRtrn = MSX_SUCCESS;
int i = 0;
int MaxRecords = a_psDataRec->sClose.iLastValid;
const MSXDataInfoRec *l_psLE; l_psLE = a_psDataInfoArgs->psDataInfoRecs[0];
const MSXDataInfoRec *l_psLX; l_psLX = a_psDataInfoArgs->psDataInfoRecs[1];
const MSXDataInfoRec *l_psSE; l_psSE = a_psDataInfoArgs->psDataInfoRecs[2];
const MSXDataInfoRec *l_psSX; l_psSX = a_psDataInfoArgs->psDataInfoRecs[3];
for (i=0; i<=MaxRecords; i++)
{ if(i==0){ a_psResultRec->psResultArray->pfValue[i] = 0;}
else if( l_psLE->pfValue[i] == 1){a_psResultRec->psResultArray->pfValue[i] = 1;}
else if( l_psSE->pfValue[i] == 1){a_psResultRec->psResultArray->pfValue[i] = -1;}
else if(( l_psLX->pfValue[i] == 1 && a_psResultRec->psResultArray->pfValue[i - 1]== 1)
|| l_psSX->pfValue[i] == 1 && a_psResultRec->psResultArray->pfValue[i - 1]==-1){
a_psResultRec->psResultArray->pfValue[i] = 0;}
else { a_psResultRec->psResultArray->pfValue[i] = a_psResultRec->psResultArray->pfValue[i - 1];}
}
if (l_bRtrn != MSX_SUCCESS) { // only for serious errors...
a_psResultRec->psResultArray->iFirstValid = 0;
a_psResultRec->psResultArray->iLastValid = -1;
}
return l_bRtrn;
}
//*********************************END LATCH FUNCTION**********************************************
//*********************************START DATE RANGE FUNCTION***************************************
BOOL __stdcall DateRange ( const MSXDataRec *a_psDataRec,
const MSXDataInfoRecArgsArray *a_psDataInfoArgs,
const MSXNumericArgsArray *a_psNumericArgs,
const MSXStringArgsArray *a_psStringArgs,
const MSXCustomArgsArray *a_psCustomArgs,
MSXResultRec *a_psResultRec)
{
BOOL l_bRtrn = MSX_SUCCESS;
int i=0;
int MaxRecords = a_psDataRec->sClose.iLastValid;
MSXDateTime *psDate = a_psDataRec->psDate;
int IntDate = 0;
const MSXDataInfoRec *l_StartDate; l_StartDate = a_psDataInfoArgs->psDataInfoRecs[0];
const MSXDataInfoRec *l_EndDate; l_EndDate = a_psDataInfoArgs->psDataInfoRecs[1];
for(i=0; i<=MaxRecords; i++)
{
IntDate = psDate[i].lDate;
if(l_StartDate->pfValue[i]==0 && IntDate <= l_EndDate->pfValue[i])
{a_psResultRec->psResultArray->pfValue[i]= 1;}
else if(l_EndDate->pfValue[i]==0 && IntDate >= l_StartDate->pfValue[i])
{a_psResultRec->psResultArray->pfValue[i]= 1;}
else if(IntDate >= l_StartDate->pfValue[i] && IntDate <= l_EndDate->pfValue[i])
{a_psResultRec->psResultArray->pfValue[i]= 1;}
}
// only for serious errors...
if (l_bRtrn != MSX_SUCCESS)
{
a_psResultRec->psResultArray->iFirstValid = 0;
a_psResultRec->psResultArray->iLastValid = -1;
}
return l_bRtrn;
}
//*********************************END DATE RANGE FUNCTION******************************************
//*********************************START VARREF FUNCTION********************************************
BOOL __stdcall VarREF (const MSXDataRec *a_psDataRec,
const MSXDataInfoRecArgsArray *a_psDataInfoArgs,
const MSXNumericArgsArray *a_psNumericArgs,
const MSXStringArgsArray *a_psStringArgs,
const MSXCustomArgsArray *a_psCustomArgs,
MSXResultRec *a_psResultRec)
{
BOOL l_bRtrn = MSX_SUCCESS;
const MSXDataInfoRec *l_VarVal; l_VarVal = a_psDataInfoArgs->psDataInfoRecs[0];
const MSXDataInfoRec *l_VarPer; l_VarPer = a_psDataInfoArgs->psDataInfoRecs[1];
int MinRecords = a_psResultRec->psResultArray->iFirstValid;
int MaxRecords = a_psResultRec->psResultArray->iLastValid;
int i = 0;
for (int i = MinRecords; i <= MaxRecords; i++ ){
int J = static_cast<int>(l_VarPer->pfValue[i]);
if( J >= i){J = 0;}
a_psResultRec->psResultArray->pfValue[i] = l_VarVal->pfValue[i-J];
}
if (l_bRtrn != MSX_SUCCESS) { // only for serious errors...
a_psResultRec->psResultArray->iFirstValid = 0;
a_psResultRec->psResultArray->iLastValid = -1;
}
return l_bRtrn;
}
//*********************************END VARREF FUNCTION*******************************************
//*********************************START VARHHV FUNCTION*****************************************
BOOL __stdcall VarHHV (const MSXDataRec *a_psDataRec,
const MSXDataInfoRecArgsArray *a_psDataInfoArgs,
const MSXNumericArgsArray *a_psNumericArgs,
const MSXStringArgsArray *a_psStringArgs,
const MSXCustomArgsArray *a_psCustomArgs,
MSXResultRec *a_psResultRec)
{ BOOL l_bRtrn = MSX_SUCCESS;
const MSXDataInfoRec *l_VarVal; l_VarVal = a_psDataInfoArgs->psDataInfoRecs[0];
const MSXDataInfoRec *l_VarPer; l_VarPer = a_psDataInfoArgs->psDataInfoRecs[1];
int MinRecords = a_psResultRec->psResultArray->iFirstValid;
int MaxRecords = a_psResultRec->psResultArray->iLastValid;
int i = 0;
float MaxValue = 0;
for (i = MinRecords; i <= MaxRecords; i++ )
{ int j = abs(static_cast<int>(l_VarPer->pfValue[i])); //Convert variable period to int
if( j > i) {j=i;} //If variable int is greater than current bar count use current bar count
float MaxValue = 0;
int t=0;
for(t=0;t<j;t++){
if(t == 0) { MaxValue = l_VarVal->pfValue[i];}
if(MaxValue<l_VarVal->pfValue[i-t]) { MaxValue = l_VarVal->pfValue[i-t];}
}
a_psResultRec->psResultArray->pfValue[i] = MaxValue;
}
if (l_bRtrn != MSX_SUCCESS) { // only for serious errors...
a_psResultRec->psResultArray->iFirstValid = 0;
a_psResultRec->psResultArray->iLastValid = -1;
}
return l_bRtrn;
}
//*********************************END VARHHV FUNCTION*****************************************
//*********************************START VARLLV FUNCTION*****************************************
BOOL __stdcall VarLLV (const MSXDataRec *a_psDataRec,
const MSXDataInfoRecArgsArray *a_psDataInfoArgs,
const MSXNumericArgsArray *a_psNumericArgs,
const MSXStringArgsArray *a_psStringArgs,
const MSXCustomArgsArray *a_psCustomArgs,
MSXResultRec *a_psResultRec)
{ BOOL l_bRtrn = MSX_SUCCESS;
const MSXDataInfoRec *l_VarVal; l_VarVal = a_psDataInfoArgs->psDataInfoRecs[0];
const MSXDataInfoRec *l_VarPer; l_VarPer = a_psDataInfoArgs->psDataInfoRecs[1];
int MinRecords = a_psResultRec->psResultArray->iFirstValid;
int MaxRecords = a_psResultRec->psResultArray->iLastValid;
int i = 0;
float MinValue = 0;
for (i = MinRecords; i <= MaxRecords; i++ )
{ int j = abs(static_cast<int>(l_VarPer->pfValue[i])); //Convert variable period to int
if( j > i) {j=i;} //If variable int is greater than current bar count use current bar count
float MinValue = 0;
int t=0;
for(t=0;t<j;t++){
if(t == 0) { MinValue = l_VarVal->pfValue[i];}
if(MinValue>l_VarVal->pfValue[i-t]) { MinValue = l_VarVal->pfValue[i-t];}
}
a_psResultRec->psResultArray->pfValue[i] = MinValue;
}
if (l_bRtrn != MSX_SUCCESS) { // only for serious errors...
a_psResultRec->psResultArray->iFirstValid = 0;
a_psResultRec->psResultArray->iLastValid = -1;
}
return l_bRtrn;
}
//*********************************END VARLLV FUNCTION*****************************************
//*********************************START VARSUM FUNCTION***************************************
BOOL __stdcall VarSUM (const MSXDataRec *a_psDataRec,
const MSXDataInfoRecArgsArray *a_psDataInfoArgs,
const MSXNumericArgsArray *a_psNumericArgs,
const MSXStringArgsArray *a_psStringArgs,
const MSXCustomArgsArray *a_psCustomArgs,
MSXResultRec *a_psResultRec)
{ BOOL l_bRtrn = MSX_SUCCESS;
const MSXDataInfoRec *l_VarVal; l_VarVal = a_psDataInfoArgs->psDataInfoRecs[0];
const MSXDataInfoRec *l_VarPer; l_VarPer = a_psDataInfoArgs->psDataInfoRecs[1];
int MaxRecords = a_psResultRec->psResultArray->iLastValid;
int i = 0;
float SumValue = 0;
for (i = static_cast<int>(l_VarPer->pfValue[1]); i <= MaxRecords; i++ )
{ int j = abs(static_cast<int>(l_VarPer->pfValue[i])); //Convert variable period to int
if( j > i) {j=0;} //If variable int is greater than current bar count use current bar count
int t=0;
for(t=0;t<j;t++){
if(t == 0) { SumValue = l_VarVal->pfValue[i];}
if(t != 0) { SumValue += l_VarVal->pfValue[i-t];}
}
a_psResultRec->psResultArray->pfValue[i] = SumValue;
}
if (l_bRtrn != MSX_SUCCESS) { // only for serious errors...
a_psResultRec->psResultArray->iFirstValid = 0;
a_psResultRec->psResultArray->iLastValid = -1;
}
return l_bRtrn;
}
//*********************************END VARSUM FUNCTION*****************************************
//*********************************START VARHHVBARS FUNCTION*****************************************
BOOL __stdcall VarHHVBARS (const MSXDataRec *a_psDataRec,
const MSXDataInfoRecArgsArray *a_psDataInfoArgs,
const MSXNumericArgsArray *a_psNumericArgs,
const MSXStringArgsArray *a_psStringArgs,
const MSXCustomArgsArray *a_psCustomArgs,
MSXResultRec *a_psResultRec)
{ BOOL l_bRtrn = MSX_SUCCESS;
const MSXDataInfoRec *l_VarVal; l_VarVal = a_psDataInfoArgs->psDataInfoRecs[0];
const MSXDataInfoRec *l_VarPer; l_VarPer = a_psDataInfoArgs->psDataInfoRecs[1];
int MinRecords = a_psResultRec->psResultArray->iFirstValid;
int MaxRecords = a_psResultRec->psResultArray->iLastValid;
int i = 0;
float MaxValue = 0;
for (i = MinRecords; i <= MaxRecords; i++ )
{ int j = abs(static_cast<int>(l_VarPer->pfValue[i])); //Convert variable period to int
if( j > i || j < 1) {j=0;} //If variable int is greater than current bar count use current bar count
float MaxValue = 0;
int t=0;
int counter = 0;
for(t=0;t<j;t++){
if(t == 0) { MaxValue = l_VarVal->pfValue[i]; counter = i;}
if(MaxValue<l_VarVal->pfValue[i-t]) { MaxValue = l_VarVal->pfValue[i-t]; counter = i - t;}
}
a_psResultRec->psResultArray->pfValue[i] = static_cast<float>(i-counter);
}
if (l_bRtrn != MSX_SUCCESS) { // only for serious errors...
a_psResultRec->psResultArray->iFirstValid = 0;
a_psResultRec->psResultArray->iLastValid = -1;
}
return l_bRtrn;
}
//*********************************END VARHHVBARS FUNCTION*****************************************
//*********************************START VARLLVBARS FUNCTION*****************************************
BOOL __stdcall VarLLVBARS (const MSXDataRec *a_psDataRec,
const MSXDataInfoRecArgsArray *a_psDataInfoArgs,
const MSXNumericArgsArray *a_psNumericArgs,
const MSXStringArgsArray *a_psStringArgs,
const MSXCustomArgsArray *a_psCustomArgs,
MSXResultRec *a_psResultRec)
{ BOOL l_bRtrn = MSX_SUCCESS;
const MSXDataInfoRec *l_VarVal; l_VarVal = a_psDataInfoArgs->psDataInfoRecs[0];
const MSXDataInfoRec *l_VarPer; l_VarPer = a_psDataInfoArgs->psDataInfoRecs[1];
int MinRecords = a_psResultRec->psResultArray->iFirstValid;
int MaxRecords = a_psResultRec->psResultArray->iLastValid;
int i = 0;
float MinValue = 0;
for (i = MinRecords; i <= MaxRecords; i++ )
{ int j = abs(static_cast<int>(l_VarPer->pfValue[i])); //Convert variable period to int
if( j > i || j < 1) {j=0;} //If variable int is greater than current bar count use current bar count
float MinValue = 0;
int t=0;
int counter = 0;
for(t=0;t<j;t++){
if(t == 0) { MinValue = l_VarVal->pfValue[i]; counter = i;}
if(MinValue>l_VarVal->pfValue[i-t]) { MinValue = l_VarVal->pfValue[i-t]; counter = i - t;}
}
a_psResultRec->psResultArray->pfValue[i] = static_cast<float>(i-counter);
}
if (l_bRtrn != MSX_SUCCESS) { // only for serious errors...
a_psResultRec->psResultArray->iFirstValid = 0;
a_psResultRec->psResultArray->iLastValid = -1;
}
return l_bRtrn;
}
//*********************************END VARLLVBARS FUNCTION*****************************************
//*********************************START VARMOV FUNCTION*******************************************
void MovingAverage (const MSXDataInfoRec *a_psSrc, MSXDataInfoRec *a_psRslt,
int a_iPeriod, BOOL a_bIsWeighted)
{
int l_iIndex = a_psSrc->iFirstValid;
int l_iMaxIndex = a_psSrc->iLastValid;
double l_lfSum = 0.0;
double l_lfDbl;
float l_fDivisor;
int i;
if (a_bIsWeighted)
l_fDivisor = float(a_iPeriod) * (float(a_iPeriod)+1.0f) / 2.0f; // sum of the digits formula
else
l_fDivisor = float(a_iPeriod);
l_fDivisor = float(ForceFloatRange (l_fDivisor));
if (l_fDivisor == 0.0)
l_fDivisor = 1.0f;
while ((l_iIndex + a_iPeriod - 1) <= l_iMaxIndex) {
l_lfSum = 0.0;
for (i=0; i<a_iPeriod; i++) {
if (a_bIsWeighted)
l_lfSum += a_psSrc->pfValue[l_iIndex+i] * (i + 1.0f);
else
l_lfSum += a_psSrc->pfValue[l_iIndex+i];
}
l_lfSum = ForceFloatRange(l_lfSum);
l_lfDbl = l_lfSum / l_fDivisor;
l_lfDbl = ForceFloatRange(l_lfDbl);
a_psRslt->pfValue[l_iIndex + a_iPeriod - 1] = float(l_lfDbl);
l_iIndex++;
}
a_psRslt->iFirstValid = a_psSrc->iFirstValid + a_iPeriod - 1;
a_psRslt->iLastValid = l_iMaxIndex;
}
void ExponentialMovingAverage (const MSXDataInfoRec *a_psSrc,
MSXDataInfoRec *a_psRslt,
int a_iPeriod)
{
int l_iIndex = a_psSrc->iFirstValid;
int l_iMaxIndex = a_psSrc->iLastValid;
double l_lfSum = 0.0;
double l_lfDivisor;
double l_lfExponent;
int i;
if (a_iPeriod > 0 && ((l_iIndex + a_iPeriod - 1) <= l_iMaxIndex)) {
l_lfExponent = ForceFloatRange(2.0 / (a_iPeriod+1));
l_lfDivisor = double(a_iPeriod);
// start with simple moving average;
for (i=0; i<a_iPeriod; i++)
l_lfSum += a_psSrc->pfValue[l_iIndex+i];
l_lfSum = ForceFloatRange(l_lfSum);
a_psRslt->pfValue[l_iIndex + a_iPeriod - 1] = float(ForceFloatRange(l_lfSum / l_lfDivisor));
l_iIndex += a_iPeriod;
while (l_iIndex <= l_iMaxIndex) {
a_psRslt->pfValue[l_iIndex] =
float(ForceFloatRange((a_psSrc->pfValue[l_iIndex] - a_psRslt->pfValue[l_iIndex-1]) *
l_lfExponent + a_psRslt->pfValue[l_iIndex-1]));
l_iIndex++;
}
a_psRslt->iFirstValid = a_psSrc->iFirstValid + a_iPeriod - 1;
a_psRslt->iLastValid = l_iMaxIndex;
}
else {
a_psRslt->iFirstValid = 0;
a_psRslt->iLastValid = -1;
}
}
BOOL __stdcall VarMOV (const MSXDataRec *a_psDataRec,
const MSXDataInfoRecArgsArray *a_psDataInfoArgs,
const MSXNumericArgsArray *a_psNumericArgs,
const MSXStringArgsArray *a_psStringArgs,
const MSXCustomArgsArray *a_psCustomArgs,
MSXResultRec *a_psResultRec)
{
BOOL l_bRtrn = MSX_SUCCESS;
const MSXDataInfoRec *l_psData;
const MSXDataInfoRec *l_psVarPer;
int l_iMethod;
int l_iIndex;
int l_iMaxIndex;
l_psData = a_psDataInfoArgs->psDataInfoRecs[0];
l_psVarPer = a_psDataInfoArgs->psDataInfoRecs[1];
int l_iPeriod = 0;
l_iMethod = a_psCustomArgs->iCustomIDs[0];
l_iIndex = l_psData->iFirstValid;
l_iMaxIndex = l_psData->iLastValid;
int i = 0;
for(i=0;i<=l_iMaxIndex;i++){
l_iPeriod = static_cast<int>(l_psVarPer->pfValue[i]);
if(l_iPeriod > i){l_iPeriod = i;}
if (l_iPeriod > 0 && (l_iIndex + l_iPeriod - 1) <= l_iMaxIndex &&
l_iIndex > 0 && l_iMaxIndex > 0 &&
l_iIndex >= a_psDataRec->sClose.iFirstValid &&
l_iMaxIndex <= a_psDataRec->sClose.iLastValid) {
switch (l_iMethod) {
case 0: // Simple
MovingAverage (l_psData, a_psResultRec->psResultArray, l_iPeriod, FALSE);
break;
case 1: // Triangular
{
MSXDataInfoRec l_sTmpRec;
l_sTmpRec.pfValue = new float[l_iMaxIndex+1];
if (l_sTmpRec.pfValue) {
l_iPeriod = (int)(((l_iPeriod+1.0)/2) + 0.5);
MovingAverage (l_psData, &l_sTmpRec, l_iPeriod, FALSE);
MovingAverage (&l_sTmpRec, a_psResultRec->psResultArray, l_iPeriod, FALSE);
delete l_sTmpRec.pfValue;
}
else {
a_psResultRec->psResultArray->iFirstValid = 0;
a_psResultRec->psResultArray->iLastValid = -1;
}
}
break;
case 2: // Weighted
MovingAverage (l_psData, a_psResultRec->psResultArray, l_iPeriod, TRUE);
break;
case 3: // Exponential
ExponentialMovingAverage (l_psData, a_psResultRec->psResultArray, l_iPeriod);
break;
default:
{
// Somehow we got called with an invalid argument
strncpy (a_psResultRec->szExtendedError, "Undefined method argument",
sizeof(a_psResultRec->szExtendedError)-1);
l_bRtrn = MSX_ERROR; // report this as an error
}
break;
}
}
else {
a_psResultRec->psResultArray->iFirstValid = 0;
a_psResultRec->psResultArray->iLastValid = -1;
}
if (l_bRtrn != MSX_SUCCESS) { // only for serious errors...
a_psResultRec->psResultArray->iFirstValid = 0;
a_psResultRec->psResultArray->iLastValid = -1;
}}
return l_bRtrn;
}
//*********************************END VARMOV FUNCTION*******************************************
BOOL __stdcall VarRSI (const MSXDataRec *a_psDataRec,
const MSXDataInfoRecArgsArray *a_psDataInfoArgs,
const MSXNumericArgsArray *a_psNumericArgs,
const MSXStringArgsArray *a_psStringArgs,
const MSXCustomArgsArray *a_psCustomArgs,
MSXResultRec *a_psResultRec)
{ BOOL l_bRtrn = MSX_SUCCESS;
const MSXDataInfoRec *l_VarVal; l_VarVal = a_psDataInfoArgs->psDataInfoRecs[0];
const MSXDataInfoRec *l_VarPer; l_VarPer = a_psDataInfoArgs->psDataInfoRecs[1];
int i;
int periods;
double UpChange = 0.0;
double DnChange = 0.0;
double UpAverage = 0.0;
double DnAverage = 0.0;
for ( i = static_cast<int>(l_VarPer->pfValue[1]+1); i <=static_cast<int>(l_VarVal->iLastValid); i++ )
{ periods = abs(static_cast<int>(l_VarPer->pfValue[i]));
if(i<periods){periods=i;}
UpChange = l_VarVal->pfValue[i]- l_VarVal->pfValue[i-1];
DnChange = UpChange;
UpChange = l_VarVal->pfValue[i] - l_VarVal->pfValue[i - 1];
DnChange = UpChange;
if ( ( UpChange < 0.0 ) )
UpChange = 0.0;
if ( ( DnChange > 0.0 ) )
DnChange = 0.0;
else
DnChange = fabs( DnChange );
if ( ( i <= periods + 1 ) )
{
UpAverage += UpChange;
DnAverage += DnChange;
if ( ( i == periods + 1 ) )
{
UpAverage /= i;
DnAverage /= i;
} /* if lp */
} /* if lp */
else
{
UpAverage =( ( UpAverage * ( periods - 1 ) ) + UpChange ) / max(periods,0.001);
DnAverage =( ( DnAverage * ( periods - 1 ) ) + DnChange ) / max(periods,0.001);
}
a_psResultRec->psResultArray->pfValue[i] = static_cast<float>(UpAverage/(max(abs(DnAverage),0.0001)));
a_psResultRec->psResultArray->pfValue[i] = (100 - ((float)100 /((a_psResultRec->psResultArray->pfValue[i]) + (float)1.0)));
a_psResultRec->psResultArray->iFirstValid = periods+1;
}
return l_bRtrn;
}
//*********************************END VARRSI FUNCTION*******************************************
//*********************************START VARMOM FUNCTION*****************************************
BOOL __stdcall VarMOM (const MSXDataRec *a_psDataRec,
const MSXDataInfoRecArgsArray *a_psDataInfoArgs,
const MSXNumericArgsArray *a_psNumericArgs,
const MSXStringArgsArray *a_psStringArgs,
const MSXCustomArgsArray *a_psCustomArgs,
MSXResultRec *a_psResultRec)
{ BOOL l_bRtrn = MSX_SUCCESS;
const MSXDataInfoRec *l_VarVal; l_VarVal = a_psDataInfoArgs->psDataInfoRecs[0];
const MSXDataInfoRec *l_VarPer; l_VarPer = a_psDataInfoArgs->psDataInfoRecs[1];
int MinRecords = a_psResultRec->psResultArray->iFirstValid;
int MaxRecords = a_psResultRec->psResultArray->iLastValid;
int i = 0;
int periods = 0;
for ( i = 1; i <= MaxRecords; i++ )
{periods = abs(static_cast<int>(l_VarPer->pfValue[i]));
if (i>periods)
{
if ( l_VarVal->pfValue[i-periods] != 0.0 )
a_psResultRec->psResultArray->pfValue[i] = (float)( (l_VarVal->pfValue[i]/l_VarVal->pfValue[i-periods] ) * 100.0 );
else
a_psResultRec->psResultArray->pfValue[i] = 0.0f;
}
else
a_psResultRec->psResultArray->pfValue[i] = 0.0f;
}
if (l_bRtrn != MSX_SUCCESS) { // only for serious errors...
a_psResultRec->psResultArray->iFirstValid = 0;
a_psResultRec->psResultArray->iLastValid = -1;
}
return l_bRtrn;
}
//*********************************END VARMOM FUNCTION*****************************************
//*********************************START VARCMO FUNCTION*****************************************
BOOL __stdcall VarCMO (const MSXDataRec *a_psDataRec,
const MSXDataInfoRecArgsArray *a_psDataInfoArgs,
const MSXNumericArgsArray *a_psNumericArgs,
const MSXStringArgsArray *a_psStringArgs,
const MSXCustomArgsArray *a_psCustomArgs,
MSXResultRec *a_psResultRec)
{ BOOL l_bRtrn = MSX_SUCCESS;
const MSXDataInfoRec *l_VarVal; l_VarVal = a_psDataInfoArgs->psDataInfoRecs[0];
const MSXDataInfoRec *l_VarPer; l_VarPer = a_psDataInfoArgs->psDataInfoRecs[1];
int MinRecords = a_psResultRec->psResultArray->iFirstValid;
int MaxRecords = a_psResultRec->psResultArray->iLastValid;
int i = 0;
int periods = 0;
float fSumUpDays = 0.0F;
float fSumDownDays = 0.0F;
for (i=MinRecords+1; i<= MaxRecords; i++ )
{periods = abs(static_cast<int>(l_VarPer->pfValue[i]));
if (l_VarVal->pfValue[i] > l_VarVal->pfValue[i-1])
fSumUpDays += (l_VarVal->pfValue[i] - l_VarVal->pfValue[i-1]);
else if (l_VarVal->pfValue[i] < l_VarVal->pfValue[i-1])
fSumDownDays += (float)fabs(l_VarVal->pfValue[i] - l_VarVal->pfValue[i-1]);
if (i > (MinRecords + periods))
{if (l_VarVal->pfValue[i-periods] > l_VarVal->pfValue[i - periods - 1])
fSumUpDays -= (l_VarVal->pfValue[i-periods] - l_VarVal->pfValue[i-periods - 1]);
else if (l_VarVal->pfValue[i-periods] < l_VarVal->pfValue[i-periods - 1])
fSumDownDays -= (float)fabs(l_VarVal->pfValue[i-periods] - l_VarVal->pfValue[i-periods - 1]);
}
if (fSumUpDays + fSumDownDays)
a_psResultRec->psResultArray->pfValue[i] = 100.0F * (fSumUpDays - fSumDownDays)/(fSumUpDays + fSumDownDays);
else
a_psResultRec->psResultArray->pfValue[i] = 0.0F;
}
if (l_bRtrn != MSX_SUCCESS) { // only for serious errors...
a_psResultRec->psResultArray->iFirstValid = 0;
a_psResultRec->psResultArray->iLastValid = -1;
}
return l_bRtrn;
}
//*********************************END VARCMO FUNCTION*****************************************
//*********************************START TD COMBO FUNCTION******************************************
BOOL __stdcall TDCOMBO (const MSXDataRec *a_psDataRec,
const MSXDataInfoRecArgsArray *a_psDataInfoArgs,
const MSXNumericArgsArray *a_psNumericArgs,
const MSXStringArgsArray *a_psStringArgs,
const MSXCustomArgsArray *a_psCustomArgs,
MSXResultRec *a_psResultRec)
{ BOOL l_bRtrn = MSX_SUCCESS;
int MinRecords = a_psResultRec->psResultArray->iFirstValid;
int MaxRecords = a_psResultRec->psResultArray->iLastValid;
int i = MinRecords;
int SetupBuy = 0;
int SetupSell = 0;
int TDBuySetup = 0;
int TDSellSetup = 0;
int BUYCOMBOCD = 0;
int SELLCOMBOCD = 0;
for(i=MinRecords; i<=MaxRecords;i++){
float CloseNow = a_psDataRec->sClose.pfValue[i];
float CloseBack = a_psDataRec->sClose.pfValue[i-3];
float Low2 = a_psDataRec->sLow.pfValue[i-1];
float High2 = a_psDataRec->sHigh.pfValue[i-1];
if( CloseNow < CloseBack){SetupBuy += 1; SetupSell = 0;}
else if( CloseNow > CloseBack){SetupBuy = 0; SetupSell += 1;}
if( SetupBuy >= 9) {TDBuySetup = 1; TDSellSetup = 0;}
else if( SetupSell >= 9) {TDBuySetup = 0; TDSellSetup = 1;}
if( TDBuySetup==1 && CloseNow > Low2) {SELLCOMBOCD = 0; BUYCOMBOCD += 1;}
else if( TDSellSetup==1 && CloseNow < High2) {SELLCOMBOCD += 1; BUYCOMBOCD = 0;}
if( BUYCOMBOCD == 13) {a_psResultRec->psResultArray->pfValue[i] = 1;}
else if( SELLCOMBOCD == 13) {a_psResultRec->psResultArray->pfValue[i] = -1;}
else if( BUYCOMBOCD != 13 && SELLCOMBOCD != 13){a_psResultRec->psResultArray->pfValue[i] = 0;}
}
return l_bRtrn;
}
//*********************************END TDCOMBO FUNCTION*******************************************
//******************************** START RANDOM FUNCTION ****************************************
BOOL __stdcall Random (const MSXDataRec * a_psData,
const MSXDataInfoRecArgsArray *a_psDataInfoArgs,
const MSXNumericArgsArray *a_psNumericArgs,
const MSXStringArgsArray *a_psStringArgs,
const MSXCustomArgsArray *a_psCustomArgs,
MSXResultRec * psResult)
{
BOOL l_bRtrn = MSX_SUCCESS;
const MSXDataInfoRec *l_VarMin; l_VarMin = a_psDataInfoArgs->psDataInfoRecs[0];
const MSXDataInfoRec *l_VarMax; l_VarMax = a_psDataInfoArgs->psDataInfoRecs[1];
int i = 0;
int random_integer = 0;
time_t seconds;
time(&seconds);
for(i=0;i<=a_psData->sClose.iLastValid;i++){
srand((unsigned int) seconds);
int range = (static_cast<int>(l_VarMax->pfValue[i])-static_cast<int>(l_VarMin->pfValue[i]))+1;
random_integer = (rand()%range)+1;
psResult->psResultArray->pfValue[i] = static_cast<float>(random_integer);
}
return l_bRtrn;
}
//******************************** END RANDOM FUNCTION ****************************************
#ifdef __cplusplus
}
#endif