# 8. C++

# 8.1. Редактор формул

Редактировать формулы на C++ вы можете во вкладке Formulas в окне настроек портфеля, которое открывается при нажатии на иконку :

Написание формул возможно как для всего портфеля, так и для каждого инструмента в отдельности.

В первом случае будут отображены поля Trade formula, Extra field#1 и Extra field#2. Во втором Count formula, Ratio buy formula, Ratio sell formula.

В редакторе формул существует возможность тестового выполнения выбранной формулы (кнопка Test, при этом в строку компиляции добавляется флаг -DDEBUG) и на момент вычисления формулы создаётся временная копия портфеля, НО если вы в формуле изменяете значения полей портфеля, и у вас существует портфель с тем же именем, то изменения применятся к этому портфелю.

Доступно редактирование как включенных, так и выключенных формул.

# 8.2. Важно

При написании формул на языке программирования C++ на код накладываются некоторые ограничения:

  • Вы пишете только тело соответствующих функций, все функции должны возвращать значение типа double;
  • Запрещено использование некоторых символов и слов: \001, #nl, #tab;
  • Вы можете получить доступ к любому портфелю робота, к инструменту портфеля робота, а также к инструменту биржи, который фигурирует хотя бы в одном из ваших порфтелей;
  • Вы можете изменять значения некоторых полей портфелей и инструментов портфелей. При изменении значений каких-то полей, вы можете "сломать" работу штатного алгоритма робота, имейте это в виду. В связи с этим для экстренного отключения торговли и выключения всех расчётов по формулам в меню действий с портфелями предусмотрен пункт Stop formulas;
  • Портфель (структура portfolio) содержит метод data(), который позволяет получить доступ к словарю, в который можно сохранять данные между вызовами формул (в API эти данные НЕ доступны, при выключении робота значения НЕ сохраняются);
  • Портфель (структура portfolio) содержит методы uf0(), ..., uf19() и set_uf0(), ..., set_uf19(), которые позволяют получить доступ к пользовательским полям, которые НЕ используюстя в штатном алгоритме робота и предназначены для исползования пользователем (значения этих полей доступны в API, это такие же поля портфеля, как и все остальные, но зарезервированные для пользователя).

Важно: если значение поля какой-либо бумаги еще не было получено с биржи или для бумаги с данной биржи нельзя получить значение этого поля, то вы получите 0. Нужно понимать что, например, на пустом стакане вы можете получить 0 в качестве цены бида или оффера, поэтому всегда проверяйте значения на равенство нулю в тех ситуациях, где это критично (например, при делении или при нахождении среднего арифметического бида и оффера).

Важно: настоятельно НЕ рекомендуется пользоваться недокументированными особенностями работы робота, т.к. недокументированное поведение робота может быть изменено без предупреждения.

Важно: если формулы изменяют значения каких-то параметров портфеля, которые изменяются алгоритмом, то можно легко получить "неожиданное" поведение.

Важно: при написании формул вы пишете код на небезопасном языке программитрования C++, своими действиями вы легко можете "положить" робота, только вы несете ответственность за корректность работы вашего кода.

Важно: везде в роботе количества в заявках/сделках и в позициях - это целые числа, сделано это для того, чтобы не иметь проблем с операциями над вещественными числами. В С++ API количества и позиции тоже целые числа, по той же причине. Для конвертации количеств и позиций в ту же размерность, в которой они отображаются на сайтах бирж (для тех бирж где возможны дробные значения в данных полях), в тех объектах, которых касается описанная выше проблема, есть поле lot_size. Для перевода из целых в дробные необходимо исходное значение умножить на lot_size, а для перевода из дробных в целые необходимо исходное значение разделить на lot_size. Для параметров портфеля и бумаг портфеля, которых касается lot_size, есть соответствующие пометки в описании этих параметров.

# 8.3. Доступ к биржевым данным по финансовым инструментам

Функция Описание
struct security get_security(const std::string& s) получить инструмент по его SecKey s
struct security get_security(const char* s) получить инструмент по его SecKey s
struct security get_security() получить инструмент, соответствующий главной бумаге текущего портфеля
struct security get_security(const security_fields& sf) получить инструмент, соответствующий заданной бумаге портфеля

Методы security:

Метод Описание
double theor_price() расчетная цена, есть только для опционов
double bid() лучшая цена на покупку
double offer() лучшая цена на продажу
double mid_price() среднее арифметическое лучших цена на покупку и продажу, если одной из цен нет, то это вторая цена, если нет обеих цен, то будет выброшено исключение std::range_error
double exp_date() дата экспирации, в формате epoch
double strike() цена страйк, есть только у опционов
long long amount_offer() объем оффера в лотах
long long amount_bid() объем бида в лотах
double limit_up() разрешенный верхний лимит цены
double limit_down() разрешенный нижний лимит цены
int trading_status() статус торгуемости бумаги на бирже (битовая маска, возможные взведенные биты TRADING_CAN_PLACE и TRADING_CAN_CANCEL, пример)
int conn_online() стауст активности маркет-дата подключения в роботе (битовая маска, возможные взведенные биты MARKET_DATA_BESTS_ONLINE и MARKET_DATA_OB_ONLINE, пример)
double min_step() минимальный шаг цены
double lot_round() количество ценных бумаг в одном стандартном лоте
double lot_size() множитель для конвертации дробных объемов в целые
double funding_rate() ставка фондирования
long long funding_time() время следующего фондирования в формате epoch
const spb_commons& spb_common() структура с полями, описанными ниже
order_book orderbook() структура с методами, описанными ниже

Поля структуры spb_commons (значения будут отличны от нуля только для инструментов с SPBEX):

Название Тип Описание
price_last double цена последней сделки
price_open double цена первой сделки за сессию
price_close double официальная цена закрытия
price_high double сделка с максимальной ценой
price_low double сделка с минимальной ценой
price_auction_close_prev double цена аукциона закрытия предыдущего дня
price_halt double цена для определения приостановок
price_official_min_time long long время последнего изменения минимальной текущей цены
price_indicative double текущая цена рынка
price_close_prev double официальная цена закрытия предыдущего дня
price_official double официальная цена онлайн (текущая цена)
price_vwap_day_prev double средневзвешенная цена основной сессии предыдущего дня
price_vwap_day double средневзвешенная цена основной сессии текущего дня
price_current double текущая котировка
price_average double средневзвешенная цена
time_last long long время последней сделки
price_prev_period_close double цена последней сделки предыдущего дня

Пример: Пример доступа к полям структуры spb_commons.

Методы order_book:

Метод Описание
bool is_available() доступен ли в данный момент для данной бумаги стакан
bool has_next_bid() есть ли еще бид в списке бидов
bool has_next_offer() есть ли еще оффер в списке офферов
std::pair next_bid() получить текущий бид в формате пара: цена + объем (если его нет, вы получите исключение std::out_of_range) и передвинуть указатель на следующий бид в списке
std::pair next_offer() получить текущий оффер в формате пара: цена + объем (если его нет, вы получите исключение std::out_of_range) и передвинуть указатель на следующий оффер в списке

По своей сути order_book является итератором сразу для двух списков: бидов и офферов, оба списка проходятся в порядке от лучшей цены в сторону худших. Вы можете получить только следующую цену в списке, если нужно вернуться к предыдущей - сохраняйте ее или получите order_book заново.

Пример: (opens new window) использования методов структуры order_book.

# 8.4. Доступ и изменение полей инструмента портфеля

Функция Описание
struct security_fields get_security_fields(const std::string& p, const std::string& s) получить бумагу портфеля с именем p с SecKey s
struct security_fields get_security_fields() получить главную бумагу текущего портфеля
struct security_fields get_security_fields(const std::string& s) получить бумагу текущего портфеля с SecKey s

Методы security_fields:

