[[20190626110203]] 『シミュレーションのしかた』(toto) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『シミュレーションのしかた』(toto)

他サイトでの回答が期待できないのと、これから先エクセルを使用することになるためここに参りました。
※他サイトへの投稿は「解決済み」としましたが、ご不快ならお許しください
※投稿内容は若干変えています
質問)
ある投資額に対する日毎の「回収率」データが数千件あります。
(概ねその値は「0〜10」の範囲内にあります)
このデータを基に、投資パターンを決めるシミュレーションを検討しています。

・シミュレーションは200個のデータで行いたいと考えています
・過去の回収率の統計量(平均、分散等)はできる限り再現したいです
・日付は回収率とは無関係とします
・度数グラフから、正規分布や指数分布といった理論分布を当てはめるのは
 適当ではないと考えています

以上の制約下で次の方法のどちらがより「数学的」に妥当と考えられるでしょうか?
方法1
 過去データをランダムに並び替え、そこから200個のデータを取出す
方法2
 過去データを例えば「0.1」刻みの度数表に表し、そのカウント数を換算した度数表を作成(*)、
その度数表からランダムに200個のデータを作成する
 *過去データが1000個で「1.4-1.5」の範囲に150個ある場合、換算度数表では
  30個となる(=150/1000*200)
 *度数の「まるめ」が避けられず、統計量が変わってしまうのは想定内です
 
どちらも過去データを忠実に再現しているわけでもなく、シミュレーションとしてどちらが
“よりふさわしいか”という問いかけになります。
あるいは、別案をご助言いただければ幸いです。

よろしくお願いします。

< 使用 Excel:Excel2007、使用 OS:Windows10 >


  データを200個に絞るだけですよね?

  方法1しかないと思えるのですが。

  方法2は、刻み幅が0.1なら、階級数は100程度ですよね?
  そこからどう200個抽出するのか、ご説明からはよく分からないです。

 一般論として、どんな具体的データがあって、どんな分析をしたいのか分からなければ
 適切な抽出法はこれだ、などとは言えないと思います。

(半平太) 2019/06/26(水) 12:45


半平太様 ありがとうございます。
データに関しては、ごく単純に日付と数値があるだけです。
例)(日付は数字化しています)
 A列		B列
 190626		1.33
 190625		0
 190618		5.41
 190617		0.75
 …		…

抽出数や刻み幅は(仮)で書きましたが、階級に分けると同じ階級に複数個存在し得ますし、当然「0」個の場合もあり得ます。

投資パターンの意味は、例えば直前の投資額に常に一定の比率を掛けていくとか、回収率が「1」以下(100%以下)の次回は○万円に固定するとか、実データと類似の統計的な特徴をもった仮想データでいろいろシミュレートしたい、ということです。
詳しくは知りませんがマーチンゲール法とかと発想は同じです。

質問は、方法1,2どちらが「実データと類似の統計的な特徴をもった」データ抽出方法といえるか、
と言換えてもいいかも知れません。

このサイトの運営主旨とは外れているかなと思っていますが、数学的センスがあり博識な方も多くおられるようなので、頼りにしました。
(toto) 2019/06/26(水) 13:53


 ようやく方法2が解りました。

 方法1だと、チャンとランダムになってくれるか不安がありますからねぇ。
 ※まぁ、200個もあればそんなに偏ることもないでしょうが・・

 それより、データの全貌が分かっているので、
 偏りの心配をしないでいい抽出方法を使う、と言うことですか。

 ただ、方法2だと、階級数の数しかバリエーションがないですから、
 200個と言っても、200種類じゃないことになります。
 ※シミュレーションの計算負担は減りますが、
  それがメリットなのかこちらでは分からないですけど。
   200個選ぶという意味が何なのかに照らし合わせる必要があります。

 そうなると、データを昇順に並べて、
 一定の間隔で200個摘み取って行くらいでよさそうな気がします。

(半平太) 2019/06/26(水) 15:24


方法2についてですが、換算した度数表が以下となった場合に
 階級		度数
 0		3
 0.1		1
 0.2		2

下記のようにデータ化⇒ランダム化するイメージです。

 データ化	
 0	
 0	
 0	
 0.1	
 0.2	
 0.2	
 ランダム化	
 0	
 0.2	
 0	
 0.1	
 0.2	
 0	

