- •Случайные события
- •Стохастический мир
- •Случайные величины
- •Совместная и условная вероятности
- •Зависимость и независимость
- •Характеристическая функция
- •Модель аддитивного блуждания
- •Случайные процессы
- •Стохастические уравнения
- •Уравнение Ито
- •Остановка перед восхождением
- •Лемма Ито
- •Точные решения
- •Простые стохастические модели
- •Представление решений
- •Автокорреляция и спектр
- •Порождающий процесс Винера
- •Средние значения
- •Динамическое уравнение для средних
- •Процесс Феллера
- •Логистическое уравнение
- •Вероятности
- •Марковские плотности вероятности
- •Граничные условия
- •Стохастические интегралы
- •Площадь под траекторией Винера
- •Интегралы Ито
- •Интегрирование стохастических уравнений
- •Единственность решений
- •Метод последовательных приближений
- •Системы уравнений
- •Скоррелированные блуждания
- •Системы стохастических уравнений
- •Стохастический осциллятор
- •Линейные многомерные модели
- •Многомерие помогает одномерию
- •Как решать стохастические задачи?
- •Стохастическая природа
- •Теория броуновского движения
- •Стохастический осциллятор
- •Дрожание земной оси
- •Электронный шум
- •Хищники и их жертвы
- •Стохастическое общество
- •Финансовые рынки
- •Эмпирические закономерности
- •Диверсификация
- •Портфель на всю жизнь
- •Опционы
- •Кривая доходности
- •Компьютерное моделирование
- •Статистики
- •Случайные числа
- •Моделирование стохастических процессов
- •Ошибки вычислений и ускорение сходимости
- •Вычисление средних
- •R: Стохастический справочник
- •Основные соотношения теории
- •Системы уравнений с одинаковым шумом
- •M: Математические приложения
- •H: Помощь
- •C: Примечания
- •Рекомендуемая литература
250 |
Глава 9. |
9.4Моделирование стохастических процессов
Рассмотрим алгоритм моделирования одномерного стохастического процесса:
dx = a(x; t)dt + b(x; t) W:
Если задано начальное условие x0 = x(0), то последующие значения процесса xk = x(tk) получаются при помощи итерационной схемы (стр.
49): p
xk+1 = xk + a(xk; tk) t + b(xk; tk) t "k:
Чем меньше временной шаг t, тем ближе будут свойства получаемого выборочного процесса к точному результату:
# include " stat . cpp " |
// ôàéë ñ RndG ( ) |
inline Float a( Float x , Float t ){ return 0; } // ñíîñ inline Float b( Float x , Float t ){ return x; } // волат .
void main ()
{
FILE * out = fopen (" ito . out " , "w" );
SRnd ( time (0)); |
// " встряхиваем " генератор |
||||
Float |
step |
= |
0.1; |
// шаг по времени для табуляции x |
|
const |
int |
num |
= 100; // |
число точек табуляции |
|
int lag = |
1000; |
// |
количество дроблений шага s t e p |
||
Float dt = step /lag , |
sqrt_dt = sqrt ( dt ); |
||||
Float |
x =1; |
|
|
// начальное значение x |
|
Float |
t =0; |
|
|
// в момент времени t |
|
fprintf (out , "%g\t%g\n" , t , x ); |
|||||
for ( int k =1; |
k <= num ; k ++){ |
||||
for ( int |
j =0; j < lag ; |
j++ , t += dt ) |
x+= a(x ,t )* dt + b(x ,t )* RndG ()* sqrt_dt ;
fprintf (out , "%g\t%g\n" , t , x ); fflush ( out );
} |
|
fclose ( out ); |
// закрываем файл |
} |
|
Разбер¼м этот код. Директивой include мы вставляем код из файлаstat.cpp , в котором содержится функция RndG, описанная в предыдущем разделе. Так как это наш файл и он находится в той же директории, где происходит компиляция основной программы, мы заключаем его имя в двойные кавычки.
Компьютерное моделирование |
251 |
Далее идут описания функций сноса и волатильности. В примере выше выбран процесс логарифмического блуждания с нулевым сносом и единичной волатильностью (стр. 58).
Âглавной функции main открывается файл с именем ito.out . В него будут помещаться результаты работы программы. Для этого объявляется переменная (указатель) out типа FILE, значение которой зада¼тся функцией fopen. Последний е¼ аргумент w определяет способ открытия файла. В данном случае это будет вновь создаваемый файл, открывающийся для записи.
Функция SRnd встряхивает генератор случайных чисел. В результате при каждом запуске программы будет получаться новая реализация случайного процесса.
Âпрограмме вычисляется num = 100 значений случайного процес-
са x(t), с равным шагом по времени: t = 0; step; 2 step; :::; num step. Каждый интервал между вычисляемыми значениями x разбивается на большое число lag точек, время между которыми равно dt = step=lag.
x |
|
x |
x0 |
x0 |
t |
t |
|
|
step |
|
step |
Для вычислений используется два вложенных цикла. Внешний по k приводит к выводу x(step), x(2step),... тогда как внутренний по j, при помощи итерационной формулы, вычисляет промежуточные значения случай-
ного процесса. Для ускоренияpвычислений мы используем переменную sqrt_dt, в которой хранится dt. Начальное значение процесса x0 = 1
в момент времени t0 = 0 зада¼тся перед выполнением циклов.
Вывод в файл осуществляется функцией fprintf, которая аналогич- на printf, но первым аргументом указывается файловая переменная, в которую направляется вывод. Функция fflush(out) приводит к немедленному помещению данных в файл, поэтому, если прервать выполнение программы, часть посчитанных к этому моменту результатов будет находиться в файле. Последняя строка закрывает файл. Этот текстовый файл можно открыть, например, в Excel и построить график соответствущего случайного процесса.
Символ \t в функции fprintf обозначает табулирование и понимается Excel в качестве разделителя колонок. Можно его заменить на запятую , , и, придав файлу расширение .csv , получить формат, воспринимаемый большинством программ обработки данных.
252 Глава 9.
Аналогичным образом моделируется система стохастических уравнений. Рассмотрим в качестве примера двухмерный осциллятор с зату-
ханием (стр. 160), имеющий скоррелированный шум Wx Wy = dt:
dx = ( x ! y) dt + Wx dy = (+! x y) dt + Wy:
Программа на C++, выдающая реализацию траектории соответствущего случайного процесса x(t); y(t), имеет вид:
# include " stat . cpp " |
// ôàéë ñ RndG ( ) |
void main ()
{
FILE * out = fopen (" ito . out " , "w" );
SRnd ( time (0)); |
// " встряхиваем " генератор |
|||
Float |
step = 0.1; |
// шаг по времени для табуляции x , y |
||
const |
int |
num = 1000; // |
число точек табуляцмм |
|
int lag = |
1000; |
// |
количество дроблений шага s t e p |
Float w =0.5 , lm =0.01 , si =1 , rho =0.1;
Float x=1 , y=0 , t=0 , x1 , y1 , r1 , r2 ;
Float dt = step /lag , sqrt_dt = sqrt ( dt ), |
rho1 = sqrt (1 - rho * rho ); |
||||||
fprintf (out , "%g\t%g\t%g\n" , t , x , y ); |
|
||||||
for ( int k =1; |
k <= num ; k ++){ |
|
|
|
|||
for ( int j =0; |
|
j < lag ; j++ , t += dt ){ |
|
|
|||
r1 = RndG (); r2 = rho * r1 + rho1 * RndG (); |
|
||||||
x1 |
= |
x |
+ |
(- lm *x -w*y )* dt |
+ |
si * r1 |
* sqrt_dt ; |
y1 |
= |
y |
+ |
(- lm *y+w*x )* dt |
+ |
si * r2 |
* sqrt_dt ; |
x= x1 ; y= y1 ; |
|
|
|
||||
} |
|
|
|
|
|
|
|
fprintf (out , |
|
"%g\t%g\t%g\n" , |
t , |
x , y ); |
|||
} |
|
|
|
|
|
|
|
fclose ( out ); |
|
|
// |
закрываем файл |
}
Принципиальное отличие от одномерного случая состоит в использовании промежуточных переменных x1 и y1. Мы должны сначала вычислить приращение каждой из переменных, и лишь затем их увеличить. Если бы это не было проделано, то во втором уравнении для y стояло
бы x не из предыдущей итерации, а уже измен¼нное. В качестве упраж-
нения стоит сравнить работу этого алгоритма и алгоритма, в котором стояло бы просто x+ = ::: и y+ = :::. Обратим также внимание на ге-
нерацию скоррелированных случайных чисел r1 и r2 с коэффициентом корреляции =rho.
Компьютерное моделирование |
253 |
Пока системы уравнений имеют небольшую размерность, для каж-
дой степени свободы вводится отдельная переменная. Однако, рано или поздно необходимо переходить к массивам, особенно, если уравнение имеет компактную векторную форму.
Рассмотрим, например, систему следующего вида:
dxi = xi r dt + Wi;
p
ãäå r = x21 + ::: + x2n расстояние до начала координат в n-мерном декартовом пространстве. Так как снос вектора x = fx1; :::; xng всегда направлен к началу координат, блуждание будет вс¼ время оставаться в его окрестности. Со временем установится стационарное распределение вероятностей.
Для моделирования подобных уравнений необходимо определить массивы значений на предыдущей и текущей итерациях, а также задать начальные значения:
const int n = 10; Float x[n], x1 [n ];
for ( int i =0; i <n; i ++) x[i ]=0;
Для объявления размера статических массивов необходимо использовать константы (const). В качестве начального значения выбрано начало координат.
Основной цикл итерационных расч¼тов имеет следующий вид:
for ( int k =1; k <= num ; k ++){ for ( int j =0; j < lag ; j ++){
Float r =0; |
|
|
for ( int |
i =0; i <n; |
i ++) r += x[i ]* x[i ]; |
r= sqrt (r ); |
|
|
for ( int i =0; i <n; i ++) |
||
x1 [i] |
= x[i] - |
x[i ]* r* dt + RndG ()* sqrt_dt ; |
for ( int |
i =0; i <n; i ++) |
|
x[i] |
= x1 [i ]; |
|
}
}
При помощи значений x[i], полученных на предыдущей итерации, вычисляется радиус-вектор r. Затем в цикле происходит определение новых значений координат, которые присваиваются в массив x1. Только после того, как все новые значения вычислены, они снова помещаются в массив решений x.