Метод Описание
order_pool orders() получить пул заявок
long long sec_type() получить "Exchange" инструмента портфеля
std::string sec_key() получить "SecKey" инструмента портфеля
int put() получить "Put" инструмента портфеля
double lot_size() получить множитель для конвертации дробных объемов в целые инструмента портфеля
long long pos() получить "Curpos" инструмента портфеля
long long count() получить "Count" инструмента портфеля
int depth_ob() получить "Depth OB" инструмента портфеля
int ob_c_p_t() получить "Calc price OB" инструмента портфеля
int ob_t_p_t() получить "Trading price OB" инструмента портфеля
int decimals() получить "Decimals" инструмента портфеля
double d_pg() получить "date pagination" инструмента портфеля
std::string client_code() получить "Client code" инструмента портфеля
bool is_first() получить "Is first" инструмента портфеля
int on_buy() получить "On buy" инструмента портфеля
int leverage() получить "Leverage" инструмента портфеля
std::string sec_board() получить "SecBoard" инструмента портфеля
std::string sec_code() получить "SecCode" инструмента портфеля
int count_type() получить "Count type" инструмента портфеля
double k() получить "k" инструмента портфеля
bool sle() получить "SLE" инструмента портфеля
double sl() получить "SL" инструмента портфеля
double tp() получить "TP" инструмента портфеля
double k_sl() получить "k_sl" инструмента портфеля
bool te() получить "TE" инструмента портфеля
int timer() получить "Timer" инструмента портфеля
int ratio_sign() получить "Ratio sign" инструмента портфеля
int ratio_type() получить "Ratio type" инструмента портфеля
double ratio_b() получить "Ratio" для расчета покупки инструмента портфеля
double ratio_s() получить "Ratio" для расчета продажи инструмента портфеля
double percent_of_quantity() получить "Percent of quantity" инструмента портфеля
double fin_res_mult() получить "Fin res multiplier" инструмента портфеля
int comission_sign() получить "Commission type" инструмента портфеля
double comission() получить "Commission" инструмента портфеля
bool mm() получить "MM" инструмента портфеля
bool maker() получить "Only maker" инструмента портфеля
bool move_limits() получить "FUT move limits" инструмента портфеля
bool move_limits1() получить "SPOT move limits" инструмента портфеля
int depth_ob() получить "Depth OB" инструмента портфеля
int ob_c_p_t() получить "Calc price OB" инструмента портфеля
int ob_t_p_t() получить "Trading price OB" инструмента портфеля
double mc_level_to0() получить "Level to0" инструмента портфеля
double mc_level_close() получить "Level close" инструмента портфеля
long long max_trans_musec() получить "Max trans time" инструмента портфеля
long long ban_period() получить "Ban period" инструмента портфеля
void set_count(long long v) изменить "Count" инструмента портфеля на значение v
void set_depth_ob(int v) изменить "Depth OB" инструмента портфеля на значение v
void set_ob_c_p_t(int v) изменить "Calc price OB" инструмента портфеля на значение v
void set_ob_t_p_t(int v) изменить "Trading price OB" инструмента портфеля на значение v
void set_decimals(int v) изменить "Decimals" инструмента портфеля на значение v
void set_client_code(std::string v) изменить "Client code" инструмента портфеля на значение v
void set_on_buy(int v) изменить "On buy" инструмента портфеля на значение v
void set_leverage(int v) изменить "Leverage" инструмента портфеля на значение v
void set_count_type(int v) изменить "Count type" инструмента портфеля на значение v
void set_k(double v) изменить "k" инструмента портфеля на значение v
void set_sle(bool v) изменить "SLE" инструмента портфеля на значение v
void set_sl(double v) изменить "SL" инструмента портфеля на значение v
void set_tp(double v) изменить "TP" инструмента портфеля на значение v
void set_k_sl(double v) изменить "k_sl" инструмента портфеля на значение v
void set_te(bool v) изменить "TE" инструмента портфеля на значение v
void set_timer(int v) изменить "Timer" инструмента портфеля на значение v
void set_ratio_sign(int v) изменить "Ratio sign" инструмента портфеля на значение v
void set_ratio_type(int v) изменить "Ratio type" инструмента портфеля на значение v
void set_percent_of_quantity(double v) изменить "Percent of quantity" инструмента портфеля на значение v
void set_fin_res_mult(double v) изменить "Fin res multiplier" инструмента портфеля на значение v
void set_comission_sign(int v) изменить "Commission type" инструмента портфеля на значение v
void set_comission(double v) изменить "Commission" инструмента портфеля на значение v
void set_mm(bool v) изменить "MM" инструмента портфеля на значение v
void set_maker(bool v) изменить "Only maker" инструмента портфеля на значение v
void set_move_limits(bool v) изменить "FUT move limits" инструмента портфеля на значение v
void set_move_limits1(bool v) изменить "SPOT move limits" инструмента портфеля на значение v
void set_depth_ob(int v) изменить "Depth OB" инструмента портфеля на значение v
void set_ob_c_p_t(int v) изменить "Calc price OB" инструмента портфеля на значение v
void set_ob_t_p_t(int v) изменить "Trading price OB" инструмента портфеля на значение v
void set_mc_level_to0(double v) изменить "Level to0" инструмента портфеля на значение v
void set_mc_level_close(double v) изменить "Level close" инструмента портфеля на значение v
void set_max_trans_musec(long long v) изменить "Max trans time" инструмента портфеля на значение v
void set_ban_period(long long v) изменить "Ban period" инструмента портфеля на значение v

Методы order_pool:

Метод Описание
bool has_next() есть ли еще заявка в списке заявок
order_item next() получить текущую заявку (если ее нет, вы получите исключение std::out_of_range) и передвинуть указатель на следующую заявку в списке

По своей сути order_pool является итератором для списка заявок бумаги портфеля робота. Вы можете получить только следующую заявку в списке, если нужно вернуться к предыдущей - сохраняйте ее или получите order_pool заново.

Поля order_item:

Название Тип Описание
price double цена
amount long long количество
amount_rest long long остаток
dir int направление
status int статус

order_item является заявкой робота, возможные значения полей dir и status описаны в константах.

Пример: (opens new window) использования структур order_pool и order_item

# 8.5. Доступ и изменение полей портфеля

Функция Описание
struct portfolio get_portfolio(const std::string& p) получить портфель c именем p
struct portfolio get_portfolio() получить текущий портфель

Методы portfolio:

Метод Описание
void restart_sec_iter() инциализировать итератор (для одного портфеля НЕЛЬЗЯ использовать один итератор вложенный в другой)
bool has_next_sec() есть ли еще бумаги в списке бумаг портфеля
security_fields next_sec() получить следующую бумагу портфеля ( пример итерации )
deal_item deal(const std::string& s) получить сделку по бумаге c SecKey s (доступно только в Trade formula, т.е. на момент совершения сделки), если сделки по указанной бумаге в реальности не было, то amount и price будут равны нулю
deal_item deal(const security_fields& sf) получить сделку по бумаге sf (доступно только в Trade formula, т.е. на момент совершения сделки), если сделки по указанной бумаге в реальности не было, то amount и price будут равны нулю
struct security_fields security_field(const std::string& s) получить бумагу данного портфеля с SecKey s
struct security_fields security_field() получить главную бумагу текущего портфеля
std::map<std::string, double>& data() словарь для сохранения пользовательских значений, НЕ будет сохранен при выключении робота
const user_value& uf0() получить "пользовательское поле" под номером 0 (пользовательские значения никак НЕ используются в штатном алгоритме робота)
... ...
const user_value& uf19() получить "пользовательское поле" под номером 19 (пользовательские значения никак НЕ используются в штатном алгоритме робота)
std::string name() получить "Name" портфеля
int decimals() получить "Decimals" портфеля
std::string comment() получить "Comment" портфеля
bool re_sell() получить "re_sell" портфеля
bool re_buy() получить "re_buy" портфеля
bool use_tt() получить "Use timetable" портфеля
int portfolio_type() получить "Type" портфеля
long long v_in_l() получить "v_in_left" портфеля
long long v_in_r() получить "v_in_right" портфеля
long long v_out_l() получить "v_out_left" портфеля
long long v_out_r() получить "v_out_right" портфеля
long long v_min() получить "v_min" портфеля
long long v_max() получить "v_max" портфеля
double k() получить "K" портфеля
double k1() получить "K1" портфеля
double k2() получить "K2" портфеля
double tp() получить "TP" портфеля
bool equal_prices() получить "Equal prices" портфеля
bool always_limits_timer() получить "Always timer" портфеля
double lim_s() получить "Lim_Sell" портфеля
double lim_b() получить "Lim_Buy" портфеля
double delta() получить "Delta" портфеля
double first_delta() получить "First delta" портфеля
long long mkt_volume() получить "Market volume" портфеля
int type_trade() получить "Type trade" портфеля
int price_type() получить "Type price" портфеля
bool simply_first() получить "Simply first" портфеля
bool quote() получить "Quote" портфеля
double percent() получить "Percent" портфеля
int timer() получить "Limits timer" портфеля
bool to0() получить "To0" портфеля
bool virtual_0_pos() получить "Virt 0 pos" портфеля
double opened() получить "Opened" портфеля
double opened_comission() получить "Commission sum" портфеля
double fin_res_wo_c() получить "Fin res wo C" портфеля
double fin_res() получить "Fin res" портфеля
long long pos() получить "Pos" портфеля
int n_perc_fill() получить "n_perc_fill" портфеля
int max_not_hedged() получить "Max not hedged" портфеля
double return_first() получить "Return first" портфеля
double price_check() получить "Price check" портфеля
int hedge_after() получить "Hedge (sec)" портфеля
long long overlay() получить "Overlay" портфеля
double ext_field1() получить "Extra field#1" портфеля
double ext_field2() получить "Extra field#2" портфеля
double sell() получить "Sell" портфеля
double buy() получить "Buy" портфеля
double price_s() получить "Price_s" портфеля
double price_b() получить "Price_b" портфеля
void set_uf0(const user_value& v) изменить "пользовательское поле" под номером 0 (пользовательские значения никак НЕ используются в штатном алгоритме робота)
... ...
void set_uf19(const user_value& v) изменить "пользовательское поле" под номером 19 (пользовательские значения никак НЕ используются в штатном алгоритме робота)
void set_decimals(int v) изменить "Decimals" портфеля на значение v
void set_comment(std::string v) изменить "Comment" портфеля на значение v
void set_re_sell(bool v) изменить "re_sell" портфеля на значение v
void set_re_buy(bool v) изменить "re_buy" портфеля на значение v
void set_use_tt(bool v) изменить "Use timetable" портфеля на значение v
void set_portfolio_type(int v) изменить "Type" портфеля на значение v
void set_v_in_l(long long v) изменить "v_in_left" портфеля на значение v
void set_v_in_r(long long v) изменить "v_in_right" портфеля на значение v
void set_v_out_l(long long v) изменить "v_out_left" портфеля на значение v
void set_v_out_r(long long v) изменить "v_out_right" портфеля на значение v
void set_v_min(long long v) изменить "v_min" портфеля на значение v
void set_v_max(long long v) изменить "v_max" портфеля на значение v
void set_k(double v) изменить "K" портфеля на значение v
void set_k1(double v) изменить "K1" портфеля на значение v
void set_k2(double v) изменить "K2" портфеля на значение v
void set_tp(double v) изменить "TP" портфеля на значение v
void set_equal_prices(bool v) изменить "Equal prices" портфеля на значение v
void set_always_limits_timer(bool v) изменить "Always timer" портфеля на значение v
void set_lim_s(double v) изменить "Lim_Sell" портфеля на значение v
void set_lim_b(double v) изменить "Lim_Buy" портфеля на значение v
void set_delta(double v) изменить "Delta" портфеля на значение v
void set_first_delta(double v) изменить "First delta" портфеля на значение v
void set_mkt_volume(long long v) изменить "Market volume" портфеля на значение v
void set_type_trade(int v) изменить "Type trade" портфеля на значение v
void set_price_type(int v) изменить "Type price" портфеля на значение v
void set_simply_first(bool v) изменить "Simply first" портфеля на значение v
void set_quote(bool v) изменить "Quote" портфеля на значение v
void set_percent(double v) изменить "Percent" портфеля на значение v
void set_timer(int v) изменить "Limits timer" портфеля на значение v
void set_to0(bool v) изменить "To0" портфеля на значение v
void set_virtual_0_pos(bool v) изменить "Virt 0 pos" портфеля на значение v
void set_opened(double v) изменить "Opened" портфеля на значение v
void set_opened_comission(double v) изменить "Commission sum" портфеля на значение v
void set_n_perc_fill(int v) изменить "n_perc_fill" портфеля на значение v
void set_max_not_hedged(int v) изменить "Max not hedged" портфеля на значение v
void set_return_first(double v) изменить "Return first" портфеля на значение v
void set_price_check(double v) изменить "Price check" портфеля на значение v
void set_hedge_after(int v) изменить "Hedge (sec)" портфеля на значение v
void set_overlay(long long v) изменить "Overlay" портфеля на значение v

