人工ニューラルネットワークで株価予測 ~Delphiソースコード集
連続する7営業日の日経平均株価終値から、翌日、翌々日の日経平均株価終値を予想するプログラムを作成します。

人工ニューラルネットワーク(Artificial Neural Network)を使用する為のファイルの準備
本ホームページのhttps://mam-mam.net/delphi/ann.htmlから
「UMamAnn.pas」ソースコード用意しプロジェクトフォルダ内に保存します。
また、
https://indexes.nikkei.co.jp/nkave/index?type=download
から「日経平均株価」⇒「日次データ」をダウンロード(nikkei_stock_average_daily_jp.csv)してプロジェクトフォルダに入ます。
Delphiを起動して新規作成を行い、必要なコンポーネントをドラッグ&ドロップする
Delphi起動⇒ファイル⇒新規作成⇒WindowsVCLアプリケーション を選択します。
TButton×3個、TMemo×1個、TChart×1個をフォームへドラッグ&ドロップします。

「ファイル」⇒「全て保存」でフォルダを作成して、プロジェクトとユニットを保存します。
プロジェクトフォルダ内に「UMamAnn.pas」ファイルと「nikkei_stock_average_daily_jp.csv」ファイルを配置します。
ソースコードを記述する
Form1のOnCreateイベント、Form1のOnDestroyイベント、Button1のOnClickイベント、Button2のOnClickイベント、Button3のOnClickイベントに以下ソースコードを記述します。
unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, VclTee.TeeGDIPlus, VCLTee.TeEngine, VCLTee.TeeProcs, VCLTee.Chart, VCLTee.Series ,UMamAnn; type //CSVファイルから日経平均株価終値を読んで入れる構造体 TData=Record dt:TDateTime;//日付 EndV:Single; //日経平均株価終値 End; TForm1 = class(TForm) Button1: TButton; Button2: TButton; Button3: TButton; Memo1: TMemo; Chart1: TChart; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure Button1Click(Sender: TObject); //0~35000を0.0[15000]~1.0[35000]に正規化 function normalize(s:Single):Single; //0.0[15000]~1.0[35000]を0~35000に戻す function renormalize(s:Single):Single; procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); private { Private 宣言 } Ann:TMamAnn; Layers:TArray<Integer>; il,ol:integer;//入力層と出力層のニューロン数 data:TArray<TData>;//CSVファイルを読んで入れる配列 public { Public 宣言 } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); var dt:string; i,j:Integer; ip,op:TArray<Single>; epoch:Integer; begin //学習 SetLength(ip,il); SetLength(op,ol); //繰り返し400回学習する for epoch := 1 to 400 do begin i:=0; dt:=''; while dt<='2022/10/31' do //2022年10月31日までを学習させる begin for j := 0 to il-1 do begin ip[j]:=(data[i+j].EndV); end; for j := 0 to ol-1 do begin op[j]:=data[i+il+j].EndV; end; dt:=FormatDateTime('YYYY/MM/DD',data[i+il+ol-1].dt);//日付を文字列で取得 //学習する Ann.Train(ip,op); inc(i); end; end; Memo1.Lines.Add(Format('学習完了 MSE=%6.4f',[Ann.GetMSE])); end; procedure TForm1.Button2Click(Sender: TObject); var dt1,dt2:TDateTime; l,i,j:Integer; ip,op:TArray<Single>; pre1,pre2:Single;//予測値(翌営業日、翌々営業日) fact1:Single;//実際の値 begin //全期間の予測 Chart1.Series[0].Clear; Chart1.Series[1].Clear; Chart1.Series[2].Clear; SetLength(ip,il);//指定日を含む過去7営業日の日経平均株価の終値を入れる SetLength(op,ol);//指定日から翌日、翌々日の日経平均株価の終値を入れる l:=0;//2022/11/01を探す for i := Low(data) to High(data) do begin if FormatDateTime('YYYYMMDD',data[i].dt)='20221101' then begin l:=i; break; end; end; //2022/11/01以降をAIに予測させる for i := l-il to High(data)-il-ol do begin for j := 0 to il-1 do begin ip[j]:=(data[i+j].EndV);//-9営業日の終値 end; Ann.Run(ip,op);//翌営業日と翌々営業日の予測 pre1:=renormalize(op[0]); pre2:=renormalize(op[1]); //翌営業日 dt1:=data[i+il+0].dt; //日付 fact1:=renormalize(data[i+il+0].EndV); //実際の値 dt2:=data[i+il+1].dt; //日付 Chart1.Series[0].AddXY( dt1,fact1 ); Chart1.Series[1].AddXY( dt1,pre1 ); Chart1.Series[2].AddXY( dt2,pre2 ); end; Memo1.Lines.Add('2022/11/01以降の予測'); end; procedure TForm1.Button3Click(Sender: TObject); var dt1,dt2:TDateTime; i,j:Integer; ip,op:TArray<Single>; pre1,pre2:Single;//予測値(翌営業日、翌々営業日) fact1:Single;//実際の値 begin //全期間の予測 Chart1.Series[0].Clear; Chart1.Series[1].Clear; Chart1.Series[2].Clear; SetLength(ip,il);//指定日を含む過去7営業日の日経平均株価の終値を入れる SetLength(op,ol);//指定日から翌日、翌々日の日経平均株価の終値を入れる //全期間AIに予測させる for i := Low(data) to High(data)-il-ol do begin for j := 0 to il-1 do begin ip[j]:=(data[i+j].EndV);//-9営業日の終値 end; Ann.Run(ip,op);//翌営業日と翌々営業日の予測 pre1:=renormalize(op[0]); pre2:=renormalize(op[1]); //翌営業日 dt1:=data[i+il+0].dt; //日付 fact1:=renormalize(data[i+il+0].EndV); //実際の値 dt2:=data[i+il+1].dt; //日付 Chart1.Series[0].AddXY( dt1,fact1 ); Chart1.Series[1].AddXY( dt1,pre1 ); Chart1.Series[2].AddXY( dt2,pre2 ); end; Memo1.Lines.Add('全期間の予測'); end; procedure TForm1.FormCreate(Sender: TObject); var LineSeries1,LineSeries2,LineSeries3:TLineSeries;//折れ線グラフ系列1,2,3 stl1,stl2:TStringList; i:Integer; begin il:=7; ol:=2; SetLength(Layers,4);//4層 Layers[0]:=il; //入力層7ニューロン(連続する7営業日の日経平均株価終値) Layers[1]:=7; //中間層7ニューロン Layers[2]:=3; //中間層3ニューロン Layers[3]:=ol; //出力層2ニューロン(翌日、翌々日の日経平均株価終値の予想値) Ann:=TMamAnn.Create(Layers,0.005);//学習率0.005 LineSeries1:=TLineSeries.Create(Chart1); LineSeries2:=TLineSeries.Create(Chart1); LineSeries3:=TLineSeries.Create(Chart1); Chart1.Title.Caption:='日経平均株価終値の予測'; Chart1.AddSeries(LineSeries1); Chart1.AddSeries(LineSeries2); Chart1.AddSeries(LineSeries3); Chart1.Series[0].XValues.DateTime:=True; Chart1.Series[1].XValues.DateTime:=True; Chart1.Series[2].XValues.DateTime:=True; Chart1.Series[0].Pen.Width:=4; Chart1.Series[1].Pen.Width:=4; Chart1.Series[2].Pen.Width:=1; Chart1.Series[0].Title:='日経平均株価終値'; Chart1.Series[1].Title:='翌営業日予測値'; Chart1.Series[2].Title:='翌々営業日予測値'; Chart1.BottomAxis.DateTimeFormat:='yyyy年mm月dd日'; Chart1.BottomAxis.LabelsAngle:=90; //Chart1.BottomAxis.LabelsFont.Size:=10; Chart1.View3D:=False; Chart1.LeftAxis.AutomaticMaximum:=true; Chart1.LeftAxis.AutomaticMinimum:=true; //https://indexes.nikkei.co.jp/nkave/index?type=download //から「日経平均株価」⇒「日次データ」を //ダウンロード(nikkei_stock_average_daily_jp.csv)して //プロジェクトフォルダに入れておく stl1:=TStringList.Create; stl2:=TStringList.Create; try stl2.Delimiter:=','; stl2.StrictDelimiter:=True; stl2.QuoteChar:='"'; stl1.LoadFromFile('..\..\nikkei_stock_average_daily_jp.csv'); stl1.Sort; SetLength(data , stl1.Count-2); for i := 0 to stl1.Count-3 do begin //日付,終値,始値,高値,安値 の順番に入っている stl2.DelimitedText:=stl1[i]; data[i].dt:=StrToDateTime( StringReplace(stl2[0],'-','/',[rfReplaceAll]) ); data[i].EndV:=normalize( StrToFloat(StringReplace(stl2[1],',','',[rfReplaceAll])) ); end; finally stl1.Free; stl2.Free; end; end; procedure TForm1.FormDestroy(Sender: TObject); begin Ann.Free; end; function TForm1.normalize(s: Single): Single; begin //0~35000を0.0[15000]~1.0[35000]に正規化 result:=(s-15000)/20000; end; function TForm1.renormalize(s: Single): Single; begin //0.0(15000)~1.0(35000)を0~35000に戻す result:=s*20000+15000; end; end.
実行する
実行ボタンを押して実行します。(デバッグ実行でもOK)
Button1をクリックすると、日経平均株価終値の2019/01~2022/10を「回帰問題」として学習します。学習が完了するまでしばらく(長ければ数分)時間がかかります。

次にButton2をクリックすると、2022/11以降の翌日、翌々日の日経平均株価終値を予想してグラフ表示します。

次にButton3をクリックすると、全期間の翌日、翌々日の日経平均株価終値を予想してグラフ表示します。
