MetastockのDLLをゼロから作成するパート2

DLL  Metastock



この記事では、関数( part1part3 )、Metastockからデータを取得し、それらを処理して結果をMetastockに返すためのルールを詳細に調べます。 この情報は、MSX DLLのエラーを回避するのに役立ちます。



関数の形式は次のとおりです。

DLL_EXPORT BOOL __stdcall Price(const MSXDataRec *a_psBasic, const MSXDataInfoRecArgsArray *a_psArrayArgs, const MSXNumericArgsArray *a_psNumericArgs, const MSXStringArgsArray *a_psStringArgs, const MSXCustomArgsArray *a_psCustomArgs, MSXResultRec *a_psResult)
      
      





どこで

* a_psBasic-MSXDataRec構造体へのポインター(有価証券に関するすべての利用可能なデータ);

* a_psArray-MSXDataInfoRecArgsArray構造体(配列引数)へのポインター。

* a_psNumeric-MSXNumericArgsArray構造体へのポインター(数値引数)。

* a_psString-MSXStringArgsArray構造体へのポインター(文字列引数);

* a_psCustom-MSXCustomArgsArray構造体へのポインター(カスタム引数);

* a_psResult-MSXResultRec構造体へのポインター(Metastockに返されるデータ処理の結果);

* a_psValue-MSXDataInfoRec構造体へのポインター(計算で使用されるすべての数値データ)。

すべての構造は、 MSXStruc.hファイルに記述されてます。



データの保存と計算



指標の計算に使用されるすべての数値データは、データ配列と呼ばれる構造に保存されます。 データ配列は、価格データ(始値、高値、安値など)、数値定数、およびインジケーター計算結果を保存するために使用されます。 MetaStockがMSX DLL関数の証券および引数に関するデータを提供する場合、このデータは配列として使用されます。 MSX DLLによって計算された関数がMetaStockでインジケーターの結果を返す場合、結果はデー​​タの配列として返されます。

データ配列はMSXDataInfoRec構造に実装され、3つの主要なコンポーネントがあります。

•データ要素-データ要素。

•最初の有効なインデックス-参照の開始点(Fvi)。

•最後の有効なインデックス-参照の終点(Lvi)。

データ項目は、データ配列に関連付けられた実際の数値です。 これらの値は、 float値として配列に保存されます。 最初と最後の有効なインデックスを使用して、どのデータ項目に有効な値が含まれているかを判断します。 最初と最後の有効なインデックス(両端を含む)の間のすべてのデータ要素には有効なデータが含まれます。 この範囲外のすべての要素には未定義の値があり、すべての計算で無視する必要があります。

Fvi <Lviの場合、データ配列は「 」と見なされます。 空のデータセットは珍しくなく、適切に処理する必要があります。 通常、空のデータセットはFvi = 0およびLvi = -1になりますが、Fvi <Lviが提供される組み合わせは空と見なされます。 データが利用できない場合、空のデータ配列が表示されます。 たとえば、「建玉」データセットは、建玉がないセキュリティ(証券)に使用されます。

または、100-期間の移動平均の結果が100未満の要素を含む証券価格データの配列に適用される場合、空のデータ配列を取得します。

最初と最後の有効なインデックスは、インジケーターの計算中に非常に重要です。 計算は常にそれらの間に含まれるデータ要素に限定する必要があります。 返されるデータ配列のFviおよびLviインデックスを正しく設定するために理解すべき2つの重要なポイント:

•計算は常に、使用するすべての入力データ配列の許容範囲の範囲に制限してください。

•計算の結果としてのFviとLviは、入力データのすべての配列の値に対する位置を保持する必要があります。



MSXDataRec構造には、7つのデータ配列が含まれています。

sOpensHighsLowsClosesVolsOIsInd

MSXDataInfoRec構造体に値を保存します。 これらのデータセットには、中央銀行の必要なすべての価格データが格納されます。

これらの配列の一部は、中央銀行にこの価格フィールドのデータがない場合(空利など)、空になる場合があります。

•さらに、 MSXDataRec構造体には、 MSXDateTime構造体からの配列へのポインターが含まれています。

この配列には、各データポイントの日付と時刻の情報が含まれます。 計算関数が機器のN番目のバーの日付と時刻にアクセスする必要がある場合、 psDate配列のN番目の要素を参照する必要があります。 この配列は、sHigh、sLowなどのデータ配列とは異なることに注意してください。