Для того чтобы иметь возможность обращаться по индексу к "пользовательским полям" есть массивы:

typedef const user_value& (portfolio::*gUF)() const;
static const gUF uf[] = {&portfolio::uf0, &portfolio::uf1, &portfolio::uf2, &portfolio::uf3, &portfolio::uf4,
                         &portfolio::uf5, &portfolio::uf6, &portfolio::uf7, &portfolio::uf8, &portfolio::uf9,
                         &portfolio::uf10, &portfolio::uf11, &portfolio::uf12, &portfolio::uf13, &portfolio::uf14,
                         &portfolio::uf15, &portfolio::uf16, &portfolio::uf17, &portfolio::uf18, &portfolio::uf19};

typedef void (portfolio::*sUF)(const user_value&);
static const sUF set_uf[] = {&portfolio::set_uf0, &portfolio::set_uf1, &portfolio::set_uf2, &portfolio::set_uf3, &portfolio::set_uf4,
                             &portfolio::set_uf5, &portfolio::set_uf6, &portfolio::set_uf7, &portfolio::set_uf8, &portfolio::set_uf9,
                             &portfolio::set_uf10, &portfolio::set_uf11, &portfolio::set_uf12, &portfolio::set_uf13, &portfolio::set_uf14,
                             &portfolio::set_uf15, &portfolio::set_uf16, &portfolio::set_uf17, &portfolio::set_uf18, &portfolio::set_uf19};

Пример: Пример доступа и редактирования "пользовательских полей" по индексу.

Поля deal_item:

Название Тип Описание
price double средневзвешенная цена сделки
amount long long суммарный объем сделки в лотах
dir int направление сделки: 1 - покупка, 2 - продажа

Конструкторы user_value:

Конструктор Описание
user_value() создать "пустое" пользовательское значение
user_value(double value, const std::string& caption) создать пользовательское значение, указав значение и подпись
user_value(double value) создать пользовательское значение, указав только зачение
user_value(const std::string& caption) создать пользовательское значение, указав только подпись

Методы user_value:

Метод Описание
double value() const получить значение
void set_value(double value) задать значение
bool has_value() const проверить задано ли значение
std::string caption() const получить подпись
void set_caption(const std::string& caption) задать подпись
bool has_caption() const проверить задана ли подпись
user_value& operator=(const user_value& v) оператор копирования, только НЕ "пустые" значения будут скопированы

Пример: Пример использования структуры user_value.

# 8.6. Доступ и изменение позиций транзакционного подключения

Функция Описание
struct connection get_connection(const std::string& c) получить подключение c именем c

Методы connection:

Метод Описание
sec_item sec(const std::string& s) получить информацию о позиции инструмена на бирже (в качестве s необходимо использовать SecBoard из пп 5.5.1. Параметры позиций по инструментам)
coin_item sec(const std::string& s) получить информацию о балансе валюты на бирже (в качестве s необходимо использовать Currency из 5.5.2. Параметры позиций по валютам)
bool is_active() получить информацию о том подключено ли подключение к бирже

Meтоды sec_item:

Метод Описание
long long pos() получить поле "Pos" инструмента
long long robot_pos() получить поле "Robot pos" инструмента
double mark_price() получить поле "Mark. price" инструмента
double liq_price() получить поле "Liq. price" инструмента
long long pos_lag() получить поле "Pos lag" инструмента
bool pos_eq() получить поле "Check equality" инструмента
bool tgr() получить поле "Tgr notify" инструмента
void set_pos_lag(long long v) изменить поле "Pos lag" инструмента
void set_pos_eq(bool v) изменить поле "Check equality" инструмента
void set_tgr(bool v) изменить поле "Tgr notify" инструмента

Meтоды coin_item:

Метод Описание
double pos() получить поле "Pos" (или "Limit") валюты
double robot_pos() получить поле "Robot pos" валюты
double pos_lag() получить поле "Pos lag" валюты
bool pos_eq() получить поле "Check equality" валюты
bool tgr() получить поле "Tgr notify" валюты
void set_pos_lag(double v) изменить поле "Pos lag" валюты
void set_pos_eq(bool v) изменить поле "Check equality" валюты
void set_tgr(bool v) изменить поле "Tgr notify" валюты

# 8.7. Дополнительные классы, структуры, функции и константы

# 8.7.1. Константы

Название Тип Значение/описание
BUY int 1, направление торговли - покупка
SELL int 2, направление торговли - продажа
FREE int 0, заявка не активна
ADDING int 1, заявка отправлена на биржу
RUNNING int 2, получен ответ о том, что заявка выставлена
DELETING int 4, снятие заявки отправлено на биржу
FIRST_DELETING int 5, снятие котируемой заявки отправлено на биржу
SL_DELETING int 6, снятие заявки по стопу отправлено на биржу
MOVING int 7, запрос на изменение заявки отправлен на биржу
ADD_ERROR int 99, ошибка выставления заявки
TRADING_HALT int 0, выставления и снятие заявок запрещены
TRADING_CAN_PLACE
int 1, разрешено выставления заявок
TRADING_CAN_CANCEL
int 2, разрешено снятие заявок
MARKET_DATA_OFFLINE int 0, маркет-дата подключение для данной бумаги оффлайн
MARKET_DATA_BESTS_ONLINE
int 1, для данной бумаги маркет-дата подключение с лучшими ценами на покупку/продажу онлайн
MARKET_DATA_OB_ONLINE
int 2, для данной бумаги маркет-дата подключение со стаканами онлайн
NAME std::string имя текущего портфеля

# 8.7.2. Функции

Функция Описание
long long nanosec_date_time() получить текущее время в epoch в наносекундах
struct tm global_tm() получить текущее время
day_time get_day_time() получить текущее время дня
void log_info(const std::string& msg) отправить сообщение с уровнем INFO в лог
void log_warn(const std::string& msg) отправить сообщение с уровнем WARNING в лог
void log_error(const std::string& msg) отправить сообщение с уровнем ERROR в лог
bool tgr_notify(int slot, const std::string& msg, int timeout)
отправить сообщение с уровнем NOTIFICATION в лог и уведомление в telegram, отправлять не чаще, чем timeout секунд (число из отрезка [10, 2000000000]), slot - идентификатор слота уведомления (число из отрезка [0, 4]), для которого будет отсчитываться timeout

# 8.7.3. Структуры

Структура day_time (время дня в часах, минутах, секундах):

