SSブログ

回帰直線によるガイダンス表示 [資産シミュレーション]

株価や為替の予想をするのはとても難しいと思います。
パラメータがあまりに多く、突発的な事象により突然パラメータも変化します。
パラメータ自体も増えたり、減ったりを繰り返しますし、そもそも何がパラメータかわかりません。

それでも、それなりにグラフの傾向を予想しようという試みは過去からもう延々と繰り返されてきました。

直近データから傾向を調べる方法として回帰直線があります。
これは、グラフに一番近い直線を1つ求めるというものです。

今回これを資産管理電卓でプログラムしてみました。
edge 対応版 v1.1.15.0 edge 未対応版 v0.18.16.0 以降で動作します。

回帰直線は求める直線とグラフの点との距離の二乗の累積が最小になる直線の位置と傾きを求めることで求まります。
これを最小二乗法と言いますが、長年研究され簡単に求まることが知られています。

回帰直線は以下の式で表されます。

元々のグラフのタグが x,値が y とすると(tmp[x] = y) x と y にそれぞれ数値を振っていき、
{
 // tmp に回帰直線を求めたい配列
 cnt = 0,
 ford(tag,tmp,
  {
   xgr[cnt] = tag,
   ygr[cnt] = tmp[tag],
   cnt = cnt + 1
  }
 )
}

として回帰直線を求めたい配列 tmp から x,y が共通タグとなる配列2つを求め xgr,ygr とします。

回帰直線 y = (xgr,ygrの共分散/xgrの分散) * (x - xgrの平均) + ygrの平均

上記で回帰曲線の式が求まります。

以下にソースを記載します。

// 回帰直線のグラフを表示する
// @1:グラフを表示する配列
// [@2]:実行式。
//      無名関数を渡すと
//      @1:回帰直線式関数
//      @2:タグが日付なら秒に変換された配列
//      @3:タグ最小値,@4:タグ最大値
//      を引数として呼び出される。
//      省略するとデフォルトのグラフ描画が呼び出される。
{
 // 回帰直線の式を得る
 // 配列インデックスの日付は連続な秒に変換しておく
 // @1:配列
 // return:回帰直線関数(@1:x とする関数)
 fnc(rformula,
  {
   // インデックスを同じにして xlis,ylis を作る
   cnt = 1,
   ford(tag,@1,
    {
     xlis[cnt] = tag,
     ylis[cnt] = @1[tag],
     cnt = cnt + 1
    }
   ),
   // 回帰直線を求める
   // f = ymean + covxy/disx *(@1 - xmean)
   b = cov(xlis,ylis)/dis(xlis),

   // 回帰直線の関数を定義して返す
   def(ffnc,amean(ylis) & "+" & b & "*(@1 - " & amean(xlis) & ")"),
   #ffnc // ffnc の無名関数を返す
  }
 ),

 // X軸の種類を調べる
 xtime = 0, // X軸は日付でない
 ford(tag,@1,
  if(tag > datetime(1900, 1, 1),
   {xtime = 1,break}, // X軸は日付
   break // X軸は数値
  )
 ),

 // X 軸連続な時間のデータ列を求める
 if(xtime ,
  ford(tag,@1,tmp[timetosec(tag)] = @1[tag]), // X軸は日付なので秒に変換
  tmp = @1 // X軸は数値なのでそのままコピー
 ),

 // 回帰直線の式を得る
 rfmu = rformula(tmp),

 // インデックス最小、最大値を求める
 ford(tag,tmp,appenddim([tag],tmp2)),
 idxmin = fmin(tmp2),
 idxmax = fmax(tmp2),

 if(isdef(@2),
  // 指定関数を実行
  return(@2(#rfmu,tmp,idxmin,idxmax)) // #rfmu で無名関数を得ている
 ),

 // 回帰直線のグラフを作成する
 tmp3[idxmin] = rfmu(idxmin),
 tmp3[idxmax] = rfmu(idxmax),

 // 秒から日付にインデックスを戻す
 if(xtime,
  // X軸は日付なので秒を日付に戻す
  ford(tag,tmp3,
   tmp4[sectotime(tag)] = tmp3[tag]
  ),
  // X軸は数値なのでそのままコピー
  tmp4 = tmp3
 ),

 // グラフ表示
 grres = grph(tmp4),
 addgrph(grres,@1),
 waitres(grres)
}


上記を関数定義ボタンから rline という関数名で定義してください。
ここからも取ってこれます
上記からファイルをダウンロードして rline.dat を 設定->設定読み込み から読み込んでも定義できます。
設定読み込みは"設定読み込み(初期化)"は選ばないでください。設定したグローバル変数が全て初期化されてしまいます。
グローバル関数 rline が定義されます。

{
 for(cnt , 1 , 100 , 1, tmp[cnt] = cnt * cnt),
 rline(tmp)
}

上記でグラフが出ればOKです。

rline は無名関数を引数に取り、渡すと回帰直線の結果を使って色々な処理が可能です。
無名関数の引数は

@1:回帰直線式関数
@2:タグが日付なら秒に変換された配列
@3:タグ最小値
@4:タグ最大値

となります。
タグ最大値、最小値はタグが日付なら秒に変換されています。
回帰直線もタグが日付なら秒を元に計算する式になっています。
秒と日付の変換は sectotime ,timetosec を使います。

{
 leng = 0.5, // 0.5年先まで計算
 retdat[0] = 0, // グラフの計算先を定義

 // 回帰直線計算
 rline($dat_kawase,
  =>
  {
   // leng年先まで計算
   @4 = @4 + leng*365*24*60*60,

   // 回帰直線を秒を日付に戻しながら計算
   for(cnt , @3 , @4 , (@4 - @3)/100 , retdat[sectotime(cnt)] = @1(cnt))
  }
 ),

 del(retdat[0]), // 定義用ダミー削除

 // グラフ表示
 setcom(retdat,"為替回帰直線"),
 grres = grph($dat_kawase),
 addgrph(grres,retdat),
 waitres(grres)
}


retdat[0] は無名関数内で外部環境の変数にアクセスできるようにダミーで設定しています。
上記では為替の半年後の傾向を表示しています。

為替データ
上記から為替データのサンプルをダウンロードできます。
同じように 設定->設定読み込み から kawase.dat を読み込むと為替データ $dat_kawase がグローバル配列として定義されます。

傾向を調べるには回帰直線は単純で解りやすい指標だと思われます。

ただ、為替の実データを見てもわかりますが傾向は突然変化していますので予想は本当に難しいと思います。
超長期ではインフレなどの長期要因が支配的になり傾向がはっきりする場合もあるとは思われます。
しかし、資産を使う目的で資産運用する場合、人が投資できる期間は子供に引き継がない場合40から始めたとして大体20年から30年ぐらいではないでしょうか。
このくらいの期間だと短中期となり短中期要因のパラメータが優勢だと思われます。
為替の場合は国間の政治的要因、国力の差等が大きいと思われますので予測はとても難しいと感じています。

コメント(0) 
共通テーマ:パソコン・インターネット

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

※ブログオーナーが承認したコメントのみ表示されます。

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。