logo
Welcome Guest! To enable all features please Login or Register.

Notification

Icon
Error

Options
Go to last post Go to first unread
DrPain  
#1 Posted : Monday, July 17, 2006 4:36:17 PM(UTC)
DrPain

Rank: Member

Groups: Registered, Registered Users
Joined: 7/10/2006(UTC)
Posts: 25

Greetings all. Been lurking for a while. Appreciate all the great stuff that's been posted! I was looking for details on the GetVar and SetVar functions provided by GV.DLL but couldn't find much. The forum search seems broken, and Google only returns a single post mentioning it. Anyway, it seemed simple enough, so I just wrote my own. Below is the code ripped out of my DLL code. It's not complete in that you'll have to add the usual wrapper code such as MSXInfo and MSXNthFunction. The code that's been #if 0'd out is just debugging code and may be ripped out if you like. It just saves the variable names that have been defined to a text file. The variable names are case insensitive, so the variable longData is the same as LONGDATA. (I think. Untested really, but it should work) Released as freeware. Feel free to do with it what you like. Suggestions and improvements always welcome. [code:1:309a09b811] typedef struct { char * variableName; MSXResultRec resultRec; } SavedVar; typedef std::list<SavedVar *> SavedVarList; typedef SavedVarList::iterator SavedVarListListItr; SavedVarList savedVariablesList; SavedVar *FindSavedVar(char *variableName) { if (savedVariablesList.empty()) return NULL; SavedVar * nextSavedVar; SavedVarListListItr listItr; #if 0 DWORD bytesWritten; HANDLE fileHandle = NULL; fileHandle = CreateFile("c:\\\\FindSavedVar.txt", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if ((fileHandle != 0) && (fileHandle != INVALID_HANDLE_VALUE)) SetFilePointer(fileHandle, 0, NULL, FILE_END); WriteFile(fileHandle, "\\n", 1, &bytesWritten, NULL); #endif listItr = savedVariablesList.begin(); while (listItr != savedVariablesList.end()) { nextSavedVar = *listItr; #if 0 WriteFile(fileHandle, nextSavedVar->variableName, strlen(nextSavedVar->variableName), &bytesWritten, NULL); WriteFile(fileHandle, "\\n", 1, &bytesWritten, NULL); #endif if (!_stricmp(nextSavedVar->variableName, variableName)) return nextSavedVar; ++listItr; } return NULL; } BOOL __stdcall SetVar(const MSXDataRec *a_psDataRec, const MSXDataInfoRecArgsArray *a_psDataInfoArgs, const MSXNumericArgsArray *a_psNumericArgs, const MSXStringArgsArray *a_psStringArgs, const MSXCustomArgsArray *a_psCustomArgs, MSXResultRec *a_psResultRec) { int dataIndex; SavedVar * savedVar; // Set up return variables to default to error condition. a_psResultRec->psResultArray->iFirstValid = 0; a_psResultRec->psResultArray->iLastValid = -1; if (a_psDataInfoArgs->iNRecs != 1) { strncpy_s(a_psResultRec->szExtendedError, "SetVar: Wrong number of arguments", sizeof(a_psResultRec->szExtendedError) - 1); return MSX_ERROR; } if (a_psStringArgs->iNRecs != 1) { strncpy_s(a_psResultRec->szExtendedError, "SetVar: Wrong number of arguments", sizeof(a_psResultRec->szExtendedError) - 1); return MSX_ERROR; } savedVar = FindSavedVar(a_psStringArgs->pszStrings[0]); if (savedVar == NULL) { // New variable. Create it. savedVar = new SavedVar; savedVar->variableName = new char[strlen(a_psStringArgs->pszStrings[0]) + 10]; strcpy_s(savedVar->variableName, strlen(a_psStringArgs->pszStrings[0]) + 1, a_psStringArgs->pszStrings[0]); savedVar->resultRec.psResultArray = new MSXDataInfoRec; savedVar->resultRec.psResultArray->pfValue = new float[65500]; // save room for max size savedVariablesList.push_back(savedVar); } savedVar->resultRec.psResultArray->iFirstValid = a_psDataInfoArgs->psDataInfoRecs[0]->iFirstValid; savedVar->resultRec.psResultArray->iLastValid = a_psDataInfoArgs->psDataInfoRecs[0]->iLastValid; for (dataIndex = a_psDataInfoArgs->psDataInfoRecs[0]->iFirstValid; dataIndex <= a_psDataInfoArgs->psDataInfoRecs[0]->iLastValid; dataIndex++) savedVar->resultRec.psResultArray->pfValue[dataIndex] = a_psDataInfoArgs->psDataInfoRecs[0]->pfValue[dataIndex]; return MSX_SUCCESS; } BOOL __stdcall GetVar(const MSXDataRec *a_psDataRec, const MSXDataInfoRecArgsArray *a_psDataInfoArgs, const MSXNumericArgsArray *a_psNumericArgs, const MSXStringArgsArray *a_psStringArgs, const MSXCustomArgsArray *a_psCustomArgs, MSXResultRec *a_psResultRec) { int dataIndex; SavedVar * savedVar; // Set up return variables to default to error condition. a_psResultRec->psResultArray->iFirstValid = 0; a_psResultRec->psResultArray->iLastValid = -1; if (a_psStringArgs->iNRecs != 1) { strcpy_s(a_psResultRec->szExtendedError, MSX_MAXSTRING - 1, "GetVar: Wrong number of arguments"); return MSX_ERROR; } savedVar = FindSavedVar(a_psStringArgs->pszStrings[0]); if (savedVar == NULL) { sprintf_s(a_psResultRec->szExtendedError, MSX_MAXSTRING - 1, "GetVar: Variable '%s' not found", a_psStringArgs->pszStrings[0]); return MSX_ERROR; } for (dataIndex = savedVar->resultRec.psResultArray->iFirstValid; dataIndex <= savedVar->resultRec.psResultArray->iLastValid; dataIndex++) a_psResultRec->psResultArray->pfValue[dataIndex] = savedVar->resultRec.psResultArray->pfValue[dataIndex]; a_psResultRec->psResultArray->iFirstValid = savedVar->resultRec.psResultArray->iFirstValid; a_psResultRec->psResultArray->iLastValid = savedVar->resultRec.psResultArray->iLastValid; return MSX_SUCCESS; } [/code:1:309a09b811]
DrPain  
#2 Posted : Sunday, July 23, 2006 10:09:32 PM(UTC)
DrPain

Rank: Member

Groups: Registered, Registered Users
Joined: 7/10/2006(UTC)
Posts: 25

Added function DeleteAllSavedVars(), which should be called from DllMain's DLL_PROCESS_DETACH case statement. Also changed the the copying of the data from a loop to a single memcpy. Should speed things up a bit. [code:1:3ae0149b97] typedef struct { char * variableName; MSXResultRec resultRec; } SavedVar; typedef std::list<SavedVar *> SavedVarList; typedef SavedVarList::iterator SavedVarListListItr; SavedVarList savedVariablesList; void DeleteAllSavedVars(void) { if (savedVariablesList.empty()) return; SavedVar *nextSavedVar; while (!savedVariablesList.empty()) { nextSavedVar = savedVariablesList.back(); delete nextSavedVar->resultRec.psResultArray->pfValue; delete nextSavedVar->resultRec.psResultArray; delete nextSavedVar->variableName; delete nextSavedVar; savedVariablesList.pop_back(); } } SavedVar *FindSavedVar(char *variableName) { if (savedVariablesList.empty()) return NULL; SavedVar * nextSavedVar; SavedVarListListItr listItr; #if 0 DWORD bytesWritten; HANDLE fileHandle = NULL; fileHandle = CreateFile("c:\\\\FindSavedVar.txt", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if ((fileHandle != 0) && (fileHandle != INVALID_HANDLE_VALUE)) SetFilePointer(fileHandle, 0, NULL, FILE_END); WriteFile(fileHandle, "\\n", 1, &bytesWritten, NULL); #endif listItr = savedVariablesList.begin(); while (listItr != savedVariablesList.end()) { nextSavedVar = *listItr; #if 0 WriteFile(fileHandle, nextSavedVar->variableName, strlen(nextSavedVar->variableName), &bytesWritten, NULL); WriteFile(fileHandle, "\\n", 1, &bytesWritten, NULL); #endif if (!_stricmp(nextSavedVar->variableName, variableName)) return nextSavedVar; ++listItr; } return NULL; } BOOL __stdcall SetVar(const MSXDataRec *a_psDataRec, const MSXDataInfoRecArgsArray *a_psDataInfoArgs, const MSXNumericArgsArray *a_psNumericArgs, const MSXStringArgsArray *a_psStringArgs, const MSXCustomArgsArray *a_psCustomArgs, MSXResultRec *a_psResultRec) { SavedVar * savedVar; // Set up return variables to default to error condition. a_psResultRec->psResultArray->iFirstValid = 0; a_psResultRec->psResultArray->iLastValid = -1; if (a_psDataInfoArgs->iNRecs != 1) { strncpy_s(a_psResultRec->szExtendedError, "SetVar: Wrong number of arguments", sizeof(a_psResultRec->szExtendedError) - 1); return MSX_ERROR; } if (a_psStringArgs->iNRecs != 1) { strncpy_s(a_psResultRec->szExtendedError, "SetVar: Wrong number of arguments", sizeof(a_psResultRec->szExtendedError) - 1); return MSX_ERROR; } savedVar = FindSavedVar(a_psStringArgs->pszStrings[0]); if (savedVar == NULL) { // New variable. Create it. savedVar = new SavedVar; savedVar->variableName = new char[strlen(a_psStringArgs->pszStrings[0]) + 2]; strcpy_s(savedVar->variableName, strlen(a_psStringArgs->pszStrings[0]) + 1, a_psStringArgs->pszStrings[0]); savedVar->resultRec.psResultArray = new MSXDataInfoRec; savedVar->resultRec.psResultArray->pfValue = new float[0xffff]; // save room for max size savedVariablesList.push_back(savedVar); } savedVar->resultRec.psResultArray->iFirstValid = a_psDataInfoArgs->psDataInfoRecs[0]->iFirstValid; savedVar->resultRec.psResultArray->iLastValid = a_psDataInfoArgs->psDataInfoRecs[0]->iLastValid; memcpy((char *)(savedVar->resultRec.psResultArray->pfValue) + (sizeof(float) * savedVar->resultRec.psResultArray->iFirstValid), (char *)(a_psDataInfoArgs->psDataInfoRecs[0]->pfValue) + (sizeof(float) * savedVar->resultRec.psResultArray->iFirstValid), sizeof(float) * (savedVar->resultRec.psResultArray->iLastValid - savedVar->resultRec.psResultArray->iFirstValid + 1)); return MSX_SUCCESS; } BOOL __stdcall GetVar(const MSXDataRec *a_psDataRec, const MSXDataInfoRecArgsArray *a_psDataInfoArgs, const MSXNumericArgsArray *a_psNumericArgs, const MSXStringArgsArray *a_psStringArgs, const MSXCustomArgsArray *a_psCustomArgs, MSXResultRec *a_psResultRec) { SavedVar * savedVar; // Set up return variables to default to error condition. a_psResultRec->psResultArray->iFirstValid = 0; a_psResultRec->psResultArray->iLastValid = -1; if (a_psStringArgs->iNRecs != 1) { strcpy_s(a_psResultRec->szExtendedError, MSX_MAXSTRING - 1, "GetVar: Wrong number of arguments"); return MSX_ERROR; } savedVar = FindSavedVar(a_psStringArgs->pszStrings[0]); if (savedVar == NULL) { sprintf_s(a_psResultRec->szExtendedError, MSX_MAXSTRING - 1, "GetVar: Variable '%s' not found", a_psStringArgs->pszStrings[0]); return MSX_ERROR; } memcpy((char *)a_psResultRec->psResultArray->pfValue + (sizeof(float) * savedVar->resultRec.psResultArray->iFirstValid), (char *)savedVar->resultRec.psResultArray->pfValue + (sizeof(float) * savedVar->resultRec.psResultArray->iFirstValid), sizeof(float) * (savedVar->resultRec.psResultArray->iLastValid - savedVar->resultRec.psResultArray->iFirstValid + 1)); a_psResultRec->psResultArray->iFirstValid = savedVar->resultRec.psResultArray->iFirstValid; a_psResultRec->psResultArray->iLastValid = savedVar->resultRec.psResultArray->iLastValid; return MSX_SUCCESS; } [/code:1:3ae0149b97]
Jose  
#3 Posted : Sunday, July 23, 2006 11:19:33 PM(UTC)
Jose

Rank: Advanced Member

Groups ready for retrieval: Registered, Registered Users
Joined: 1/19/2005(UTC)
Posts: 1,065
Location: Koh Pha-Ngan, Earth

Was thanked: 2 time(s) in 2 post(s)
Good work, DP. Can your code store any precision values passed on by MetaStock? Any chance of adding a "cumulative storage" function, so that each time it is called, it then adds the variable's value to the existing stored value? Can you compile your code into a functioning MetaStock DLL for testing? Many thanks in adv. jose '-)
wabbit  
#4 Posted : Monday, July 24, 2006 12:00:32 AM(UTC)
wabbit