Конструктор Описание
day_time() создать объект с временем 00:00:00
day_time(int h, int m, int s) создать объект с временем h:m:s
day_time(const day_time& dt) конструктор копирования
Название поля Тип Описание
h int часы (от 0 до 23)
m int минуты (от 0 до 59)
s int секунды (от 0 до 59)
Функции и методы Описание
int to_sec() const получить время в секундах, т.е. h * 3600 + m * 60 + s
bool operator<(const day_time& a, const day_time& b) оператор <
bool operator<=(const day_time& a, const day_time& b) оператор <=
bool operator>(const day_time& a, const day_time& b) оператор >
bool operator>=(const day_time& a, const day_time& b) оператор >=
bool operator==(const day_time& a, const day_time& b) оператор ==
bool operator!=(const day_time& a, const day_time& b) оператор !=

Пример: Пример использования структуры day_time.

# 8.7.4. Классы

Важно: все классы, описанные ниже, относятся к пространству имен timers.

Класс timer (отмеряет отрезки времени не менее заданного в наносекундах):

Конструктор Описание
timer(unsigned long long timeout, bool initialized = false) создать объект с интервалом таймера timeout (в наносекундах), если initialized истинно, то стартовое время будет задано текущим временем, иначе стартовое время не определено и первый timeout сработает сразу
Функции и методы Описание
bool tick() Если с момента предыдущего вызова данного метода прошло не меньше, чем timeout наносекунд, то вернет истину и обновит предыдущее время вызова

Класс day_timer (отмеряет сутки и вызывается не ранее, чем в заданный момент времени):

Конструктор Описание
day_timer(int h, int m, int s, bool initialized = false) создать объект с временем срабатывания на следующие сутки не раньше, чем в момент времени h:m:s (часов, минут, секунд), если initialized истинно, то стартовое время будет задано текущим временем, иначе стартовое время не определено и первый таймаут может сработать и без смены дня
day_timer(int h, int m, bool initialized = false) создать объект с временем срабатывания на следующие сутки не раньше, чем в момент времени h:m (часов, минут, 0 секунд), если initialized истинно, то стартовое время будет задано текущим временем, иначе стартовое время не определено и первый таймаут может сработать и без смены дня
day_timer(const day_time& dt, bool initialized = false) создать объект с временем срабатывания на следующие сутки не раньше, чем в момент времени dt, если initialized истинно, то стартовое время будет задано текущим временем, иначе стартовое время не определено и первый таймаут может сработать и без смены дня
Функции и методы Описание
bool tick() Если изменился день и текущее время больше или равно заданному, то вернет истину и обновит сохраненный день

Пример: Примеры использования классов timer и day_timer.

# 8.7.5. Функции для работы с опционами

# 8.7.5.1. “Умные” функции

double S_delta(const std::string& s, double rate = 0)
double P_delta(const std::string& p, double rate = 0)
вычисляет дельту финансового инструмента или портфеля со ставкой рефинансирования rate (указывается в процентах)

double S_gamma(const std::string& s, double rate = 0)
double P_gamma(const std::string& p, double rate = 0)
вычисляет гамму финансового инструмента или портфеля со ставкой рефинансирования rate (указывается в процентах)

double S_vega(const std::string& s, double rate = 0)
double P_vega(const std::string& p, double rate = 0)
вычисляет вегу финансового инструмента или портфеля со ставкой рефинансирования rate (указывается в процентах)

double S_theta(const std::string& s, double rate = 0)
double P_theta(const std::string& p, double rate = 0)
вычисляет тету финансового инструмента или портфеля со ставкой рефинансирования rate (указывается в процентах)

double S_iv(const std::string& s, double rate = 0)
double P_iv(const std::string& p, double rate = 0)
вычисляет ожидаемую волатильность опциона или портфеля со ставкой рефинансирования rate (указывается в процентах)

double S_price(const std::string& s, double rate = 0)
вычисляет справедливую цену опциона со ставкой рефинансирования rate (указывается в процентах)

Аргументы для функций выше:

Название Описание
s ключ инструмента SecKey
p имя портфеля
rate ставка рефинансирования в процентах

# 8.7.5.2. “Простые” функции

double C(double futPrice, double strike, double expDate, double iv, double rate=0)
вычисляет справедливую цену опциона call

double P(double futPrice, double strike, double expDate, double iv, double rate=0)
вычисляет справедливую цену опциона put

double CDELTA(double futPrice, double strike, double expDate, double iv, double rate=0)
вычисляет дельту опциона call

double PDELTA(double futPrice, double strike, double expDate, double iv, double rate=0) вычисляет дельту опциона put

double CGAMMA(double futPrice, double strike, double expDate, double iv, double rate=0)
вычисляет гамму опциона call

double PGAMMA(double futPrice, double strike, double expDate, double iv, double rate=0)
вычисляет гамму опциона put

double CVEGA(double futPrice, double strike, double expDate, double iv, double rate=0)
вычисляет вегу опциона call

double PVEGA(double futPrice, double strike, double expDate, double iv, double rate=0)
вычисляет вегу опциона put

double CTHETA(double futPrice, double strike, double expDate, double iv, double rate=0)
вычисляет тету опциона call

double PTHETA(double futPrice, double strike, double expDate, double iv, double rate=0)
вычисляет тету опциона put

double CIV(double futPrice, double strike, double expDate, double call, double rate=0)
вычисляет implied volatility опциона call

double PIV(double futPrice, double strike, double expDate, double put, double rate=0)
вычисляет implied volatility опциона put

Аргументы для функций выше:

Название Описание
futPrice цена базового актива
strike цена страйк опциона
expData дата экспирации опциона в формате epoch
iv ожидаемая волатильность
call/put цена опциона
rate ставка рефинансирования в процентах

# 8.8. Индикаторы и математическая статистика

# 8.8.1. Общие положения

# 8.8.1.1. Особенности объектов для расчета значений индикаторов

Для расчета индикаторов используются объекты соответствующих классов, т.к. объекты создаются внутри функции, то чтобы они каждый раз не создавались заново и инициализировались только один раз, все объекты предполагается создавать как статические (static). Если для расчета значения индикатора нужна история, а ее в данный момент не хватает (т.е. количество значений в истории меньше, чем length), то в качестве значения length индикаторов будет использоваться текущее количество элементов в накопленной истории.

Все "формулы" в роботе вызываются (пересчитываются) при любом обновлении стакана любой бумаги портфеля + раз в секунду, поэтому пытаться добавлять значение для пересчета индикатора вы можете довольно часто. Добавленное значение будет считаться новым и индикатор будет пересчитан, только если [ttimeframe]×timeframe>tlast[\frac{t}{\mathit{timeframe}}] \times \mathit{timeframe} > t_{last}, где tt - текущее время, timeframe\mathit{timeframe} - таймфрейм для расчета индиактора, tlastt_{last} - время последнего значения, используемого для расчета индикатора в данный момент. Т.е. по большому счету индикатор строится по "ценам открытия" значений на выбранном таймфрейме.

Важно: все классы, описанные ниже, относятся к пространству имен indicators.

Примеры использования индикаторов в пользовательском коде.

# 8.8.1.2. TradingDays и schedule индикатора

Для расчета любого индикатора обычно используются цены, получаемые с биржи. Если бумага на бирже торгуется 24/7, то никаких сложностей с ценами не возникает, в противном же случае встает вопрос фильтрации получаемых данных, чтобы не пересчитывать индикаторы на "нулевых" и "кривых" ценах (при пустых стаканах в неторговые дни и часы, аукционах открытия и т.п.). Для фильтрации цен у объектов индикаторов существуют TradingDays и schedule, TradingDays - это фильтр по дням, а schedule - фильтр по временным интервалам внутри дня (для всех дней schedule одинаковое).

По умолчанию TradingDays индикатора - это ссылка на TradingDays портфеля, в коде которого данный индикатор считается, т.е. при изменении TradingDays портфеля TradingDays индикатора тоже будет изменен (это справедливо даже если в портфеле TradingDays не используется). Если же необходимо использовать свой TradingDays, то индикатору можно явно указать значение для TradingDays. TradingDays - это битовая маска торговых дней недели, дни недели занумерованы с нуля, причем нулевой бит (считая справа налево) - это воскресенье, т.е. воскресенье это 1 << 0 (где << это побитовый сдвиг числа влево), понедельник это 1 << 1 и т.д.

По умолчанию schedule индикатора пуст, это означает, что расписание не задано и фильтрация по времени отсутствует. Если же schedule не пусто, то это список неперсекающихся временных интервалов (временной интервал - это пара времен, т.е. время начала и время конца, оба времени включительно) в которые необходимо рассчитывать значение индекса.

# 8.8.1.3. Объект indicators::interval

Конструкторы interval:

Конструктор Описание
interval(day_time b, day_time e) создать временной интервал c началом во время b и концом во время e, должно выполняться условие b < e, иначае будет выброшено исключение std::invalid_argument

# 8.8.1.4. Объект indicators::schedule

Конструкторы schedule:

Конструктор Описание
schedule() создать пустое расписание
schedule(std::vector<interval> sch) создать расписание, инициализированное списком непересекающихся интервалов, отсортированных по возрастанию, если интервалы пересекаются или не отсорированы по возрастанию, будет выброшено исключение std::invalid_argument
schedule(const schedule& sch) конструктор копирования

Методы schedule:

Метод Описание
bool is_in(const day_time& dt) const проверить находится ли указанное время в одном из интервалов расписания

# 8.8.1.5. Константы

Название Тип Значение/описание
WD_SUNDAY int 1 << 0, воскресенье
WD_MONDAY int 1 << 1, понедельник
WD_TUESDAY int 1 << 2, вторник
WD_WEDNESDAY int 1 << 3, среда
WD_THURSDAY int 1 << 4, четверг
WD_FRIDAY int 1 << 5, пятница
WD_SATURDAY int 1 << 6, суббота
WHOLE_WEEK int WD_SUNDAY | WD_MONDAY | WD_TUESDAY | WD_WEDNESDAY | WD_THURSDAY | WD_FRIDAY | WD_SATURDAY, торговать всю неделю
WORK_WEEK int WD_MONDAY | WD_TUESDAY | WD_WEDNESDAY | WD_THURSDAY | WD_FRIDAY, торговать с понедельника по пятницу

# 8.8.2. Простое скользящее среднее (SMA)

Рассчитывается по формуле:

SMAt=1ni=0n1pti\mathit{SMA}_t = \frac{1}{n} \sum_{i=0}^{n - 1}p_{t-i}

где SMAt\mathit{SMA}_t - значение искомой величины в момент времени tt;

ptip_{t-i} - значение исходной функции (цены) в момент времени tit-i;

nn - количество значений исходной функции (цены) для расчета искомой величины (SMA).

Конструкторы SMA:

Конструктор Описание
SMA() создать объект с пустым раписанием и с TradingDays портфеля
SMA(std::vector<interval> sch) создать объект c раписанием и с TradingDays портфеля
SMA(schedule sch) создать объект c раписанием и с TradingDays портфеля

Методы SMA:

Метод Описание
size_t length() const Получить количество элементов для расчета (парметр nn из формулы)
void set_length(size_t n) Задать количество элементов для расчета, значение данного параметра должно быть целым числом из отрезка [1, 10000] (значение по умолчания 10), в противном случае будет выброшено исключение std::invalid_argument
size_t timeframe() const Получить тайм-фрейм расчетов, т.е. с какой периодичностью получать pip_{i}
void set_timeframe(size_t timeframe) Задать тайм-фрейм для расчетов (в секундах), значение данного параметра должно быть целым числом из отрезка [1, 86400] (значение по умолчанию 1 секунда), в противном случае будет выброшено исключение std::invalid_argument. При изменении таймфрейма накопленная для расчетов очередь значений очищается
int trading_days() const Получить TradingDays индикатора
void set_trading_days(int trading_days) Задать TradingDays, значение данного параметра должно быть целым числом из отрезка [0, 127], в противном случае будет выброшено исключение std::invalid_argument
bool update(double p) Добавить новое значение pip_{i} для расчета. Если тайм-фрейм истек, то новое значение будет добавлено и функция вернет true, иначе false
double value() const Получить текущее значение индикатора. Если список элементов для расчета индикатора пуст, то будет выброшено исключение std::out_of_range
void clear() Очистить список элементов по которым считается значение индикатора
bool empty() Проверить на пустоту список элементов по которым считается значение индикатора
size_t size() Получить размер списка элементов по которым считается значение индикатора
void shift(double p) Прибавить заданное значение ко всем элементам списка по которым считается значение индикатора и пересчитать значение индикатора по новым значениям

# 8.8.3. Экспоненциальное скользящее среднее (EMA)

Рассчитывается по формуле:

EMAt=2n+1(ptEMAt1)+EMAt1\mathit{EMA}_t = \frac{2}{n + 1} (p_t - \mathit{EMA}_{t-1}) + \mathit{EMA}_{t-1}

где EMAt\mathit{EMA}_t - значение искомой величины в момент времени tt;

EMAt1\mathit{EMA}_{t-1} - значение искомой величины в предыдущий момент времени, т.е. в момент времени t1t-1;

ptp_{t} - значение исходной функции (цены) в момент времени tt;

nn - количество значений исходной функции (цены) для расчета искомой величины (EMA).

Конструкторы EMA:

Конструктор Описание
EMA() создать объект с пустым раписанием и с TradingDays портфеля
EMA(std::vector<interval> sch) создать объект c раписанием и с TradingDays портфеля
EMA(schedule sch) создать объект c раписанием и с TradingDays портфеля

Методы EMA:

Метод Описание
size_t length() const Получить количество элементов для расчета (парметр nn из формулы)
void set_length(size_t n) Задать количество элементов для расчета, значение данного параметра должно быть целым числом из отрезка [1, 10000] (значение по умолчания 10), в противном случае будет выброшено исключение std::invalid_argument
size_t timeframe() const Получить тайм-фрейм расчетов, т.е. с какой периодичностью получать pip_{i}
void set_timeframe(size_t timeframe) Задать тайм-фрейм для расчетов (в секундах), значение данного параметра должно быть целым числом из отрезка [1, 86400] (значение по умолчанию 1 секунда), в противном случае будет выброшено исключение std::invalid_argument. При изменении таймфрейма накопленная для расчетов очередь значений очищается
int trading_days() const Получить TradingDays индикатора
void set_trading_days(int trading_days) Задать TradingDays, значение данного параметра должно быть целым числом из отрезка [0, 127], в противном случае будет выброшено исключение std::invalid_argument
bool update(double p) Добавить новое значение pip_{i} для расчета. Если тайм-фрейм истек, то новое значение будет добавлено и функция вернет true, иначе false
double value() const Получить текущее значение индикатора. Если список элементов для расчета индикатора пуст, то будет выброшено исключение std::out_of_range
void clear() Очистить список элементов по которым считается значение индикатора
bool empty() Проверить на пустоту список элементов по которым считается значение индикатора
size_t size() Получить размер списка элементов по которым считается значение индикатора
void shift(double p) Прибавить заданное значение ко всем элементам списка по которым считается значение индикатора и пересчитать значение индикатора по новым значениям

# 8.8.4. Максимум на отрезке (Max)

Рассчитывается по формуле:

Maxt=max(pt,pt1,...,ptn+1)\mathit{Max}_t = \max(p_{t}, p_{t-1}, ... , p_{t-n+1})

где Maxt\mathit{Max}_t - значение искомой величины в момент времени tt;

ptp_{t} - значение исходной функции (цены) в момент времени tt;

pip_{i} - значение исходной функции (цены) в момент времени ii;

nn - количество значений исходной функции (цены) для расчета искомой величины (Max).

Конструкторы Max:

Конструктор Описание
Max() создать объект с пустым раписанием и с TradingDays портфеля
Max(std::vector<interval> sch) создать объект c раписанием и с TradingDays портфеля
Max(schedule sch) создать объект c раписанием и с TradingDays портфеля

Методы Max:

Метод Описание
size_t length() const Получить количество элементов для расчета (парметр nn из формулы)
void set_length(size_t n) Задать количество элементов для расчета, значение данного параметра должно быть целым числом из отрезка [1, 10000] (значение по умолчания 10), в противном случае будет выброшено исключение std::invalid_argument
size_t timeframe() const Получить тайм-фрейм расчетов, т.е. с какой периодичностью получать pip_{i}
void set_timeframe(size_t timeframe) Задать тайм-фрейм для расчетов (в секундах), значение данного параметра должно быть целым числом из отрезка [1, 86400] (значение по умолчанию 1 секунда), в противном случае будет выброшено исключение std::invalid_argument. При изменении таймфрейма накопленная для расчетов очередь значений очищается
int trading_days() const Получить TradingDays индикатора
void set_trading_days(int trading_days) Задать TradingDays, значение данного параметра должно быть целым числом из отрезка [0, 127], в противном случае будет выброшено исключение std::invalid_argument
bool update(double p) Добавить новое значение pip_{i} для расчета. Если тайм-фрейм истек, то новое значение будет добавлено и функция вернет true, иначе false
double value() const Получить текущее значение индикатора. Если список элементов для расчета индикатора пуст, то будет выброшено исключение std::out_of_range
void clear() Очистить список элементов по которым считается значение индикатора
bool empty() Проверить на пустоту список элементов по которым считается значение индикатора
size_t size() Получить размер списка элементов по которым считается значение индикатора
void shift(double p) Прибавить заданное значение ко всем элементам списка по которым считается значение индикатора и пересчитать значение индикатора по новым значениям

# 8.8.5. Минимум на отрезке (Min)

Рассчитывается по формуле:

Mint=min(pt,pt1,...,ptn+1)\mathit{Min}_t = \min(p_{t}, p_{t-1}, ... , p_{t-n+1})

где Mint\mathit{Min}_t - значение искомой величины в момент времени tt;

ptp_{t} - значение исходной функции (цены) в момент времени tt;

nn - количество значений исходной функции (цены) для расчета искомой величины (Min).

Конструкторы Min:

Конструктор Описание
Min() создать объект с пустым раписанием и с TradingDays портфеля
Min(std::vector<interval> sch) создать объект c раписанием и с TradingDays портфеля
Min(schedule sch) создать объект c раписанием и с TradingDays портфеля

Методы Min:

Метод Описание
size_t length() const Получить количество элементов для расчета (парметр nn из формулы)
void set_length(size_t n) Задать количество элементов для расчета, значение данного параметра должно быть целым числом из отрезка [1, 10000] (значение по умолчания 10), в противном случае будет выброшено исключение std::invalid_argument
size_t timeframe() const Получить тайм-фрейм расчетов, т.е. с какой периодичностью получать pip_{i}
void set_timeframe(size_t timeframe) Задать тайм-фрейм для расчетов (в секундах), значение данного параметра должно быть целым числом из отрезка [1, 86400] (значение по умолчанию 1 секунда), в противном случае будет выброшено исключение std::invalid_argument. При изменении таймфрейма накопленная для расчетов очередь значений очищается
int trading_days() const Получить TradingDays индикатора
void set_trading_days(int trading_days) Задать TradingDays, значение данного параметра должно быть целым числом из отрезка [0, 127], в противном случае будет выброшено исключение std::invalid_argument
bool update(double p) Добавить новое значение pip_{i} для расчета. Если тайм-фрейм истек, то новое значение будет добавлено и функция вернет true, иначе false
double value() const Получить текущее значение индикатора. Если список элементов для расчета индикатора пуст, то будет выброшено исключение std::out_of_range
void clear() Очистить список элементов по которым считается значение индикатора
bool empty() Проверить на пустоту список элементов по которым считается значение индикатора
size_t size() Получить размер списка элементов по которым считается значение индикатора
void shift(double p) Прибавить заданное значение ко всем элементам списка по которым считается значение индикатора и пересчитать значение индикатора по новым значениям

# 8.8.6. Дисперсия (Var)

Рассчитывается по формуле:

Vart=1ni=0n1(ptip)2\mathit{Var}_t = \frac{1}{n}\sum_{i=0}^{n-1}{\left( p_{t - i} - \overline{p} \right) ^2}

где Vart\mathit{Var}_t - значение искомой величины в момент времени tt;

p=1ni=0n1pti\overline{p} = \frac{1}{n}\sum_{i=0}^{n-1}{p_{t - i}};

ptip_{t-i} - значение исходной функции (цены) в момент времени tit-i;

nn - количество значений исходной функции (цены) для расчета искомой величины (Var).

Конструкторы Var:

Конструктор Описание
Var() создать объект с пустым раписанием и с TradingDays портфеля
Var(std::vector<interval> sch) создать объект c раписанием и с TradingDays портфеля
Var(schedule sch) создать объект c раписанием и с TradingDays портфеля

Методы Var:

Метод Описание
size_t length() const Получить количество элементов для расчета (парметр nn из формулы)
void set_length(size_t n) Задать количество элементов для расчета, значение данного параметра должно быть целым числом из отрезка [1, 10000] (значение по умолчания 10), в противном случае будет выброшено исключение std::invalid_argument
size_t timeframe() const Получить тайм-фрейм расчетов, т.е. с какой периодичностью получать pip_{i}
void set_timeframe(size_t timeframe) Задать тайм-фрейм для расчетов (в секундах), значение данного параметра должно быть целым числом из отрезка [1, 86400] (значение по умолчанию 1 секунда), в противном случае будет выброшено исключение std::invalid_argument. При изменении таймфрейма накопленная для расчетов очередь значений очищается
int trading_days() const Получить TradingDays индикатора
void set_trading_days(int trading_days) Задать TradingDays, значение данного параметра должно быть целым числом из отрезка [0, 127], в противном случае будет выброшено исключение std::invalid_argument
bool update(double p) Добавить новое значение pip_{i} для расчета. Если тайм-фрейм истек, то новое значение будет добавлено и функция вернет true, иначе false
double value() const Получить текущее значение индикатора. Если список элементов для расчета индикатора пуст, то будет выброшено исключение std::out_of_range
void clear() Очистить список элементов по которым считается значение индикатора
bool empty() Проверить на пустоту список элементов по которым считается значение индикатора
size_t size() Получить размер списка элементов по которым считается значение индикатора
void shift(double p) Прибавить заданное значение ко всем элементам списка по которым считается значение индикатора и пересчитать значение индикатора по новым значениям

# 8.8.7. Среднеквадратическое отклонение (StdDev)

Рассчитывается по формуле:

StdDevt=1ni=0n1(ptip)2\mathit{StdDev}_t = \sqrt{\frac{1}{n}\sum_{i=0}^{n-1}{\left( p_{t - i} - \overline{p} \right) ^2}}

где StdDevt\mathit{StdDev}_t - значение искомой величины в момент времени tt;

p=1ni=0n1pti\overline{p} = \frac{1}{n}\sum_{i=0}^{n-1}{p_{t - i}};

ptip_{t-i} - значение исходной функции (цены) в момент времени tit-i;

nn - количество значений исходной функции (цены) для расчета искомой величины (StdDev).

Конструкторы StdDev:

Конструктор Описание
StdDev() создать объект с пустым раписанием и с TradingDays портфеля
StdDev(std::vector<interval> sch) создать объект c раписанием и с TradingDays портфеля
StdDev(schedule sch) создать объект c раписанием и с TradingDays портфеля

Методы StdDev:

Метод Описание
size_t length() const Получить количество элементов для расчета (парметр nn из формулы)
void set_length(size_t n) Задать количество элементов для расчета, значение данного параметра должно быть целым числом из отрезка [1, 10000] (значение по умолчания 10), в противном случае будет выброшено исключение std::invalid_argument
size_t timeframe() const Получить тайм-фрейм расчетов, т.е. с какой периодичностью получать pip_{i}
void set_timeframe(size_t timeframe) Задать тайм-фрейм для расчетов (в секундах), значение данного параметра должно быть целым числом из отрезка [1, 86400] (значение по умолчанию 1 секунда), в противном случае будет выброшено исключение std::invalid_argument. При изменении таймфрейма накопленная для расчетов очередь значений очищается
int trading_days() const Получить TradingDays индикатора
void set_trading_days(int trading_days) Задать TradingDays, значение данного параметра должно быть целым числом из отрезка [0, 127], в противном случае будет выброшено исключение std::invalid_argument
bool update(double p) Добавить новое значение pip_{i} для расчета. Если тайм-фрейм истек, то новое значение будет добавлено и функция вернет true, иначе false
double value() const Получить текущее значение индикатора. Если список элементов для расчета индикатора пуст, то будет выброшено исключение std::out_of_range
void clear() Очистить список элементов по которым считается значение индикатора
bool empty() Проверить на пустоту список элементов по которым считается значение индикатора
size_t size() Получить размер списка элементов по которым считается значение индикатора
void shift(double p) Прибавить заданное значение ко всем элементам списка по которым считается значение индикатора и пересчитать значение индикатора по новым значениям

# 8.8.8. Линии Боллинджера (BB)

Состоит из трех значений, рассчитывается по формуле:

MLt=1ni=0n1pti\mathit{ML}_t = \frac{1}{n} \sum_{i=0}^{n - 1}p_{t-i}

TLt=MLt+d×StdDevt\mathit{TL}_t = \mathit{ML}_t + d \times \mathit{StdDev}_t

BLt=MLtd×StdDevt\mathit{BL}_t = \mathit{ML}_t - d \times \mathit{StdDev}_t

где MLt\mathit{ML}_t, TLt\mathit{TL}_t, BLt\mathit{BL}_t - значения искомых величин в момент времени tt;

StdDevt=1ni=0n1(ptip)2\mathit{StdDev}_t = \sqrt{\frac{1}{n}\sum_{i=0}^{n-1}{\left( p_{t - i} - \overline{p} \right) ^2}};

p=1ni=0n1pti\overline{p} = \frac{1}{n}\sum_{i=0}^{n-1}{p_{t - i}};

ptip_{t-i} - значение исходной функции (цены) в момент времени tit-i;

dd - константа;

nn - количество значений исходной функции (цены) для расчета искомой величины (BB).

Конструкторы BB:

Конструктор Описание
BB() создать объект с пустым раписанием и с TradingDays портфеля
BB(std::vector<interval> sch) создать объект c раписанием и с TradingDays портфеля
BB(schedule sch) создать объект c раписанием и с TradingDays портфеля

Методы BB:

Метод Описание
size_t length() const Получить количество элементов для расчета (парметр nn из формулы)
void set_length(size_t n) Задать количество элементов для расчета, значение данного параметра должно быть целым числом из отрезка [1, 10000] (значение по умолчания 10), в противном случае будет выброшено исключение std::invalid_argument
size_t timeframe() const Получить тайм-фрейм расчетов, т.е. с какой периодичностью получать pip_{i}
void set_timeframe(size_t timeframe) Задать тайм-фрейм для расчетов (в секундах), значение данного параметра должно быть целым числом из отрезка [1, 86400] (значение по умолчанию 1 секунда), в противном случае будет выброшено исключение std::invalid_argument. При изменении таймфрейма накопленная для расчетов очередь значений очищается
double d() const Получить dd
void set_d(double d) Задать dd, значение данного параметра должно быть дробным числом из отрезка [1, 1000] (значение по умолчанию 4), в противном случае будет выброшено исключение std::invalid_argument
int trading_days() const Получить TradingDays индикатора
void set_trading_days(int trading_days) Задать TradingDays, значение данного параметра должно быть целым числом из отрезка [0, 127], в противном случае будет выброшено исключение std::invalid_argument
bool update(double p) Добавить новое значение pip_{i} для расчета. Если тайм-фрейм истек, то новое значение будет добавлено и функция вернет true, иначе false
double value() const Получить текущее значение ML индикатора. Если список элементов для расчета индикатора пуст, то будет выброшено исключение std::out_of_range
double tl() const Получить текущее значение TL индикатора. Если список элементов для расчета индикатора пуст, то будет выброшено исключение std::out_of_range
double ml() const Получить текущее значение ML индикатора. Если список элементов для расчета индикатора пуст, то будет выброшено исключение std::out_of_range
double bl() const Получить текущее значение BL индикатора. Если список элементов для расчета индикатора пуст, то будет выброшено исключение std::out_of_range
void clear() Очистить список элементов по которым считается значение индикатора
bool empty() Проверить на пустоту список элементов по которым считается значение индикатора
size_t size() Получить размер списка элементов по которым считается значение индикатора
void shift(double p) Прибавить заданное значение ко всем элементам списка по которым считается значение индикатора и пересчитать значение индикатора по новым значениям

# 8.8.9. Индекс относительной силы (RSI)

Рассчитывается по формуле:

RSIt=1001001+RSt\mathit{RSI}_t = 100 - \frac{100}{1 + \mathit{RS}_t}

где RSIt\mathit{RSI}_t - значение искомой величины в момент времени tt;

RSt=EMA_GAINtEMA_LOSSt\mathit{RS}_{t} = \frac{EMA\_GAIN_t}{EMA\_LOSS_t};

EMA_GAINt=2n+1(GtEMA_GAINt1)+EMA_GAINt1\mathit{EMA\_GAIN}_t = \frac{2}{n + 1} (G_t - \mathit{EMA\_GAIN}_{t-1}) + \mathit{EMA\_GAIN}_{t-1};

EMA_LOSSt=2n+1(LtEMA_LOSSt1)+EMA_LOSSt1\mathit{EMA\_LOSS}_t = \frac{2}{n + 1} (L_t - \mathit{EMA\_LOSS}_{t-1}) + \mathit{EMA\_LOSS}_{t-1};