先にも書きましたように、実データを度数表化→換算度数表の作成過程で「まるめ」が避けられません。
が、統計量はそれなりに近似できるのではないかと思うのですが、やはり実データからの抽出の方が
理にかなっているのでしょうか...
(toto) 2019/06/26(水) 17:11


 まだ、数学的センスがあり博識な人の目に留まってないみたいですね。

 >やはり実データからの抽出の方が理にかなっているのでしょうか...

 そんなことはないです。
 シミュレーションですから、理想的な架空データが最善と言えるんじゃないですか。

 >データ化⇒ランダム化するイメージです。 

 ここがよく分からないです。
 なぜランダム化する必要があるんですか?

 順番が大事な要素なら、並べ替えの類は一切やってはいけないと思うんですが。

 とにかく、シミュレーションの詳細が何か分からなければ、
 何が適切なサンプリングなのか、他人には判断つかない・・(のではないかと思う。)

(半平太) 2019/06/27(木) 10:29


 「データを昇順に並べて、一定の間隔で200個摘み取って行く」

半平太様のこの方法がいいのでは、と思い始めています。
(より過去データの統計量を引継げそうに思えます)

 「ランダムにする必要性」

過去の統計量はそのままにいろいろな出現パターンで投資案を検証したいからです。 
(出現パターンの発生は乱数で行う予定です)
例えば、最初からいきなり回収率「0」が10回も連続して発生すれば、私の資金力では即パンクしてしまい意味ないですから。
(もちろんその発生リスクはゼロではないわけですが)

未だ明確な方針が決まっているわけでもないですが、先ずは半平太様の方法でシミュレーションできるように手段を模索中です…
(他の作業との兼ね合いで、覚えたてのマクロを予定しています)

(toto) 2019/06/27(木) 13:44


どんなデータをシミュレートするのか判らないので、何がベストかなんて当事者にしか判らないと思いますよ。 いろいろ試行錯誤して、好きに決めれば良いです。 身近に、同じ仕事をしていてデータ内容を理解している人は居ないのでしょうか? 部外者の意見より参考になると思うのですが。

素人案だけ書きますと、過去の実データが複数あるなら平均を求めて、平均値でデータを作るとか、完全ランダムではなく、過去値を少し上下させるだけのランダムにするとか。

あとはExcelらしさを出すなら、過去データで折れ線グラフを描いてから、系列を右クリックして「近似曲線の追加」をしてみるとか。 うねうねと上下するようなデータでも、多項式近似にして次数を増やすと、それっぽい曲線を描いてくれますよ。 良さそうならば、近似曲線のオプションで数式表示し、この式を元に、計算式で1点毎の値を求めて表にすれば良いです。
(???) 2019/06/27(木) 14:03


投資案を検討するためのシミュレートのようですが、検討というよりゲーム的なものを考えているならば、徐々に上がる/下がるパターンとか、大きく変動するパターンとか、たいして動かずうろうろするパターンとか、似た傾向のものを集めて平均を求め、それぞれ1線描いてみる。 そして近似式まで出す。 これを10パターンとか用意して、どのパターンを使うのかをランダムで決定。 実際の値も計算した結果をランダムで少し上下させる。 こんな感じで、毎回それっぽい変化をするように見えますが、いかがでしょうか。(つまり、上で書いた事を全部やる)

慣れてくると、変動具合からパターンを読まれる可能性はありますけど。
(???) 2019/06/27(木) 14:15


こんばんは。
系列相関の要素を反映するかどうかで大きく変わってくるでしょうね。
 
単なる多数の投資リターンのばらつきを見たいということなら、
ノンパラメトリックな(つまりモデルを想定しない)ブートストラップ法によればよいと思います。
(つまり数千個のなかから復元を許して200回取り出せばよいわけです。
それによってどの程度のばらつきがあるかを見ることができます)
 
既に指摘頂いているように、シミュレーションの目的に依存するとしか言えないと思います。
(γ) 2019/06/27(木) 22:47

いろいろとご助言ありがとうございます。

統計学の知識がないとキビしそうなので、ご助言をもとにいろいろ試してみたいと思います。
ブートストラップ法は初めて目にしましたが、何となく私がやろうとしているのに近いのかな、
との印象を受けました。
(浅はかなことは承知での、あくまでも現時点での印象です)