Rank: Advanced Member

Groups: Registered, Registered Users, Subscribers, Unverified Users
Joined: 10/28/2004(UTC)
Posts: 3,111
Location: Perth, Western Australia

Was thanked: 16 time(s) in 16 post(s)
Nice work... Have sent PM with some other stuff for you. wabbit :D
DrPain  
#5 Posted : Monday, July 24, 2006 3:30:05 AM(UTC)
DrPain

Rank: Member

Groups: Registered, Registered Users
Joined: 7/10/2006(UTC)
Posts: 25

Jose: I don't understand what you mean by "precision values passed on by MetaStock". Can you elaborate? For the "cumulative storage" function, do you mean you'd like to add some number (say 5) to the entire data series? Perhaps passed in as a parameter? As for compiling to a DLL, sure, I'd be happy to do that. I'll post a link tomorrow. Wabbit: Replied via PM.
Jose  
#6 Posted : Monday, July 24, 2006 4:05:34 AM(UTC)
Jose

Rank: Advanced Member

Groups ready for retrieval: Registered, Registered Users
Joined: 1/19/2005(UTC)
Posts: 1,065
Location: Koh Pha-Ngan, Earth

Was thanked: 2 time(s) in 2 post(s)
DP, by "precision values" I mean this: could your external function store large numbers, such as "123456.789"? And as well as the read/write/clear functions, a cumulative function would be very useful, specially for adding columns in explorations: ExtFml("DP.Cum","StoredVariable",AddThisVariable); For example: ---8<------------------------------------------- variable:=5 ExtFml("DP.Cum","StoredVariable",variable); ExtFml("DP.Cum","StoredVariable",variable); ExtFml("DP.Cum","StoredVariable",variable); ---8<------------------------------------------- ...would result in ExtFml("DP.Read","StoredVariable") plotting an output of 15 (variable x3 store passes). DP, the two points above would allow your DLL to accurately add Volume for a basket of securities through an exploration. jose '-)
StorkBite  
#7 Posted : Monday, July 24, 2006 6:47:46 PM(UTC)
StorkBite

