#resource "Python/model.onnx" as uchar ExtModel[]// リソースとしてのモデル
#define TESTS 10000 // テストデータセットの数
//+------------------------------------------------------------------+
//| スクリプトプログラム開始関数 |
//+------------------------------------------------------------------+
int OnStart()
{
//--- モデルを作成する
long session_handle=OnnxCreateFromBuffer(ExtModel,ONNX_DEBUG_LOGS);
if(session_handle==INVALID_HANDLE)
{
Print("Cannot create model. Error ",GetLastError());
return(-1);
}
//--- 入力テンソルサイズがモデルに定義されていないため、明示的に指定する
//--- 最初のインデックスはバッチサイズ、2番目のインデックスはシリーズサイズ、3番目のインデックスはシリーズ数(OHLC)
const long input_shape[]={1,10,4};
if(!OnnxSetInputShape(session_handle,0,input_shape))
{
Print("OnnxSetInputShape error ",GetLastError());
return(-2);
}
//--- 出力テンソルサイズがモデルに定義されていないため、明示的に指定する
//--- 最初のインデックスはバッチサイズであり、入力テンソルのバッチサイズと一致する必要がある
//--- 2番目のインデックスは予測価格の数(ここでは終値のみを予測)
const long output_shape[]={1,1};
if(!OnnxSetOutputShape(session_handle,0,output_shape))
{
Print("OnnxSetOutputShape error ",GetLastError());
return(-3);
}
//--- テストを実行する
vector closes(TESTS); // 検証価格を保存するためのベクトル
vector predicts(TESTS); // 得られた予測を保存するためのベクトル
vector prev_closes(TESTS); // 前の価格を保存するベクトル
matrix rates; // OHLCシリーズを取得するための行列
matrix splitted[2]; // シリーズをテストと検証に分割するための2つの部分行列
ulong parts[]={10,1}; // 分割された部分行列のサイズ
//--- 前のバーから開始
for(int i=1; i<=TESTS; i++)
{
//--- 11バーを取得する
rates.CopyRates("EURUSD",PERIOD_H1,COPY_RATES_OHLC,i,11);
//--- 行列をテストと検証に分割する
rates.Vsplit(parts,splitted);
//--- 検証行列から終値を取得する
closes[i-1]=splitted[1][3][0];
//--- last Close in the tested series
prev_closes[i-1]=splitted[0][3][9];
//--- 10バーのテスト行列をテストに提出する
predicts[i-1]=PricePredictionTest(session_handle,splitted[0]);
//--- ランタイムエラー
if(predicts[i-1]<=0)
{
OnnxRelease(session_handle);
return(-4);
}
}
//--- 操作を完成する
OnnxRelease(session_handle);
//--- 価格変動が正しく予測されたかどうかを評価する
int right_directions=0;
vector delta_predicts=prev_closes-predicts;
vector delta_actuals=prev_closes-closes;
for(int i=0; i<TESTS; i++)
if((delta_predicts[i]>0 && delta_actuals[i]>0) || (delta_predicts[i]<0 && delta_actuals[i]<0))
right_directions++;
PrintFormat("right direction predictions = %.2f%%",(right_directions*100.0)/double(TESTS));
//---
return(0);
}
//+------------------------------------------------------------------+
//| データを準備してモデルを実行する |
//+------------------------------------------------------------------+
double PricePredictionTest(const long session_handle,matrix& rates)
{
static matrixf input_data(10,4); // 変換された入力の行列
static vectorf output_data(1); // 結果を受け取るベクトル
static matrix mm(10,4); // 水平ベクトルMeanの行列
static matrix ms(10,4); // 水平ベクトルStdの行列
//--- 一連のOHLC垂直ベクトルをモデルに入力する必要がある
matrix x_norm=rates.Transpose();
//--- 価格を正規化する
vector m=x_norm.Mean(0);
vector s=x_norm.Std(0);
for(int i=0; i<10; i++)
{
mm.Row(m,i);
ms.Row(s,i);
}
x_norm-=mm;
x_norm/=ms;
//--- モデルを実行する
input_data.Assign(x_norm);
if(!OnnxRun(session_handle,ONNX_DEBUG_LOGS,input_data,output_data))
{
Print("OnnxRun error ",GetLastError());
return(0);
}
//--- 出力値から価格を非正規化する
double y_pred=output_data[0]*s[3]+m[3];
return(y_pred);
}
|