で、半平太様の方法を実現すべくコードを作成中なんですが、早くも躓きまして
下記の「data(k, 2) = tg(r, 1)」のエラー(応答なしになります)を回避したく、
ご教授願えないでしょうか?

 Sub test()
 Rem 予めD列にデータをコピーしておき、100個分のデータを選択してから実行します
 Rem D列を昇順並び替えした後に50個を等間隔で抽出します
 Rem あとでランダム化するために、乱数で整数値を50個に割振っています
 Rem 結果をF,G列に出力します
    Dim RNG As Range
    Dim tg(), data()
    Dim r As Long, i As Long, k As Long
    Dim cnt As Long                     'データ数
    Dim num As Long			'割振り数
    Dim flg() As Boolean		'乱数発生用
    Const ct As Long = 50               '抽出数
    Dim stp As Long                     '間隔
 '// 前処理(未);データコピー、出力先クリアなど
 '........
    Set RNG = Selection
 '// 昇順
    RNG.Sort Key1:=Range("D1"), _
                Order1:=xlAscending, Header:=xlYes
 '// 選択範囲の変更
    Dim cntRow As Long
    Dim cntCol As Long
    cntRow = RNG.Rows.Count - 1
    cntCol = RNG.Columns.Count
    Set RNG = RNG.Offset(1, 0)              '1行下にずらす
    Set RNG = RNG.Resize(cntRow, cntCol)    '1行削る
 '// 抽出
    tg = RNG.Value      '格納
    cnt = UBound(tg)    'データ数
    ReDim data(1 To ct, 1 To 2)
    ReDim flg(1 To ct)
    Randomize
    k = 1
    stp = WorksheetFunction.RoundUp(cnt / ct, 0)
    For r = 1 To cnt Step stp
        For i = 1 To ct
            Do      '重複しない乱数(整数)を生成
                num = Int(Rnd * ct) + 1
                If flg(num) = False Then
                  flg(num) = True
                  Exit Do
                End If
            Loop

            data(k, 1) = num
            data(k, 2) = tg(r, 1)       '--->Error

            k = k + 1
        Next i
    Next r
 '// 出力
    Range("F2:G" & ct + 1).Value = data

 '// 昇順並び替え(未)
 '........
 End Sub
(toto) 2019/06/28(金) 10:38

  rのループ(またはiのループ)は必要ないです。

  どっちか一方があれば、相手方の位置を計算できるので。

 Sub test()
   Rem 予めD列にデータをコピーしておき、100個分のデータを選択してから実行します
   Rem D列を昇順並び替えした後に50個を等間隔で抽出します
   Rem あとでランダム化するために、乱数で整数値を50個に割振っています
   Rem 結果をF,G列に出力します
      Dim RNG As Range
      Dim tg(), data()
      Dim r As Long, i As Long, k As Long
      Dim cnt As Long                     'データ数
      Dim num As Long         '割振り数
      Dim flg() As Boolean        '乱数発生用
      Const ct As Long = 50               '抽出数
      Dim stp As Long                     '間隔
   '// 前処理(未);データコピー、出力先クリアなど
   '........
      Set RNG = Selection
   '// 昇順
      RNG.Sort Key1:=Range("D1"), _
                  Order1:=xlAscending, Header:=xlYes
   '// 選択範囲の変更
      Dim cntRow As Long
      Dim cntCol As Long
      cntRow = RNG.Rows.Count - 1
      cntCol = RNG.Columns.Count
      Set RNG = RNG.Offset(1, 0)              '1行下にずらす
      Set RNG = RNG.Resize(cntRow, cntCol)    '1行削る
   '// 抽出
      tg = RNG.Value      '格納
      cnt = UBound(tg)    'データ数
      ReDim data(1 To ct, 1 To 2)
      ReDim flg(1 To ct)
      Randomize
      k = 1
  '    stp = WorksheetFunction.RoundUp(cnt / ct, 0)   ←不要★1/3
  '    For r = 1 To cnt Step stp                      ←不要★2/3
          For i = 1 To ct
              Do      '重複しない乱数(整数)を生成
                  num = Int(Rnd * ct) + 1
                  If flg(num) = False Then
                    flg(num) = True
                    Exit Do
                  End If
                  DoEvents
              Loop

              data(k, 1) = num
              r = WorksheetFunction.RoundUp(cnt * k / ct, 0) '挿入★1/1(rの位置を特定する)
              data(k, 2) = tg(r, 1)       '--->Error

              k = k + 1
          Next i
  '    Next r                                          ←不要★3/3
   '// 出力
      Range("F2:G" & ct + 1).Value = data

   '// 昇順並び替え(未)
   '........
 End Sub