Rank: Advanced Member

Groups: Registered, Registered Users
Joined: 3/19/2005(UTC)
Posts: 2,995

Was thanked: 14 time(s) in 10 post(s)
Hi DP- Welcome to the forum! This is a great contribution- I listed it as a HOT TOPIC. We get a lot of inquires about gv.dll and documentation. It's always nice to see what's actually happening. I'm not a C++ programmer at all, but couldn't you change your long variables to float or double to accommodate the precision that Jose's mentioning?
DrPain  
#8 Posted : Monday, July 24, 2006 8:23:46 PM(UTC)
DrPain

Rank: Member

Groups: Registered, Registered Users
Joined: 7/10/2006(UTC)
Posts: 25

The variables that are stored are already floats. It's stored in the standard MSXResultRec structure, which uses an array of floats for the data. So, each value can be up to size FLT_MAX (+/- 3.402823466e+38F). Perhaps the confusion came about when I used the variable name "longData" in the first post of this thread? Bad choice of names on my part. Replace that with "floatData". I was just trying to show the case insensitivity, not imply any type of data. And Jose, I will add a Cum function for you. Haven't had a chance to create a seperate DLL yet. Will do that very soon.
DrPain  
#9 Posted : Monday, July 24, 2006 8:30:41 PM(UTC)
DrPain