Gt={ptpt1,ifptpt10,ifpt<pt1G_{t} = \begin{cases} p_t - p_{t-1}, &\text{if}\enspace p_t \ge p_{t-1}\\ 0, &\text{if}\enspace p_t < p_{t-1} \end{cases};

Lt={pt1pt,ifptpt10,ifpt>pt1L_{t} = \begin{cases} p_{t-1} - p_t, &\text{if}\enspace p_t \le p_{t-1}\\ 0, &\text{if}\enspace p_t > p_{t-1} \end{cases};

ptp_{t} - значение исходной функции (цены) в момент времени tt;

n+1n + 1 - количество значений исходной функции (цены) для расчета искомой величины (RSI).

Конструкторы RSI:

Конструктор Описание
RSI() создать объект с пустым раписанием и с TradingDays портфеля
RSI(std::vector<interval> sch) создать объект c раписанием и с TradingDays портфеля
RSI(schedule sch) создать объект c раписанием и с TradingDays портфеля

Методы RSI:

Метод Описание
size_t length() const Получить количество элементов для расчета (парметр nn из формулы)
void set_length(size_t n) Задать количество элементов для расчета, значение данного параметра должно быть целым числом из отрезка [1, 10000] (значение по умолчания 10), в противном случае будет выброшено исключение std::invalid_argument
size_t timeframe() const Получить тайм-фрейм расчетов, т.е. с какой периодичностью получать pip_{i}
void set_timeframe(size_t timeframe) Задать тайм-фрейм для расчетов (в секундах), значение данного параметра должно быть целым числом из отрезка [1, 86400] (значение по умолчанию 1 секунда), в противном случае будет выброшено исключение std::invalid_argument. При изменении таймфрейма накопленная для расчетов очередь значений очищается
int trading_days() const Получить TradingDays индикатора
void set_trading_days(int trading_days) Задать TradingDays, значение данного параметра должно быть целым числом из отрезка [0, 127], в противном случае будет выброшено исключение std::invalid_argument
bool update(double p) Добавить новое значение pip_{i} для расчета. Если тайм-фрейм истек, то новое значение будет добавлено и функция вернет true, иначе false
double value() const Получить текущее значение индикатора. Если список элементов для расчета индикатора пуст, то будет выброшено исключение std::out_of_range
void clear() Очистить список элементов по которым считается значение индикатора
bool empty() Проверить на пустоту список элементов по которым считается значение индикатора
size_t size() Получить размер списка элементов по которым считается значение индикатора
void shift(double p) Прибавить заданное значение ко всем элементам списка по которым считается значение индикатора и пересчитать значение индикатора по новым значениям

# 8.9. Примеры доступа к параметрам портфеля, инструмента, сделки, позиций

Пусть имеется портфель с именем "si" и в этом портфеле есть один инструмент - фьючерс на доллар "SiH6". Для того, чтобы получить, например, бид и объем бида по бумаге портфеля и сложить эти значения в переменные, надо написать следующий код:

security s = get_security();
double bid = s.bid();
long long amount_bid = s.amount_bid();

Чтобы получить, например, позицию и сигнал на покупку портфеля надо написать:

portfolio p = get_portfolio();
double lim_buy = p.lim_b();
long long pos = p.pos();

Чтобы проверить, например, что в данный момент по инструменту можно выставлять заявки и в роботе есть активное подключение, получающее стаканы:
security s = get_security();
if ((s.trading_status() & TRADING_CAN_PLACE) && (s.conn_online() & MARKET_DATA_OB_ONLINE))
{
    // TODO place your code here
}

Позицию портфеля можно посчитать самому, разделив позицию главной бумаги портфеля на ее вес в портфеле, вот так:

security_fields sf = get_security_fields();
long long pos = sf.pos() / sf.count();

Для подсчета раздвижки по сделкам портфеля можно использовать формулу:

portfolio p = get_portfolio();
return p.deal("SiH6").price;

Сохранить и загрузить значение из data можно так:

portfolio p = get_portfolio("si");
p.data()["key"] = 10;
double p = p.data()["key"];

Чтобы получить, например, цену последней сделки для бумаги с СПб биржи (получение цены последней сделки по ключу возможно только для СПБ биржи):
security s = get_security("SPB_AGGR_AAPL");
const spb_commons& c = s.spb_common();
double p = c.price_last;

Чтобы, например, задать и потом получить значение "пользовательского поля#0":
portfolio p = get_portfolio();
p.set_uf0(user_value(123));
const user_value& v = p.uf0();
return v.value();

Чтобы найти, например, средневзвешенный бид по первым 10-ти элементам стакана (настоятельно НЕ рекомендуется искать что-то по всему стакану, т.к. стакан меняется часто, то работать ваш код будет долго):

double sum1 = 0, sum2 = 0, avg_bid = 0;
security s = get_security("SPB_AGGR_AAPL");
order_book ob = s.orderbook();
if (ob.is_available())
{
    int i = 0;
    while (i <= 10 && ob.has_next_bid())
    {
        i++;
        std::pair<double, long long> b = ob.next_bid();
        sum1 += b.first * b.second;
        sum2 += b.second;
    }
}
avg_bid = (sum2 != 0) ? (sum1 / sum2) : 0;

Чтобы пройти в цикле по всем бумагам портфеля и вывести имена бумаг в лог:
portfolio p = get_portfolio();
p.restart_sec_iter();
while (p.has_next_sec())
{
    security_fields sf = p.next_sec();
    log_info(sf.sec_key());
}

Чтобы найти, например, сумму объемов активных заявок портфеля по бумаге по заданной цене 100:

security_fields sf = get_security_fields();
order_pool p = sf.orders();
long long amount = 0;
while (p.has_next())
{
    order_item o = p.next();
    if (o.status == RUNNING && fabs(o.price - 100) < 1e-9)
    {
        amount += o.amount_rest;
    }
}

Чтобы найти, например, текущую позицию по бумаге и текущий баланс по валюте:

connection c = get_connection("okex_send_test");
coin_item ci = c.coin("BTC");
sec_item si = c.sec("isolated/BTC-USD-SWAP");
double coin_pos = ci.pos();
long long sec_pos = si.pos();

# 8.10. Примеры использования функций и классов

Пусть имеется портфель с именем "test" и в этом портфеле есть два инструмента: фьючерс на индекс РТС "RIH6" и его опцион call на страйк 70000 "RI70000BB6", позиция по обоим бумагам в портфеле равна 1, а направление торговли у обоих On_by = Buy.

Рассчитаем дельту одного из инструментов портфеля, например, "RIH6". Для этого воспользуемся функцией delta из модуля options. Дельта для фьючерса всегда равна 1, проверим, для этого надо написать:

return S_delta("RIH6");

и выполнить этот код, в результате получим 1. Если хотим рассчитать дельту с учетом ставки рефинансирования, то укажем необязательный параметр rr, например, равный 6.25%:

return P_delta("test");

здесь test - имя портфеля (для портфелей с другими именами нужно писать их имена). Дельта всего портфеля будет равна сумме дельт его инструментов с учетом позиции и направления торговли:

Δportfolio=iportfolioΔi×posi×{1,ifOnbuyi=Buy1,ifOnbuyi=Sell\Delta_{portfolio}=\sum_{i\in portfolio}\Delta_i \times pos_i \times \begin{cases} 1, &\text{if}\enspace On\enspace buy_i=Buy\\ -1, &\text{if}\enspace On\enspace buy_i=Sell \end{cases}

где i - i-тый инструмент портфеля, Δi - дельта i-го инструмента портфеля, posi - позиция i-го инструмента портфеля, On buyi - On buy i-го инструмента портфеля. Величины гамма, вега, тета и ожидаемая волатильность для портфеля рассчитываются аналогично. Функции для их рассчета вызываются аналогично примеру с дельтой. Функция price так же вызывается аналогично delta, но НЕ может быть вызвана для портфеля, может быть вызвана только для финансового инструмента.


Теперь рассмотрим пример использования функций, которые позволяют более "гибко" рассчитывать необходимые величины, так как им на вход можно передать более широкий набор аргументов, но эти функции работают исключительно для опционов и при использовании этих функций необходимо четко знать для опциона call или для опциона put вы хотите рассчитать значение. Например, рассчитаем ожидаемую волатильность опциона "RI70000BB6", в качестве цен опциона и базового актива возьмем их лучшие цены на покупку:

security s1 = get_security("RIH6");
security s2 = get_security("RI70000BB6");
return CIV(s1.bid(), s2.strike(), s2.exp_date(), s2.bid());

Чтобы проверить, что текущее время меньше полудня:
day_time t = get_day_time();
day_time t1(12, 0, 0);
return t < t1;

Пример тaймера на каждые 10 секунд:
static timers::timer t(10000000000LL);
if (t.tick())
{
    // do some operation
}

Пример вызова операции ежедневно не ранее, чем в 10:00:

static timers::day_timer t(10, 0);
if (t.tick())
{
    // do some operation
}

Пример получения и изменения "пользовательских полей" (увеличить значение i-го поля на i):

portfolio p = get_portfolio();
for (int i = 0; i < 20; i++)
{
    double v = std::invoke(uf[i], p).value();// get value
    std::invoke(set_uf[i], p, user_value(v + i));// set value
}
return 0;

# 8.11. Примеры написания Ratio buy/sell formula

При написании формул можно использовать все те инструменты, которые используются в любом из портфелей, также можно использовать доступные значения других портфелей , например, их позиции по бумагам.

Для того, чтобы использовать поле Ratio sell/buy formula необходимо для выбранного инструмента портфеля выбрать Ratio type = Ratio formula. После этого двойным кликом войти в редактор и написать необходимое значение.

Пусть имеется портфель с именем "si" и в этом портфеле есть один инструмент - фьючерс на доллар "SiH6", направление торговли этого инструмента On by = Buy.

Если Ratio sign = "×", то ничего особо интересного с формулами не придумаешь, разве что какой-то хитрый множитель (и для покупки и для продажи), например, такой:

security s = get_security("SiH6");
return sqrt(s.bid());

в таком случае для расчета Buy и Sell будет использован один и тот же множитель, если же вы хотите использовать разные множители надо вписать разные значения в Ratio buy formula и Ratio sell formula, например, так:

security s = get_security("SiH6");
return sqrt(s.bid());
security s = get_security("SiH6");
return sqrt(s.offer());

для покупки и продажи, соответственно.

В таком случае для расчета Buy будет использован квадратный корень из бида, а для расчета Sell будет использован квадратный корень из оффера.

Если же Ratio sign = "+", то вы можете полностью изменить формулу расчета Buy и Sell, для этого надо для начала вычесть те значения, которые используются в данный момент, тем самым обнулив Buy и Sell:

security s = get_security("SiH6");
return -s.bid();
security s = get_security("SiH6");
return -s.offer();

для покупки и продажи, соответственно, а после этого прибавить к Buy и Sell новое значение, например, так:

security s = get_security("SiH6");
double price = s.offer() * 3 + 5;
return -s.offer() + price;

и

security s = get_security("SiH6");
double price = s.bid() * 3 + 5;
return -s.bid() + price;

теперь значения переменной price при расчете каждого из параметров будут новыми значениями для Buy и Sell. Хочется отметить, что без использования Ratio formula такое "хитрое" значение получить бы не удалось.


Рассмотрим еще один пример. Пусть имеется портфель с именем "test" и в этом портфеле есть два инструмента: фьючерс на доллар "SiH6", направление торговли этого инструмента On_by = Buy и он является Is first и фьючерс на индекс РТС "RIH6", направление торговли этого инструмента тоже On_by = Buy (для примера направление не Is first инструмента значения не имеет). Для того чтобы использовать эти два инструмента в одном портфеле нужно привести их цены в пунктах к одной размерности, как известно, доллар торгуется в рублях (1 : pt = 1 rub), а вот индекс торгуется не в рублях, для него 1 pt = 0.02 * $price rub (где $price - это курс доллара в рублях, но это не константа, а динамически изменяющаяся величина). Есть два варианта решения поставленной задачи, оба реализуемы только с использованием Ratio formula и оба приводят к абсолютно одинаковому результату. Вот они:

  1. Для доллара просто зададим Ratio = 1, а вот для индекса РТС выберем Ratio sign = "×", а в Ratio buy formula напишем следующее:

    security s = get_security("SiH6");
    return (0.02 * s.offer() * 0.001);
    

    в Ratio sell formula напишем следующее:

    security s = get_security("SiH6");
    return (0.02 * s.bid() * 0.001);
    

    таким образом при расчете Buy мы будем использовать бид доллара, а при расчете Sell - его оффер, и величину получим в рублях.

  2. Для доллара просто зададим Ratio = 1, а вот для индекса РТС выберем Ratio sign = "+", а в Ratio buy formula напишем следующее (вначале обнулим значение, как в предыдущем примере, а затем зададим новое):

    security s1 = get_security("SiH6");
    security s2 = get_security("RIH6");
    double price = s2.offer() * 0.02 * s1.offer() * 0.001;
    return -s2.offer() + price;
    

    в Ratio sell formula напишем следующее:

    security s1 = get_security("SiH6");
    security s2 = get_security("RIH6");
    double price = s2.bid() * 0.02 * s1.bid() * 0.001;
    return -s2.bid() + price;
    

    теперь значения переменной price и будут новыми значениями (так сказать, со стороны индекса РТС), используемыми для расчета Buy и Sell, соответственно.

# 8.12. Примеры использования индикаторов

Самый простой пример расчета SMA без каких-либо дополнительных настроек (т.е. тайм-фрейм 1 секунда и 10 значений для усреднения):

security s = get_security();// get main security
static indicators::SMA sma;// initialize SMA object as static variable
sma.update(s.mid_price());// try to update SMA value, by adding new price
return sma.value();// get current SMA value

Пример расчета EMA с использованием расписания (TradingDays берутся из портфеля, тайм-фрейм 1 секунда и 10 значений для усреднения):

security s = get_security();// get main security
static indicators::EMA ema({{{7, 0}, {18, 45}}, {{19, 0}, {23, 50}}});// initialize EMA with trading schedule: 7:00-18:45, 19:00-23:50
ema.update(s.mid_price());// try to update EMA value, by adding new price
return ema.value();// get current EMA value

Пример расчета Var с использованием значений пользовательских полей для настройки параметров индикатора и с обработкой отсутствия цен по заданной бумаге:

portfolio p = get_portfolio();// get current portfolio
user_value td = p.uf0();// get TradingDays value from user field 0
user_value len = p.uf1();// get length value from user field 1
user_value tf = p.uf2();// get timeframe value from user field 2
security s = get_security();// get main security

static indicators::Var v({{{7, 0}, {23, 0}}});// initialize Var with trading schedule: 7:00-23:00
v.set_timeframe(tf.value());// set timeframe value from user field 2
v.set_length(len.value());// set length value from user field 1
v.set_trading_days(td.value());// set TradingDays value from user field 0

try// try to catch exception
{
    v.update(s.mid_price());// try to update Var value, by adding new price
}
catch(std::range_error& e)// if there is no mid_price value simply return -1
{
    return -1;
}
return v.value();// get current Var value

Примеры задания TradingDays индикатора:

sma.set_trading_days(WD_MONDAY | WD_TUESDAY);// compute indicator value on Monday and Tuesday only
sma.set_trading_days(WORK_WEEK);// compute indicator value from Monday till Friday
sma.set_trading_days(WHOLE_WEEK & (~ WD_MONDAY));// compute indicator value from Tuesday till Sunday