Пока рыночек пилит, мы тоже попилим чего-нибудь. Данная статься написана по мотивам главы 3 «Time-Series Analysis» из книги «Machine trading» E.Chan.
Все расчеты сделаны на matlab.
Первым делом, берем 5-минутки нашего любимого Сбербанка и разделим на две набора данных, первый набор 01.01.2020-01.01.2024 для тренировки нашей модели ARIMA(p, 0, 0), а второй набор с 01.01.2024г. — 08.11.2024г. для проверки модели.
Для тренировки модели используется средняя цена, т.е. 0.5*(High + Low). Для нахождения оптимального числа p (лаг) на тренировочных данных используем цикл, где перебираются p от 1 до 60 и определяем для каждого лага Байесовский информационный критерий (BIC). Оптимальный лаг будет иметь минимальный BIC.
В нашем случае получилось, что оптимальное p = 41 с такими параметрами:
ARIMA(41,0,0) Model (Gaussian Distribution): Value StandardError TStatistic PValue ___________ _____________ __________ ___________ Constant 0. 0044119 0.003667 1.2031 0.22893 AR{1} 1.2416 0.00038211 3249.4 0 AR{2} -0.31171 0.00067491 -461.86 0 AR{3} 0.050585 0.0010332 48.961 0 AR{4} 0.022658 0.0012971 17.468 2.4899e-68 AR{5} -0.05493 0.001379 -39.833 0 AR{6} 0.04739 0.0014496 32.692 2.0322e-234 AR{7} -0.018811 0.0015392 -12.221 2.3964e-34 AR{8} 0.021583 0.0016458 13.114 2.7354e-39 AR{9} 0.014553 0.0017273 8.4251 3.6049e-17 AR{10} 0.028344 0.0016042 17.669 7.3227e-70 AR{11} -0.016945 0.001519 -11.155 6.7466e-29 AR{12} 0.0011352 0.0011099 1.0228 0.30639 AR{13} -0.014298 0.00072126 -19.823 1.8809e-87 AR{14} -0.013205 0.00091651 -14.408 4.6262e-47 AR{15} -0.005481 0.001332 -4.1149 3.8736e-05 AR{16} -0.0060875 0.0013819 -4.4053 1.0565e-05 AR{17} -0.00308 0.0015478 -1.9899 0.046604 AR{18} 0.022897 0.0015615 14.664 1.0998e-48 AR{19} -0.00057571 0.001496 -0.38484 0.70036 AR{20} 0.0074662 0.0014159 5.2731 1.3415e-07 AR{21} -0.024364 0.001357 -17.954 4.4415e-72 AR{22} 0.032438 0.0012885 25.175 7.5672e-140 AR{23} -0.015657 0.0010254 -15.269 1.2215e-52 AR{24} 0.0031435 0.0008982 3.4998 0.00046566 AR{25} -0.0036452 0.0010939 -3.3323 0.00086145 AR{26} 0.0036641 0.0014248 2.5717 0.010121 AR{27} -0.018374 0.0015304 -12.006 3.2975e-33 AR{28} 0.013843 0.0014963 9.2514 2.2154e-20 AR{29} -0.018975 0.0015305 -12.398 2.6793e-35 AR{30} 0.028452 0.0012616 22.553 1.2418e-112 AR{31} -0.019905 0.0013221 -15.055 3.1791e-51 AR{32} 0.021178 0.0014053 15.07 2.5648e-51 AR{33} -0.018781 0.0015817 -11.874 1.625e-32 AR{34} 0.0053725 0.0016047 3.348 0.00081383 AR{35} -0.020494 0.0013739 -14.916 2.5938e-50 AR{36} 0.030063 0.0015222 19.75 8.0827e-87 AR{37} -0.0025714 0.0016767 -1.5336 0.12512 AR{38} -0.0039149 0.0018077 -2.1657 0.030333 AR{39} 0.0058523 0.0016222 3.6076 0.00030904 AR{40} -0.034314 0.0015485 -22.159 8.5091e-109 AR{41} 0.02384 0.00098174 24.284 2.9093e-130 Variance 0.13025 3.7647e-05 3459.8 0
Система всегда в рынке, и простая как пять копеек. Если прогнозируемая цена больше, чем текущая цена, то входим в лонг, и наоборот, если прогнозируемая цена меньше текущей, то идем в шорт.
И последний шаг, имея модель, строим доходность нарастающим итогом на проверочных данных.
Вот такой красивый график получился на проверочном наборе данных ( OOS), т.е. данные с 01.01.2024г. Проблема только в том, что в реальности, такое торговать не получится, т.к. предполагается, что сделки идут по средним ценам, тогда как после формирования бара вряд ли можно войти по средней цене.
Ну и сам код в конце.
data = readtimetable(..\sber5min.csv'); LOGL = zeros(60,1); P = zeros(size(LOGL,1),1); data.mid = (data.High + data.Low)*0.5; fullset = timerange('2020-01-01 00:00:00','inf'); trainset = timerange('2020-01-01 00:00:00','2024-01-01 00:00:00'); testset = timerange('2024-01-01 00:00:00','inf'); data = data(fullset, :); for p = 1:length(P) model = arima(p,0,0) [~,~,logL] = estimate(model,data.mid(trainset)) LOGL(p) = logL; P(p) = p; end [~,bic] = aicbic(LOGL, P+1, length(data.mid(trainset))); [~,pMin] = min(bic) model = arima(pMin,0,0) fit = estimate(model, data.mid(trainset)); yF = nan(size(data,1),1); data = addvars(data,yF); for t = size(data.mid(trainset)):size(data.mid) [y,~] = forecast(fit, 1, 'Y0', data.mid(t - pMin + 1:t)); data.yF(t) = y(end); end data.deltaYF = data.yF - data.mid; data.pos = zeros(size(data,1),1); data.pos(data.deltaYF > 0) = 1; data.pos(data.deltaYF < 0) = -1; diff1 = diff(data.mid); diff1(size(diff1,1)+1) = 0; data = addvars(data, diff1); data.proc_chg = data.diff1./data.mid; data.proc_profit = data.proc_chg.*data.pos; data.cum_p = cumsum(data.proc_profit); plot(data.cum_p(testset))