Rank: Member

Groups: Registered, Registered Users
Joined: 7/10/2006(UTC)
Posts: 25

Oh, and one last thing. I don't have an explicit Clear function. Is that something that would be useful? Should it just zero out the data, or actually delete the variable so it's no longer available, like my DeleteAllSavedVars function does now? Or perhaps something more useful would be a Set function? Then to clear the data, just call Set with a zero for a parameter. ExtFml("DP.Set","StoredVariable",0); That would give more flexibility I suppose. Would you ever need to set the array to anything other than zero?
Jose  
#10 Posted : Monday, July 24, 2006 10:15:04 PM(UTC)
Jose

Rank: Advanced Member

Groups ready for retrieval: Registered, Registered Users
Joined: 1/19/2005(UTC)
Posts: 1,065
Location: Koh Pha-Ngan, Earth

Was thanked: 2 time(s) in 2 post(s)
Thanks, DP. I wouldn't bother with a Clear (reset to zero) function - as long as variables are initialized/reset in memory prior to writing values to them (except for the Cum function of course). I think that DeleteAllSavedVars is a good thing to clear any possible junk memory, and DeleteVar may also prove to be useful in the future. To save on scarce MetaStock formula space, I would also keep all function names as short as possible. For example: ExtFml("DP.Store",... ExtFml("DP.Read",... ExtFml("DP.DelAll",... ExtFml("DP.Cum","... jose '-)
DrPain  
#11 Posted : Tuesday, July 25, 2006 12:17:45 PM(UTC)
DrPain

