Моделирование фондовой биржи
Для дальнейшего знакомства с использованием делегатов рассмотрим пример моделирования фондовой биржи, реализованный в папке stockMarket. Модель состоит из двух модулей:
На рис. 5.2 показана общая архитектура модели.
Модель допускает выполнение следующих операций:
Модель содержит следующие параметры:
Рис. 5.2. Архитектура эмулятора фондовой биржи
Запуск моделирования
Скомпонуйте и запустите программу StockMarket. Начните с принятой по умолчанию конфигурации: информация о текущем шаге не выводится, информация о сделках выводится, количество шагов— 100. (Заметим, что в программе используется генератор случайных чисел, так что результаты будут разными при каждом запуске программы.)
Ticks are OFF
Trades are ON
Run count = 100
Enter command, quit to exit
: run
2 ACME 23 600
27 MSFT 63 400
27 IBM 114 600
38 MSFT 69 400
53 MSFT 75 900
62 INTC 27 800
64 MSFT 82 200
68 MSFT 90 300
81 MSFT 81 600
83 INTC 30 800
91 MSFT 73 700
99 IBM 119 400
Список доступных команд выводится по команде help (помощь). Вот что выводится по этой команде:
count set run count
ticks toggle ticks
trades toggle trades
config show configuration
run run the simulation
quit exit the program
При выполнении программы выводится информация о шаге, акциях, цене и количестве проданных акций.
Определение делегата
В файле Engine . h объявлены два делегата.
_delegate void TickCallback(int ticks);
_delegate void TradeCallback(
int ticks, String *pStock, int price, int volume);
Как мы уже знаем, делегат подобен классу, так что экземпляр делегата создается с помощью оператора new (создать).
TickCallback *pTickDlg =
new TickCallback(0, PrintTick); //0 для статического
TradeCallback *pTradeDlg =
new TradeCallback(0, PrintTrade); //0 для статического
Имя метода передается делегату в качестве аргумента его конструктора. Сигнатура метода должна совпадать с сигнатурой делегата.
static void PrintTick(int ticks)
{
Console::Write("{0} ", _box(ticks));
if (++printcount == LINECOUNT)
{
Console::WriteLine(); printcount = 0;
}
}
static void PrintTrade(
int ticks, String *pStock, int price, int volume)
{
if (printcount != 0)
{
Console::WriteLine();
}
printcount = 0;
Console::WriteLine("{0,4} {l,-4} {2,4} {3,4}",
_box(ticks), pStock,
_box(price), _box(volume));
}
Передача информации о делегате эмулятору
Класс Admin (Управляющий модуль) передает информацию об используемом делегате классу Engine (Машинный модуль) при вызове конструктора класса Engine (Машинный модуль).
Engine *pEngine = new Engine(pTickDlg, pTradeDlg);
Генерация случайных чисел
Основой эмулятора является метод Run (Запуск) класса Engine (Машинный модуль). Основная работа метода Run (Запуск) состоит в присвоении данных, полученных в результате генерации случайных чисел. Для генерации случайных чисел используется класс System: :Random (Система::Случайный), рассмотренный нами в главе 3 "Программирование на управляемом C++".
double г = pRangen->NextDouble();
if (r < tradeProbti])
{
int delta = // дельта
(int) (price[i] * volatility[i]); // цена * изменение
if (pRangen->NextDouble() < .5)
{
delta = -delta; // дельта = - дельта
}
price[i] += delta; // цена + = дельта
int volume = pRangen->Next(
minVolume, maxVolume) * 100;
pTradeOp(
tick, stocks[i], price [i], volume); // шаг, акции,
//цена, объем
Использование делегатов
Указатели на экземпляры делегатов объявляются в классе Engine (Машинный модуль):
TickCallback *pTickOp;
TradeCallback *pTradeOp;
Указатели на делегаты инициализируются в конструкторе класса Engine (Машинный модуль):
Engine(TickCallback *pTickOp, TradeCallback *pTradeOp)
{
this->pTickOp = pTickOp; this->pTradeOp = pTradeOp;
}
Метод, связанный с экземпляром делегата, можно вызвать, используя указатель на делегат:
pTickOp(tick);
pTradeOp(
tick, stocks[i], price [i], volume); // шаг, акции, цена, объем
CompEbook.ru Железо, дизайн, обучение и другие