隨機微積分

正態隨機數和 NaN 的極端情況

  • January 21, 2017

在嘗試實現我在 C++ 中模擬 SDE 的 Euler 方法版本時,我遇到了一個問題。在某些情況下,我的方法生成的路徑最終給出的值是NaN(非數字)。這種情況很少發生,但如果我計算 100 條路徑,通常會出現大約 1 或 2 種情況。

我相信問題出在正常的隨機數上 $ Z_i $ 我用於迭代的

$$ S_{i+1}=S_i+f(S_i)\cdot \sqrt{dt}\cdot Z_i $$ (例如 SDE 是 $ dS_t=f(S_t)dW_t $ )。我嘗試使用std::normal_distribution生成器std::mt199737並實現我自己的 Box-Muller 方法(使用 生成統一數字std::uniform_real_distribution)。 使用這兩種方法,總是存在使整個模擬變為無窮大並產生 的奇數值NaN。問題是我需要對最終值進行一些計算 $ S_1 $ 由我的路徑產生。

我應該忽略NaN那些嗎?與路徑總數相比,它們的數量非常少。

人們在執行這種類型的模擬時會遇到這些問題嗎?

這是我的程式碼:

#include <iostream>
#include <vector>
#include <random>

typedef double ( *funct )( double );

double square( double x ) { return x * x; }
double fourx( double x ) { return 4 * x; }

double generateGaussian();
std::vector< double > createPath( unsigned, double, funct );


int main()
{
 double initial = 1.0;
 unsigned intervals = 3000;
 unsigned paths = 500;

 std::vector< double > path;
 int n = 0;
 for ( auto j = 0; j < paths; ++j )
 {
   path = createPath( intervals, initial, square );
   if ( isnan( path.back() ) )
     ++n;
 }

 std::cout << n << std::endl;
}

double generateGaussian()
{
 static std::mt19937 generator( std::random_device{}() );
 std::normal_distribution< double > dist( 0.0, 1.0 );

 return dist( generator );
}

std::vector< double > createPath( unsigned numberOfIntervals, double initialCondition, funct f )
{
 double sqdt = sqrt( 1.0 / numberOfIntervals );
 std::vector< double > path;
 path.push_back( initialCondition );
 for ( auto i = 0; i < numberOfIntervals; ++i )
 {
   double Z = generateGaussian();
   double Si = path.back();
   double S = Si + f( Si ) * sqdt * Z;

   path.push_back( S );
 }
 return path;
}

我只是用它編譯它

g++ -std=c++11 test.cpp

這是在 Mac OS X 10.10.5 的終端上:

g++ -v
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin14.5.0
Thread model: posix

有時我會得到一條以NaN. 我還用其他功能實現了這一點,並得到了類似的情況。我嘗試例如服用 $ f(x)=4x $ (所以 $ dS_t=4S_tdW_t $ ),有時我會得到異常巨大的數字(甚至忽略NaN路徑)。同樣在這種特殊情況下 $ f(x)=4x $ ,我從執行到執行得到完全不一致的結果,這讓我很惱火,但我還沒有想過為什麼。

最後,如果我用 0 初始化生成器,我會得到完全相同的程式碼 2 NaN

問題不在於您的程式碼,而在於 SDE 本身。過程

$$ \begin{equation} \mathrm{d}S_t = \sigma S^\beta \mathrm{d}W_t \end{equation} $$ 是一個非負局部鞅。為了 $ \beta \leq 1 $ 它是鞅並且對於 $ \beta > 1 $ 這是一個嚴格的局部鞅。這體現在您的模擬中,當使用該函式時,某些路徑的擴散項會爆炸square。它導致S = InforS = -Inf和 下一步以及您獲得的所有後續步驟S = NaN

使用您的功能fourx時,您不應該遇到這種情況。SDE 的更好離散化

$$ \begin{equation} \mathrm{d}S_t = \sigma S_t \mathrm{d}W_t \end{equation} $$ 是通過模擬日誌。即你近似

$$ \begin{equation} \mathrm{d} \ln S_t = -\frac{1}{2} \sigma^2 \mathrm{d}t + \sigma \mathrm{d}W_t \end{equation} $$ 經過

$$ \begin{equation} \ln S_i = \ln S_{i - 1} - \frac{1}{2} \sigma^2 \Delta t + \sigma \sqrt{\Delta t} Z. \end{equation} $$ 這樣,您就擺脫了擴散係數中的狀態依賴性,並且對於任何步長都不會產生離散化誤差。

另請參閱相關問題。

引用自:https://quant.stackexchange.com/questions/32013