Rank: Member

Groups: Registered, Registered Users
Joined: 7/10/2006(UTC)
Posts: 25

The source and compiled DLL are now ready for download. The zip includes the Microsoft Visual Studio 5.0 project files as well. http://www.greygames.com/MetaStock/GlobalVars.zip Enjoy!
wabbit  
#12 Posted : Tuesday, July 25, 2006 1:22:16 PM(UTC)
wabbit

Rank: Advanced Member

Groups: Registered, Registered Users, Subscribers, Unverified Users
Joined: 10/28/2004(UTC)
Posts: 3,111
Location: Perth, Western Australia

Was thanked: 16 time(s) in 16 post(s)
Love your work! Thanks. wabbit :D
Jose  
#13 Posted : Tuesday, July 25, 2006 3:05:48 PM(UTC)
Jose

Rank: Advanced Member

Groups ready for retrieval: Registered, Registered Users
Joined: 1/19/2005(UTC)
Posts: 1,065
Location: Koh Pha-Ngan, Earth

Was thanked: 2 time(s) in 2 post(s)
Thanks, DP - excellent work. Some hiccups found with preliminary testing: 1) The version I've just downloaded has no DelAll function available. 2) The indicator below should plot a cumulative output of "3.03", but instead reports an "Invalid incoming ranges" error. [code:1:4c590bae96]x:=1.01; y:=ExtFml("GlobalVars.Cum","GlobalVar",x); y:=ExtFml("GlobalVars.Cum","GlobalVar",x); y:=ExtFml("GlobalVars.Cum","GlobalVar",x); z:=ExtFml("GlobalVars.Get","GlobalVar"); z [/code:1:4c590bae96] Seeding the non-existing "GlobalVar" with a zero value prior to accumulating fixes the problem, but unfortunately also resets the cumulative count: [code:1:4c590bae96] a:=0; y:=ExtFml("GlobalVars.Set","GlobalVar",a); x:=1.01; y:=ExtFml("GlobalVars.Cum","GlobalVar",x); y:=ExtFml("GlobalVars.Cum","GlobalVar",x); y:=ExtFml("GlobalVars.Cum","GlobalVar",x); z:=ExtFml("GlobalVars.Get","GlobalVar"); z [/code:1:4c590bae96] Rather than looking for a way around this limitation, it would be great if the Cum function could pre-test the GlobalVar to see if it already exists, and initialize (seed) it with a zero value if it doesn't (if null -> initialize). 3) At 550Kb GlobalVars.dll is about x12 larger than its predecessor. Any chance of getting it down to a slim size? jose '-)
DrPain  
#14 Posted : Tuesday, July 25, 2006 3:28:31 PM(UTC)
DrPain

Rank: Member

Groups: Registered, Registered Users
Joined: 7/10/2006(UTC)
Posts: 25