sIndデータ配列には、ユーザーが選択したインジケーターのデータが含まれます。 カスタムインジケーターの場合、このデータ配列には、インジケーターがアタッチされたチャートオブジェクトの値が含まれます。 sInd部分が選択されていない場合、データ配列は空になります。

•これらの配列内のデータの場所は、期間に対応する配列の各要素のN番目の要素と同期されることに注意してください。

sCloseデータ配列には、常に最大数のデータ要素が含まれます。 他のすべてのデータセットには、<= sClose.iLastValidの要素数が含まれます。

•sCloseデータセットのiFirstValidおよびiLastValid設定は非常に重要です。

通常、この配列の要素数により、他の価格配列に格納されるデータ要素の最大数が決まります。 これは、psDate配列に含まれる有効な要素の数を決定するために重要です。 たとえば、sClose.iFirstValid = 100フィールドおよびsClose.iLastValid = 200フィールドの場合、psDate配列にpsDate [100]とpsDate [200]の間の有効なデータが含まれていることを確認できます。

•計算が完了した後、a_psResult-> psResultArrayのiLastValid値は、sCloseデータ配列のiLastValid値より大きくなることはありません。

sCloseのiFirstValidおよびiLastValidを使用して、すべての配列データを格納するために使用できる値の数を決定する必要があります。 sClose.iLastValidデータポイントにのみ、すべての配列を格納するのに十分なメモリが割り当てられます。 MSX DLLからa_psResult-> psResultArrayで返されるデータは、同じストレージ制限に収まる必要があります。

•MSX DLLから返されるa_psResult-> psResultArrayデータセットの先頭は、sClose.iFirstValidより小さくならないようにしてください。 データセットの終わりa_psResult-> psResultArrayがsClose.iLastValidより大きくなることはありません。



覚えておくべきこと



•計算関数は、結果のレコード(a_psResult)を除き、入力引数を変更しないでください。 不正な変更が発生しないように、提供されるテンプレートでは、可能な場合、着信引数は ' const 'として定義されます。

•関数から戻る前に、必ずa_psResult-> psResultArray-> iFirstValidおよびa_psResult-> psResultArray-> iLastValidを設定してください。

•関数が内部エラーを示すMSX_ERRORを返す場合、エラーa_psResult-> pszExtendedErrorを説明するエラーを拡張文字列に必ずコピーしてください。

•a_psResult-> psResultArray-> iFirstValidをsClose.iFirstValidより小さく設定しないでください。

•a_psResult-> psResultArray-> iLastValidをsClose.iLastValidより大きく設定しないでください。 a_psResult-> psResultArray-> pfValueに値sClose.iLastValidを書き込むと、メモリがMetaStockにマップされ、プログラムがクラッシュします。

•使用する予定のMSXDataInfoRecまたはa_psBasic引数については、必ずiFirstValidおよびiLastValidを確認してください。 データがどのデータ配列でも利用できるとは思わないでください。 処理機能でデータが利用できない場合、設定

a_psResult-> psResultArray-> iFirstValid = 0および

a_psResult-> psResultArray-> iLastValid = -1

配列を返す有効なデータがないことを示します。 このメソッドは、Metastockプログラムの異常終了を回避します。



コードを変更する