(半平太) 2019/06/28(金) 14:06


ありがとうございます。
テストデータを変えながら抽出前後のエクセル分析の基本統計量を比較したところ、
どれも差異2%未満で満足のいくものでした。

が、ご提示コードを見てもエラー原因がわかりません。
挿入コードを含めて「解説」願えないでしょうか?
(toto) 2019/06/28(金) 15:55


 >どれも差異2%未満で満足のいくものでした。 

 2%もあったですか・・・

 2,4,6,8,・・,100 だから、プラス方向に少しずれますかね。

 1,3,5,7,・・,99 も求めて、足して2で割った「架空値」にすれば、ほぼピタリのハズです。

 >、ご提示コードを見てもエラー原因がわかりません。 

 iはDATAの位置番号です。
 その番号に対応するtgtの番号を求めれば終わる話ですよね?

 iが1,2,3・・なら、tgtのkは2,4,6・・

 そういう対応関係を求める式が
  r = WorksheetFunction.RoundUp(cnt * k / ct, 0) '挿入★1/1(rの位置を特定する) 
 ※割り切れない場合も想定して、そんな数式になっています。(kのMaxがctと一致する必要がある)

 なので  data(k, 2) = tg(r, 1)   ← これでDATA配列は求まります。

 そのループの外側にrのループがあったら、折角求めたDATA配列をまた一からrで書き換えてしまうことになります。

 エラーになるかどうかとは直接関係ないです。rのループは有害無益なんです。

 あと、何故kとiを二つも使っているのか、こちらでは分からないです。 同じ値ですよね?

(半平太) 2019/06/28(金) 17:15


半平太様
 エラーになるかどうかとは直接関係ない・・・rのループは有害無益
 あと、何故kとiを二つも使っているのか、・・・同じ値

無意味なループで「応答なし」になってたんですかね...
初歩的なことでご丁寧な説明、ありがとうございました。

抽出データの差異が5%未満なら想定内のつもりでしたが、学問的?にはどうなんでしょう。
???様やγ様のご意見も踏まえつつ、抽出のしかたやその後のランダム化(並べ替え)について
もっと検討したいと思います。

他にもエクセルの初歩的と思われる事でつまずいており、なかなか前へ進めませんが、
これは別途アップさせていただきます。
これからもよろしくお願いします。

(toto) 2019/06/30(日) 12:17


素朴な疑問ですが、後学のために教えて下さい。
・数千あるリターンに関するデータと
・100個のデータ
・ 50個のデータ
それはどういう関係にあるんでしょうか。
100個のデータはどうやって抽出しているのですか?
100個から50個に絞り込む理由は?

(γ) 2019/06/30(日) 23:36


γ様
掲載コードはあくまでもテスト用に100個のデータから50個抽出するコードにしました。
質問の実データ(過去データ数千個)から200個抽出する処理とは違います。
抽出する個数(200個)も今は暫定の位置づけです。
(説明不足ですみませんでした)

未だ構想が固まっていないのでうまく説明できませんが、
将来の投資に対して今までのリターンをベースとした場合に、今考えている投資法が通用するかどうか、
をシミュレートしようとしています。
そのために基本統計量はそのままに、出現パターンをいろいろ変えてみたらどうなるかをみてみようと思っています。
(リターンやヒット率はある意味現状の自分の能力なので大きく変化はしないが、出現パターンは“波”のようなもので変わり得るもの→どのようなパターンでも破産しない投資法をつくりたい)

当然ながら「将来のリターンやヒット率が今までと同じとはいえない」という当たり前のリスクは想定内です。
実データとシミュレートに使うデータがどこまで近似できるか、基本統計量だけに注目していていいのか、等々疑問はあります。

目下のところ、手段で使うエクセルの作業に戸惑りなかなか前に進めないのが最大の“障害”で..
これからもよろしくお願いします。
(toto) 2019/07/01(月) 10:19


回答いただき、ありがとうございました。
今後検討いただくところが残っているということでしょうか。
頑張って下さい。取り急ぎ御礼まで。

(γ) 2019/07/01(月) 23:23


統計知識はもとより、エクセルを習熟しないことには...と痛感しています。

最初はこんな内容に回答いただけるか不安でしたが、いろいろ気付かせていただいて
本当によかったと本心から思っています。

皆様ありがとうございました!!
(toto) 2019/07/02(火) 09:13


コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.