Ok, I think the bugs are squashed. And I compiled this version as Release instead of Debug to save the 500K. :) Same link as above.
Jose  
#15 Posted : Tuesday, July 25, 2006 11:31:46 PM(UTC)
Jose

Rank: Advanced Member

Groups ready for retrieval: Registered, Registered Users
Joined: 1/19/2005(UTC)
Posts: 1,065
Location: Koh Pha-Ngan, Earth

Was thanked: 2 time(s) in 2 post(s)
Good job, DP. A couple of observations: ColA exploration (no filter) [code:1:44c5459830]x:=ExtFml("GlobalVars.Cum","count",1); secNr:=ExtFml("GlobalVars.Get","count"); LastValue(secNr) [/code:1:44c5459830] 1) Without LastValue() the exploration above reports N/A (null) values - is it possible to incorporate LastValue() into the DLL so it always plots the last output value throughout the whole data array? 2) GlobalVars.Cum still reports "Invalid incoming ranges" for 51% of securities, and rejects them in the exploration. I can't see any data-derived reason for this - maybe some sort of Dll internal timing problem? jose '-)
mstt  
#16 Posted : Tuesday, July 25, 2006 11:51:13 PM(UTC)
mstt

Rank: Advanced Member

Groups: Registered, Registered Users, Subscribers
Joined: 7/25/2005(UTC)
Posts: 1,042

Was thanked: 57 time(s) in 54 post(s)
Hi DP As per Jose's request I wonder if the Get function could also pre-test the GlobalVar to see if it exists, and initialise it if it doesn't. This would fix an apparent variation from Mark Pyles original GlobalVar. My difficulty is not with the GV being undefined but with the dll generating an unrecoverable error when it hits the Get function. Another problem causing an unrecoverable error seems to be when data is one bar short of generating a valid plot from an indicator using your dll. For example, when using a modified Trade Equity GV LE that requires 104 bars to plot its first valid plot, a security with 103 (weekly) bars of data creates the error(s) below. Securities with a lesser number of bars do not create the same error, though I'm not sure how narrow the error window might be. An MSX DLL has triggered an access violation error All subsequent attempts to use the modified TE formula generate another error. Restarting MetaStock is necessary. Attempt to call an MSX DLL function that has been invalidated. Referenced DLL: "GlobalVar.Set" DLL Message: 8_s That's what happens in MS7.03. The second error message is slightly garbled in MS 9.1 but the effect is exactly the same. An MSX DLL has triggered an access violation error. Attempt to call an MSX DLL function that has been invalidated. Referenced DLL: "GlobalVar.Set" DLL Message: ȇ Apart from these issues the dll works well and I applaud your efforts thus far. Roy MetaStock Tips & Tools
DrPain  
#17 Posted : Wednesday, July 26, 2006 1:50:49 PM(UTC)
DrPain

Rank: Member

Groups: Registered, Registered Users
Joined: 7/10/2006(UTC)
Posts: 25