上記の資料に従って、関数のコードをわずかに変更します。 FviとLviを追加し、関数の出力で破損した配列を受け取った場合の例外を追加します。



 DLL_EXPORT BOOL __stdcall Price(const MSXDataRec *a_psBasic, const MSXDataInfoRecArgsArray *a_psArrayArgs, const MSXNumericArgsArray *a_psNumericArgs, const MSXStringArgsArray *a_psStringArgs, const MSXCustomArgsArray *a_psCustomArgs, MSXResultRec *a_psResult) { BOOL l_bRtrn = MSX_SUCCESS; for (int i= a_psBasic ->sClose.iFirstValid; i<= a_psBasic ->sClose.iLastValid; i++) a_psResult->psResultArray->pfValue[ i ] = a_psBasic ->sClose.pfValue[ i ]; //     . a_psResult->psResultArray->iFirstValid = a_psBasic->sClose.iFirstValid; a_psResult->psResultArray->iLastValid = a_psBasic->sClose.iLastValid; //    if (a_psResult->psResultArray->iFirstValid < 0 || a_psResult->psResultArray->iLastValid < 0 || a_psResult->psResultArray->iLastValid < a_psResult->psResultArray->iFirstValid || a_psResult->psResultArray->iFirstValid < a_psBasic->sClose.iFirstValid || a_psResult->psResultArray->iLastValid > a_psBasic->sClose.iLastValid) l_bRtrn = MSX_ERROR; //    ,   . if (l_bRtrn != MSX_SUCCESS) { strncpy (a_psResult->szExtendedError, "Error: Corrupted Result Array.", sizeof(a_psResult->szExtendedError)-1); a_psResult->psResultArray->iFirstValid = 0; a_psResult->psResultArray->iLastValid = -1; } return l_bRtrn; }
      
      





ファイルへの出力



データを表示するには、stdio.hヘッダーファイルを含める必要があります。このファイルには、特別なデータ型が宣言されています-FILE構造体。

#include <stdio.h>

コメント
ファイルでの作業を整理するには、プログラムはファイルへのポインターを使用する必要があります。 ファイルポインター変数を作成するには、FILE * file(ストリーム宣言)型の演算子を使用します。 ファイルにアクセスできるようにするには、ファイルを開く必要があります。 fopen()関数は、使用するストリームを開き、このストリームにファイルを関連付け、このストリームへのFILEポインターを返します。形式は次のとおりです。

•file = fopen(「ファイルパス」、「ファイル操作モード」)。

wモードは、ファイルへの書き込みに使用されます。 fprintf()関数はファイルに書き込みます:

•fprintf(ファイル、[フォーマット文字列]、[変数のリスト、定数])。

fclose()関数は、以前にfopen()で開かれたストリームを閉じるために使用されます。

•fclose(ファイル)

fclose()を呼び出すと、ストリームに関連付けられたファイル制御ブロックが解放され、再利用可能になります。



次のデータを取得しましょう:中央銀行の名前、期間( 'D'aily'、W'eekly、 'M'onthly'、Q'uarterly、 'I'ntraday)、インデックス、インディケーター、ファイルの時間と日付。



 DLL_EXPORT BOOL __stdcall Price(const MSXDataRec *a_psBasic, const MSXDataInfoRecArgsArray *a_psArrayArgs, const MSXNumericArgsArray *a_psNumericArgs, const MSXStringArgsArray *a_psStringArgs, const MSXCustomArgsArray *a_psCustomArgs, MSXResultRec *a_psResult) { BOOL l_bRtrn = MSX_SUCCESS; FILE *file; file = fopen("D:\\example.txt", "w"); for (int i= a_psBasic ->sClose.iFirstValid; i<= a_psBasic ->sClose.iLastValid; i++) { a_psResult->psResultArray->pfValue[ i ] = a_psBasic ->sClose.pfValue[ i ]; if (file) fprintf(file, "%-10s %2c %5u %12.4f %5u %10u\n", a_psBasic ->pszSecurityName, a_psBasic ->iPeriod, i, double (a_psResult->psResultArray->pfValue[i]), a_psBasic ->psDate[i].lTime/1000, a_psBasic ->psDate[i].lDate); } fclose(file); //     . a_psResult->psResultArray->iFirstValid = a_psBasic->sClose.iFirstValid; a_psResult->psResultArray->iLastValid = a_psBasic->sClose.iLastValid; //    if (a_psResult->psResultArray->iFirstValid < 0 || a_psResult->psResultArray->iLastValid < 0 || a_psResult->psResultArray->iLastValid < a_psResult->psResultArray->iFirstValid || a_psResult->psResultArray->iFirstValid < a_psBasic->sClose.iFirstValid || a_psResult->psResultArray->iLastValid > a_psBasic->sClose.iLastValid) l_bRtrn = MSX_ERROR; //    ,   . if (l_bRtrn != MSX_SUCCESS) { strncpy (a_psResult->szExtendedError, "Error: Corrupted Result Array.", sizeof(a_psResult->szExtendedError)-1); a_psResult->psResultArray->iFirstValid = 0; a_psResult->psResultArray->iLastValid = -1; } return l_bRtrn; }
      
      





その結果、RTSインデックスの1分間の先物チャートで次のようになりました。

example.txt
 SP_RTS_1m I 1 112310.0000 1725 20140417 SP_RTS_1m I 2 112320.0000 1726 20140417 SP_RTS_1m I 3 112130.0000 1727 20140417 ... SP_RTS_1m I 497 117150.0000 1336 20140418 SP_RTS_1m I 498 117170.0000 1337 20140418 SP_RTS_1m I 499 117200.0000 1338 20140418 SP_RTS_1m I 500 117190.0000 1339 20140418
      
      







引数のない関数で、私たちがそれを理解したことを願っています。 次の記事では、さまざまな引数を持つ関数の作成について見ていきます。



All Articles