Quote:
1) Without LastValue() the exploration above reports N/A (null) values - is it possible to incorporate LastValue() into the DLL so it always plots the last output value throughout the whole data array?
Sorry, I don't understand. I read the lastvalue description in the manual, and it says it returns a single numeric which is the last value of the array. How do I incorporate that into the DLL?
Quote:
2) GlobalVars.Cum still reports "Invalid incoming ranges" for 51% of securities, and rejects them in the exploration. I can't see any data-derived reason for this - maybe some sort of Dll internal timing problem?
Hmmm... this must be from the firstValid/lastValid test I do in that function: [code:1:f1ffb41cf7] if (savedVar->resultRec.psResultArray->iFirstValid <= 0 || savedVar->resultRec.psResultArray->iLastValid <= 0 || savedVar->resultRec.psResultArray->iFirstValid < a_psDataInfoArgs->psDataInfoRecs[0]->iFirstValid || savedVar->resultRec.psResultArray->iLastValid > a_psDataInfoArgs->psDataInfoRecs[0]->iLastValid) { // invalid incoming ranges strncpy_s(a_psResultRec->szExtendedError, "Cum: Invalid incoming ranges", sizeof(a_psResultRec->szExtendedError) - 1); return MSX_ERROR; } [/code:1:f1ffb41cf7] I imagine it's because the range of the saved variable don't equal the range of the passed in data array. I'll have to add some logic to determine the overlap between the ranges and use that as the new range. How would you suggest I handle overlap? If the saved array is larger than the passed in array, should I keep the range of the saved var the same, or should I change it to match the smaller passed-in array? If the saved array is smaller than the passed-in array, I suppose I should just process the overlapped data, and return that overlapped portion (as well as changing the range of the saved array to the overlapped area)?
Quote:
As per Jose's request I wonder if the Get function could also pre-test the GlobalVar to see if it exists, and initialise it if it doesn't.
I assumed that if you make a Get request on data that doesn't exist, that would indeed be an error condition, but I can easily change that. I suppose initializing to zeroes over the range of the CLOSE data is appropriate.
Quote:
Another problem causing an unrecoverable error seems to be when data is one bar short of generating a valid plot from an indicator using your dll.
This one has me stumped. I don't know what a "modified Trade Equity GV LE" is. Is it an indicator? Can you tell me the steps required to reproduce this error?
Jose  
#18 Posted : Wednesday, July 26, 2006 10:25:46 PM(UTC)
Jose

Rank: Advanced Member

Groups ready for retrieval: Registered, Registered Users
Joined: 1/19/2005(UTC)
Posts: 1,065
Location: Koh Pha-Ngan, Earth

Was thanked: 2 time(s) in 2 post(s)
DrPain wrote:
Quote:
1) Without LastValue() the exploration above reports N/A (null) values - is it possible to incorporate LastValue() into the DLL so it always plots the last output value throughout the whole data array?
Sorry, I don't understand. I read the lastvalue description in the manual, and it says it returns a single numeric which is the last value of the array. How do I incorporate that into the DLL?
This exploration returns N/A values: [code:1:0e0592bea5]x:=ExtFml("GlobalVars.Cum","count",1); secNr:=ExtFml("GlobalVars.Get","count"); secNr[/code:1:0e0592bea5] Adding a LastValue() function to the exploration output returns correct values: [code:1:0e0592bea5]x:=ExtFml("GlobalVars.Cum","count",1); secNr:=ExtFml("GlobalVars.Get","count"); LastValue(secNr)[/code:1:0e0592bea5] Is there a way for the Dll to emulate this function, i.e., return the last value for the complete data array back to bar 1?
Quote:
How would you suggest I handle overlap? If the saved array is larger than the passed in array, should I keep the range of the saved var the same, or should I change it to match the smaller passed-in array? If the saved array is smaller than the passed-in array, I suppose I should just process the overlapped data, and return that overlapped portion (as well as changing the range of the saved array to the overlapped area)?
I don't understand the above issue(s). I guess try both and see which one results in a count that doesn't skip. :) jose '-)
mstt  
#19 Posted : Wednesday, July 26, 2006 10:51:36 PM(UTC)
mstt

Rank: Advanced Member

Groups: Registered, Registered Users, Subscribers
Joined: 7/25/2005(UTC)
Posts: 1,042

Was thanked: 57 time(s) in 54 post(s)
DP
Quote:
I assumed that if you make a Get request on data that doesn't exist, that would indeed be an error condition, but I can easily change that. I suppose initializing to zeroes over the range of the CLOSE data is appropriate
That should work.
Quote:
This one has me stumped. I don't know what a "modified Trade Equity GV LE" is. Is it an indicator? Can you tell me the steps required to reproduce this error?
This link has many Trade Equity formulas http://www.metastocktips.co.nz/te_formulas.htmlr my particular test the TE indicator is invalid for the first 103 bars and plots a valid signal from bar 104 onward. Setting the number of exploration bars to 103 generates an MSX error on the first security. A lesser number of bars merely produces an MS "Period value out of valid range" error, one that doesn't need MS to be closed and restarted to get around. [code:1:ec38952d3a]{Column A: $ Profit} {Net profit} Eq:=Fml("Trade Equity GVs LE"); Tr:=ExtFml("GVs.Get","Tr"); Cp:=ExtFml("GVs.Get","Cp"); En:=ExtFml("GVs.Get","En"); N:=ExtFml("GVs.Get","N"); LastValue(Cum(N));[/code:1:ec38952d3a] Roy MetaStock Tips & Tools
Users browsing this topic
Guest (Hidden)
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.