В поисках «Годзиллы». Нейросети и прогнозирование котировок на основе биржевых и «внешних» данных


Эта работа вдохновлена статьей «Мечтают ли нейросети об электроденьгах?», где автор без преувеличения талантливо в своей доходчивости объясняет, почему использование искусственных нейросетей на голых биржевых данных не приводит к успеху. Вот особенно, на мой взгляд, удачный отрывок:


«Цена не формирует сама себя… Если рынок выразить как метафоричное озеро, то биржевой график это лишь рябь на воде. Может быть это ветер подул, может камень в воду бросили, может рыбы плеснула, может Годзилла прыгает в 200 километрах на батуте. Мы видим лишь рябь.»

Действительно, пытаться предсказать поведение ряби на следующий день, имея в распоряжении только лишь данные о поведении ряби в прошлом, видится, как минимум, самонадеянным. Не тот масштаб модели. Поведение водной глади формируется за счет множества внешних и внутренних по отношению к водоему факторов. И вот на этом моменте мое любопытство не позволило мне пройти мимо. А что если все-таки поработать с этими факторами? Что получится, если учесть их в модели данных, предназначенных для «кормежки» нейросети?


«Но как же учесть миллионы, если не миллиарды возможных факторов влияющих на наш метафорический водоем?» — спросите вы. А я отвечу, что нас не интересуют ни движение мальков, ни случайно упавший с близлежащей скалы камушек, ни мерное покачивание удочки Дяди Вити-рыбака. Нас интересует Годзилла.


Справедливости ради стоит отметить, что автор вдохновившей меня статьи не исключает возможности увеличения прогностической точности нейросети, если учесть все множество отмеченных факторов. Тем не менее, в упомянутой статье рассуждения об их природе сводятся к пределу детализации — к человеку. А именно, к учету состояния (психического, психологического, физиологического, финансового и т.д.) каждого конкретного участника рынка. Этооо… дорого. Дорого настолько, что неразумно.


Я же в своей работе обращаюсь к гипотезе, что поведение участников торгов предваряют события, которые это поведение определяют. Я предполагаю что в паре «События»/«Поведение пользователей» «События» все же метафорическая собака, а «Поведение пользователей» — метафорический хвост, и собака, как положено, виляет хвостом, а не наоборот. Вот это самое предположение я и предлагаю нам с вами проверить.


Для тех, кто хочет сразу перейти к делу и поэкспериментировать самостоятельно — весь код и данные содержатся на GitHub вот тут.


Начнем


Сформулируем вопрос, на который будем искать ответ, более строго: «Увеличится ли эффективность прогнозирования поведения цены финансового актива нейронной сетью, при включении результатов анализа событийного потока в состав модели данных?»


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


По отношению к анализу новостей, очевидно, разумным решением будет применить методы sentiment analisys, а в отношении транзакционной активности… «Стоп. Что за зверь эта ваша «транзакционная активность»?» — повис вопрос на лице читателя. Тут мы подошли к моменту, когда пора определить наш объект исследования.


Среди всего многообразия активов, для анализа я выбрал биткоин, и на то есть причина. Имя причины — блокчейн. Мне стало до жути интересно — как изменится предиктивная способность сети, если в модель данных мы добавим еще и динамику активности в самой сети биткоин? Сможем ли мы таким образом выявить «подводное течение» в нашем метафорическом водоеме? В конце концов, вдруг Годзилла в лучших традициях классического кинематографа прячется под водой?


Активность справедливо измерять в объемах переданных по сети криптомонет, информация о которых содержится в записях транзакций в блоках, собственно, блокчейна. Транзакция, в свою очередь, состоит из «входов» — это сумма монет, которую определенный кошелек принял, и «выходов» —это суммы монет, которые были (а) отправлены с определенного кошелька, (б) были возвращены на кошелек-отправитель в качестве «сдачи», (в) были уплачены в качестве комиссии майнерам. Поскольку суммы, указанные в качестве выходов транзакций на мой взгляд содержат больше информаци, в качестве мерила активности сети предлагаю использовать именно их.


Итак, прежде, чем отправиться в увлекательное путешествие, заглянем в список того, что должно находится в нашем инвентаре:


  1. Данные о биржевых торгах;
  2. Данные об активности в биткоин-сети;
  3. Преобразованный поток тематических новостей;
  4. TensorFlow + Keras — one love.

Пункт 3 — предмет для описания в ближайшем будущем, а вот со всем остальным мы поработаем сейчас.


Поиск данных


Первое — данные о биржевых торгах. Найти их не должно быть тяжелой задачей. И действительно, быстрая пробежка по первым строкам результатов Google привела меня на investing.com. Здесь забираем CVS с максимальной глубиной во времени и дневной детализацией.


Пометка на полях: пользоваться рекомендую данными Investing.com Bitcoin Index, поскольку автоматически рекомендуемый Bitfinex Bitcoin US Dollar содержит бессовестные пропуски данных недельных масштабов.


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


Из всего представленного перечня датасетов, нам понадобятся:


  • bh.dat.gz — содержит хэш-суммы блоков. Формат: идентификатор блока (blockID), хэш-сумма (hash), временная метка записи блока в блокчейн (block_timestamp), количество транзакций в блоке (n_txs);
  • tx.dat.xz — содержит информацию о транзакциях. Формат: идентификатор транзакции (txID), идентификатор блока, в который записана транзакция (blockID), количество входов (n_inputs), количество выходов (n_outputs);
  • txout.dat.xz —содержит информацию о выходах для каждой транзакции. Формат: идентификатор транзакции (txID), порядковый номер (output_seq), идентификатор адреса, куда отправляется выход (addrID), объем отправленных монет (sum).

Сопоставим данные файлов друг с другом следующим образом:


Код для сопоставления таблиц
import pandas as pd

#Loading bh.dat
mit_data = pd.read_table('.../bh.dat',
                         header=None, names=['blockID', 'hash','block_timestamp', 'n_txs'])
mit_data['block_timestamp'] = pd.to_datetime(mit_data['block_timestamp'], unit='s')
#Loading info about output of transactions
out_txs_all = pd.read_table('.../txout.dat',header=None,
                           names=['txID', 'output_seq','addrID', 'sum'])
#Loading info transaction overview dataset
mapping_dataset = pd.read_table('.../tx.dat', #The path to the tx.dat file
                                header=None, names=['txID', 'blockID','n_inputs', 'n_outputs'])
#Dropping needless columns in outputs dataset and summing up outputs values groupping them by 'txID'
out_txs_all.drop('output_seq',axis=1,inplace=True)
out_txs_all.drop('addrID',axis=1,inplace=True)
out_txs_all = out_txs_all.groupby('txID').sum().reset_index()

#Dropping needless columns in transactions dataset and adding outputs values
mapping_dataset.drop('n_inputs', axis=1,inplace=True)
mapping_dataset.drop('n_outputs', axis=1,inplace=True)
mapping_dataset['sum_outs'] = out_txs_all['sum']

#Now we can dropp 'txID' column since it's useless now.
#Then we group mapping_df by blockID and addup all sums to get btc_sum per particular block
mapping_dataset.drop('txID', axis=1, inplace=True)
mapping_dataset=mapping_dataset.groupby('blockID').sum().reset_index()

#Prepare mit_data to the next manipulations
mit_data.drop('hash', axis=1,inplace=True)
mit_data.drop('n_txs', axis=1,inplace=True)

#Now we just can get dates from sliced block_timestemp dataset and concatinate
#it with mapping_df since they have equals sizes and contains similar blocks.
mapping_dataset['Date'] = mit_data['block_timestamp']
mapping_dataset['sum_outs'] = mapping_dataset['sum_outs'].apply(lambda x: x/100000000) #Getting amount of bitcoins instead of satoshies

#Finally we are making a csv file
mapping_dataset.to_csv('../filename.csv', index=False) 

На выходе получаем таблицу суммарного объема выходов, записанных в блокчейн биткоина с 17.07.2010 по 08.02.2018. И вроде все чудесно, только покоя не дает тот факт, что данные ограничиваются 08 февраля 2018 года. А ведь дальше занимательный период волатильности, начавшегося как раз в феврале 2018 года. А волатильность — это источник информации. Разбрасываться информацией — кощунство. Потому обращаемся к API blockchain.com, потому как более удобного варианта я не нашел.


Получаем недостающие данные следующим образом:


Код для парсинга блоков через API Blockchain.com
import requests
import json
# Makeing timeline in unix time
limit_day = pd.to_datetime('2018-02-09')
datelist = pd.date_range(limit_day, periods=733).to_list()
date_series = pd.DataFrame(data=(datelist), columns=['Date'])
dt = pd.DatetimeIndex(date_series['Date']).astype(np.int64)//1000000
unix_mlseconds_lst = dt.to_list()

#Getting blocks hash list with timestamps
blocks_lst = []
for j in unix_mlseconds_lst:
    request = requests.get('https://blockchain.info/blocks/'+str(j)+'?format=json')
    parse_result = json.loads(request.content)
    blocks_lst.append(parse_result['blocks'])

#Parsing json content for the final dataset
blockID = []
hashID = []
timestamp = []
for d_list in blocks_lst:
    for dictionary in d_list:
        blockID.append(dictionary['height'])
        hashID.append(dictionary['hash'])
        timestamp.append(dictionary['time'])

#Makeing additional bh-dataset
additional_bh = pd.DataFrame(data=(blockID,hashID,timestamp)).T
additional_bh.columns=['blockID','hash','timestamp']
additional_bh['timestamp']=pd.to_datetime(additional_bh['timestamp'], unit='s')

#Getting info about additional outputs
dates_out_sums = {}
for indx in range(len(additional_bh)):
    request = requests.get('https://blockchain.info/rawblock/'+str(additional_bh['hash'][indx])) #Getting all info about block by it's hash
    parse_result = json.loads(request.content)
    block_outs_sum=[]
    for i in parse_result['tx']: #Running through all txs to sum up all outputs
        intermid_out_sum_values = []
        for j in i['out']:
            intermid_out_sum_values.append(j['value'])
        block_outs_sum.append(sum(intermid_out_sum_values))
    dates_out_sums[bh['timestamp'][indx]] = sum(block_outs_sum)

#Making dataframe of additional outputs
dates_out_sums_lst = dates_out_sums.items()
out_txs = pd.DataFrame(dates_out_sums_lst, columns=['Date', 'out_sums'])
out_txs['out_sums']=out_txs['out_sums'].apply(lambda x: x/100000000) #Making a series of bitcoins instead of satoshies
out_txs.to_csv('.../Data/additional_outs_dated(2018-02-09_2018-04-28).csv', index=False)

Пометка на полях: качать информацию с blockchain.com оказалось делом, мягко говоря, небыстрым. В процессе работы над статьей, наряду с лопнувшим терпением, я получил данные из 11949 дополнительных блоков, что соответствует двум дополнительным месяцам. Я посчитал, что этого будет достаточно.


Теперь объединяем полученные датасеты, и мы готовы к этапу предварительной обработки информации.


Data pre-processing


Первое, что бросается в глаза, это формат данных нашего биржевого датасета.



Кроме того, что данные приведены в текстовом формате, выгрузка совсем некстати содержит запятые и разнородные ‘K’, и ‘M’ в значениях объемов, что не дает конвертировать данные во float-формат стандартными методами. Дотошное гугление рыночных данных с пристрастием не дало результатов такого же широкого временного диапазона. Что ж. Регулярные выражения Python, дайте мне силы!



Код конвертера str во float
import re
import pandas as pd

def strtofloatconvert(data):

    #Converting series to list
    price_lst = data['Price'].to_list()
    open_lst = data['Open'].to_list()
    high_lst = data['High'].to_list()
    low_lst = data['Low'].to_list()
    vol_lst = data['Vol.'].to_list()
    change_lst = data['Change %'].to_list()

    #Separating str by ',' sign exept Volume strings. It's got anoter
    #format, like '294.8K' or '12.9M'. Volume we convert lower
    sprt_prices = []
    sprt_open = []
    sprt_high = []
    sprt_low = []
    sprt_p = []
    sprt_o = []
    sprt_h = []
    sprt_l = []

    for price in price_lst:
        sprt_p = re.split(r',',price)
        sprt_prices.append(sprt_p)
    for open_p in open_lst:
        sprt_o = re.split(r',',open_p)
        sprt_open.append(sprt_o)
    for high in high_lst:
        sprt_h = re.split(r',',high)
        sprt_high.append(sprt_h)
    for low in low_lst:
        sprt_l = re.split(r',',low)
        sprt_low.append(sprt_l)

    #Adding splitted values together and converting them to float
    add_p = []
    add_o = []
    add_h = []
    add_l = []
    add_v = []
    add_ch = []

    for p in sprt_prices:
        if len(p) == 2:
            a = p[0]+p[1]
            a = float(a)
            add_p.append(a)
        else:
            a = p[0]
            a = float(a)
            add_p.append(a)
    for o in sprt_open:
        if len(o) == 2:
            a = o[0]+o[1]
            a = float(a)
            add_o.append(a)
        else:
            a = o[0]
            a = float(a)
            add_o.append(a)
    for h in sprt_high:
        if len(h) == 2:
            a = h[0]+h[1]
            a = float(a)
            add_h.append(a)
        else:
            a = h[0]
            a = float(a)
            add_h.append(a)
    for l in sprt_low:
        if len(l) == 2:
            a = l[0]+l[1]
            a = float(a)
            add_l.append(a)
        else:
            a = l[0]
            a = float(a)
            add_l.append(a)

    #Working with zeroes in 'Vol.' in str_flt because it does not matter whether we put None or zero in empty space.
    #Pandas will convert None into NaN wich is kind of float 'number'. It will not respond to pandas 'isnull()' function.
    for v in vol_lst:
        if v == '-':
            add_v.append(0)
        else:
            exam = re.findall(r'K',v)
            if len(exam)>0:
                add = re.sub(r'K', '',v)
                add = float(add)
                add *= 1000
                add_v.append(add)
            else:
                add = re.sub(r'M', '',v)
                add = float(add)
                add *= 1000000
                add_v.append(add)
    for i in change_lst:
        add = re.sub(r'%', '',i)
        add = float(add)
        add_ch.append(add)

    #Putting all lists above to the DataFrame
    test_df = pd.DataFrame(data=(add_p, add_o, add_h, add_l,
                                        add_v,add_ch)).T
    test_df.columns = ['Price', 'Open', 'High', 'Low', 'Vol.', 'Change%']
    return test_df

Другое дело.


Посмотрим на хвост полученного нами датафрейма.



267 элементов датасета не содержат информации о динамике изменения стоимости. Удалим их повышения общей информативности данных ради.


Теперь, поскольку мы собрались все же прогнозировать поведение цены в будущем, нам нужно организовать данные так, чтобы цена в момент времени Т соответствовала набору признаков T-n, где n — это дальность нашего горизонта прогноза. Предлагаю попытаться заглянуть в будущее для начала на один день вперед. Для этого мы удаляем последнее значение из перечня цен закрытия и первую строку соответствующих признаков.


price = test_df.pop('Price')
price = price.drop(price.index[-1])
test_df = test_df.drop(test_df.index[0])

test_df.index = np.arange(len(test_df))
test_df = pd.concat((price,test_df), axis=1)

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


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


PRACTICE_DS_SIZE = 45
later_testds_for_plot = test_df.iloc[:PRACTICE_DS_SIZE]
test_df = test_df.iloc[len(later_testds_for_plot):]
test_df = test_df.reset_index(drop=True)

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


timestamps = test_df.pop('Date')
sum_outs = test_df.pop('out_sums')

Делим датасет на тренировочную и тестовую выборки и извлекаем зависимую переменную — цену закрытия:


# Making train/test split
train = test_df.sample(frac=0.8, random_state=42)
test = test_df.drop(train.index)

#Setting targets
train_labels = train.pop('Price')
test_labels = test.pop('Price')

Полученные данные нормализуем.


def norm(train_data, data):
    #Getting overall statistics
    train_stats = train_data.describe()
    train_stats = train_stats.transpose()

    #Normalising data
    normalized_data = (data - train_stats['mean']) / train_stats['std']

    return normalized_data

Теперь проверим насколько эффектным будет обычный многослойный перцептрон, если ему скормить только лишь биржевые данные.


Тестирование нейронной сети


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


Код конфигурации нейронной сети
def build_model():
    model = keras.Sequential([
    layers.Dense(32, activation='relu', input_shape=[len(train.keys())]),
    layers.Dense(32, activation='relu'),
    layers.Dense(32, activation='relu'),
    layers.Dense(16, activation='relu'),
    layers.Dense(1)
    ])
    optimizer = tf.keras.optimizers.RMSprop(0.001)
    model.compile(loss='mse',
                optimizer=optimizer,
                metrics=['mae', 'mse'])
    return model
model = build_model()
model.summary()

EPOCHS = 500

# Patience parameter describes epoch amount testing on improvement
early_stop = keras.callbacks.EarlyStopping(monitor='val_loss', patience=10)

model.fit(normed_train_data2, train_labels2, epochs=EPOCHS,
                    validation_split = 0.2, verbose=0, callbacks=[early_stop, PrintDot()])


PrintDot() — коллбэк отвечающий за вывод красивых точек в процессе обучения модели. Позаимствовал его из официальной документации по TensorFlow. Очень уж он мне понравился. Выглядит он незамысловато:


class PrintDot2(keras.callbacks.Callback):
    def on_epoch_end(self, epoch, logs):
        if epoch % 100 == 0: print('')
        print('.', end='')

Задача его — рисовать точки, отражая эпохи.
Что ж, запустим тренировку нашей модели и посмотрим на результат.



Проверим эффективность модели на тестовой выборке.


loss, mae, mse = model.evaluate(normed_test_data, test_labels, verbose=2)

Результат: 506/506 — 0s — loss: 36201.9241 — mae: 66.5216 — mse: 36201.9219


MSE в 45430.1133 долларов оставляет нас со среднеквадратическим отклонением в 190.27 долларов. Многовато.


Теперь проведем обучение и тестирование сети на данных, содержащих выходы транзакций.



loss, mae, mse = model.evaluate(normed_test_data2, test_labels2, verbose=2)

Результат: 506/506 — 0s — loss: 24382.0926 — mae: 48.5508 — mse: 24382.0918


MSE в 24382.0918 долларов значит, что среднеквадратическое отклонение сократилось до 156.15 долларов, что, конечно, не сказка, но улучшение налицо.


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


Код для формирования графиков
actual_price = later_testds_for_plot.pop('Price')
actual_dates = later_testds_for_plot.pop('Date')
normed_practice_data = norm(train, later_testds_for_plot)
practice_prediction = model.predict(normed_practice_data).flatten()

actual_price2 = later_testds_for_plot2.pop('Price')
actual_dates2 = later_testds_for_plot2.pop('Date')
normed_practice_data2 = norm(train2, later_testds_for_plot2)
practice_prediction2 = model.predict(normed_practice_data2).flatten()

fig = plt.figure(figsize=(15,6))
ax1 = fig.add_subplot(121)
ax2 = fig.add_subplot(122)

ax1.plot(actual_dates,actual_price, label ='actual btc price')
ax1.plot(actual_dates,practice_prediction, label ='predicted btc price')
ax1.set_title('BTC Close Price Prediction with only Exch Data')
ax1.legend()

ax2.plot(actual_dates2,actual_price2, label ='actual btc price')
ax2.plot(actual_dates2,practice_prediction2, label ='predicted btc price')
ax2.set_title('BTC Close Price Prediction with Outs')
ax2.legend()


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


Выводы


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


Этот вольный эксперимент, безусловно, не обнадеживает в части создания финансового «Демона Лапласа» (мы ж ведь все-таки разумные люди), но дарит определенный оптимизм в отношении моделирования хотя бы небольшого такого «бесенка».


Ресурсы


AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 45

    +4
    Увеличится ли эффективность прогнозирования поведения цены финансового актива нейронной сетью, при включении результатов анализа событийного потока в состав модели данных?»

    Нет не увеличится.
    Причин несколько. Одна из главных: индукция не работает для системы финансовых активов.
    В общем случае, поведение сложной реальной системы невозможно предсказать.
    1. Обычно не учитываются сложные связи между элементами модели.
    Например, важны связи между элементами системы. Но их определить невозможно по имеющейся информации. Восстановление структуры системы по ее отклику всегда дает неограниченное количество возможных вариантов структуры системы.
    2. Обычно используются упрощенные аналитические модели 1 порядка. Для задачи о финансовых рынках такие модели не применимы. Совсем неприменимы.
    А аналитически (через логику и рассуждения) построить можно только простейшие модели структуры системы первого порядка. Реально на поведение такой сложной системы влияют события более высоких порядков.
    3. Учитывается статическая структура системы, а в реальности она динамическая. Причем изменяются элементы системы, их связи, поведение элементов.
    И это только про статические модели системы. Еще сложнее построить структуру моделей в динамике (изменение во времени).
    4. Не учитываются эффекты возрастания сложности (и потеря адекватности) модели системы при введении новых параметров.
    Использование значимых параметров — тоже плохой вариант. Сложность поведения модели системы при добавлении одного параметра может вырасти на несколько порядков. Причина: нелинейные связи или нелинейное поведение хотя бы нескольких элементов.

    Это только самое простое.
    Самое главное: зачем придумывать и развивать неверные направления моделирования? Эти вопросы уже лет 30 отработаны, проверены — не работает. Даже на нейросетях и прочем хайпе — не работает. Неверный подход. Это как измерять температуру «пространства» в космосе. Можно использовать разные методы, получить результаты от -150 до +4 С. Но непонятно температуру чего измеряют?
    Или использование градусника для измерения скорости. Не тот инструмент!!!
    Рекомендую начинать работу в этом направлении хотя с анализа уже использованных методов для этой темы. Особенно доходчиво объясняется эта тема у моего любимого писателя — Николаса Талеба. В его серии книг «Инсерто» («Одураченные случайностью» и далее).
    Можно начать с Каннемана «Думай медленно, решай быстро». Тогда становится понятно, почему именно большинство людей почти всегда неправильно подходят к моделированию сложных систем. Так устроен разум человека, особенно если нет охоты мыслить. Тогда используется система 1, которая находит быстрые, простые, логичные, очевидные неправильные решения.
      +2

      Спасибо за рекомендованную литературу.


      Было бы странно не согласиться с приведёнными тезисами. Однако путь на «плечи атлантов» необязательно должен идти исключительно через теории, часто возводимые некоторыми в степень догм. Бывает просто-напросто увлекательно убедиться на практике, что все работает именно так, как теорией предусмотрено. А если повезёт — в процессе такой «проверки мира на прочность» ещё и что-нибудь новенькое найдётся.


      Мое копье, несмотря на незначительный положительный результат, которого удалось достичь, как и тысячи копей до этого, осталось сломаным на этом поле битвы. Но это не повод принципиально обходить поле битвы стороной.
      Я получил колоссальное удовольствие просто от самого процесса исследования. Быть может кто-то, найдёт для себя нечто полезное в моей работе. Быть может (и я на это очень надеюсь), кто-то вдохновится ей пойдёт дальше, добившись куда более значительных результатов. И речь не обязательно про прогнозирование котировок.


      В моём представлении практика, определяемая неудержимым любопытством — существенная часть прогресса. А к прогрессу хочется быть причастным.

        –2
        «Мое копье, несмотря на незначительный положительный результат, которого удалось достичь, как и тысячи копей до этого, осталось сломаным на этом поле битвы.»
        Надо было реально показать «незначительный положительный результат», тогда бы это вранье прошло незамеченным.
          0

          Я далёк от механики нейросетей, но изучал довольно плотно технику торговли таких финансовых инструментов. Вы идёте не тем путем. Биткоины это чисто скальперский инструмент. Более фундаментальный и прогнозируемый же инструмент этофьючерс на индекс РТС с его открытым интересом и его производными (число сделок на открыиме/закрытие и суммарная позиция покупателец/продавцов). А так же его поводыри. Это Сишка и MOEX10.

            0

            Так же, помимо перечисленного, еще более важно учитывать фишки стаканной торговли. Вот тут по люди добиваются успеха. Я мог бы вам разложить это все по полочкам и поставить задачу на что подробно надо смотреть. Там есть ещё ньюнсы по технике.

              0
              Ознакомлюсь с большой радостью) Всегда открыт к конструктивной дискуссии. Если не затруднит — напишите мне в личку.
          0
          ОФФ.
          использование градусника для измерения скорости. Не тот инструмент!!!

          Смотря как использовать. Есть датчики скорости потока воздуха для вентиляции где для определения скорости используют термометры!.. Вот даже статья была с описанием есть: habr.com/ru/company/efo/blog/280031
          0

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


          Обычные объемы торгов более показательны.


          Ну и многослойная полносвязная сеть, имхо, не очень подходит для анализа временнОго ряда. Для таких задач больше подходят рекуррентные сети.


          Их относительно дешевле обучать, они меньше страдают от затухания градиента, при этом качество работы и анализа будет выше.


          Однако, боюсь, в конечном счете это сведется обратно к кормлению сети свечами с ожиданием угадывания t+1 свечи.

            0
            О! Да это же сам автор вдохновившей меня статьи! Приятно находиться в вашей компании, сэр) *снял шляпу в приветственном жесте

            Что касается выходов сети биткоина, как плохого выбора для аналитики по той причине, что торговые сделки на бирже не связаны с транзакциями сети — здесь я позволю себе подискутировать. Я исходил из предположения, что участники биржевых торгов представляют собой большое разнообразие. Это не только спекулянты в чистом их виде, но и представители обменников, активные трейдеры на таких ресурсах, как localbitcoins, платежные агрегаторы и иные, с позволения, «пространственные арбитражники». Все они вынуждены калибровать свои позиции при торговле со своими клиентами. Эти операции находят свое отражение как в транзакциях в сети биткоина, так и, частично, в биржевых торгах.
            Если под этим углом посмотреть на работу, то можно сказать, грубо, что мы пытались выяснить насколько активность таких участников торгов влияет на биржевой курс актива.

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

              Ну, исследование, есть исследование. А отрицательный результат тоже результат.

            0
            Автор ответьте, пожалуйста, а сколько фич было на входе при обучении нейросети? Т.е. сколько элементов во входном векторе и сколько самих векторов???
              0
              Нашел на вашем гитхабе следующую инфу:
              1. всего данных для обучения — 2500
              2. в каждом по 5 фич.
              Но, мне кажется с такими данными и такой конфигурацией нейросети невозможно получить прогноз который вы рисуете. Или я не прав?
              0
              И еще вопрос, в статье упущена главная инфа — какие данные и за какой период подавались нейросети для обучения? В приведенной табличке цена имеет только один знак после запятой, как такое может быть??? Прогноз с такой же точностью?
                0
                Автор, по структуре нейросети проясните, пожалуйста. Я правильно понял, что в ней 5 слоев из которыз 4 по 32 нейрона, один 16 и выходной 1?
                Какая активация у выходного слоя?
                  0
                  В табличке «датафрейма» странные данные в колонке «Change%», они не связаны с другими колонками, это изменение чего?
                    –2
                    График прогноза просто потрясающий! Невероятно крутой прогноз да еще и с шагом 1 день!!! Только что бы можно было поверить в эту сказку надо ответить на главный вопрос — что скармливалось нейросети?
                    Если это секретное know-how тогда хотябы укажите за какой период и какое количество фич в каждом векторе.
                      0
                      Уточню вопрос. Вы на гитхабе показываете табличку с входными данными. Вы их построчно скармливали сети для обучения или объединяли в пулы? Вопрос простой, но важный, по ответу можно будет понять выбор конфинурации нейросети.
                      0
                      Внимательно изучил ссылку на гитхаб, вот инфа которая спрятана за демагогией:
                      1. для работы используется самая простая нейросеть («Hello world»), да еще и неправильно сконфигурированная;
                      2. входные данные — четыре цены дневной свечи + объем + изменение цены (более примитивный набор трудно придумать);
                      3. обучние на 2500 примеров.
                      4. прогноз на 1 свечу.
                      В результате фантастический по точности прогноз показанный на графике!

                      Хабр! Как здесь может быть такое вранье???
                        0
                        Добрый день.
                        Приятно потрясен, что статья вызвала у вас такой активный отклик) Пройдемся по пунктам.

                        1. Представленная нейросеть ни в коем случае не претендует на статус «state-of-art». И если вы готовы поделиться своими взглядами в отношении более, по вашему мнению, грамотной ее конфигурации, я буду рад с ними — взглядами — ознакомиться.
                        2. Входные данные — дневные цены Open, Close, High, Low, объемы торгов, дневное изменение цены и, что немаловажно, информация об объемах выходов транзакций сети биткоин. Ну, вы же читали статью? Мы там «Годзиллу» искали.
                        3. Все верно.
                        4. Если быть более точным — прогноз на цену закрытия следующего дня.

                        В результате суровый лик реальности не оставил никаких шансов на фантастику. Прошу, ознакомьтесь с результатами работы внимательнее. Они далеки от фантастических.

                        Ну а что касается «вранья» — вы, следуя вашим заявлениям, уже исследовали проект на GitHub. Думаю, вам не составит труда запустить представленный там код собственноручно и воочию убедиться в воспроизводимости результатов.
                          –2
                          Опять демагогия ))
                          "Представленная нейросеть ни в коем случае не претендует на статус «state-of-art»" — она даже не претендует на работоспособность.
                          Ваша сеть + входные данные не могут дать такой результат как на графике, даже близко!
                          Более того, такая конфигурация не покажет признаков обучаемости.
                            +1
                            Запустите уже и узнаем :) Всем интересно.

                            Но соглашусь, что происходящее на графике больше похоже на глубокую переобученность.
                              –2
                              переобученность не может отражаться на этом графике, вы тоже эксперт?
                                +2
                                Да запустите уже у себя и напишите статью-ответ. С анализом. С выводами. Разве это не интереснее, чем наезды в комментариях? Ну правда, раз уж занялись всерьез этим вопросом.
                                +2
                                Это не переобучение. Это просто случайность. Возьмите 100 случайных чисел, постройте их график. Потом возьмите эти 100 случайных чисел и случайно прибавьте к каждому число, например, от -5 до 5. И постройте график новых 100 чисел поверх старых. Графики точно так же будут близки друг к другу. И именно это и делает модель — предсказывает следующую точку по одной предыдущей. Не удивлюсь, что простая baseline-модель «завтра цена будет как сегодня» дала бы большую точность. Короче, модель и рассуждения совершенно мимо.
                                Но за старание можно плюсик поставить. Чтобы не просто критиковать, то могу посоветовать смотреть на кривые обучения и давать их в качестве иллюстрации, а не табличку с последними 5 эпохами, а также чуть лучше освоить pandas — читать код больно, многие вещи, которые сделаны в 5+ строк кода делается одной.
                                  +1
                                  И именно это и делает модель — предсказывает следующую точку по одной предыдущей.

                                  Посмотрел внимательнее. Согласен. До этого по-диагонали мельком пробежал, каюсь.
                                    0
                                    За конструктив — спасибо.
                                    Соглашусь. Не сравнить результаты с «наивным предиктором» — кощунственное упущение. Исправлюсь.
                              0

                              Я как-то подобным баловался, и точность прогноза следующей свечи получилась просто невероятная, 99.99% или в районе того. Когда порадовался и распланировал, на что буду тратить миллиарды, решил всё же разобраться. Оказалось, что я нормировал N-1 значений по среднему из N значений (последнее из которых и должна была предсказывать сеть). Сеть научилась выводить это значение из получающегося отклонения от истинного среднего между N-1 значением. Но фокус занятный получился, который ещё раз напомнил, что нейросеть — это просто такой инструмент, который (как и традиционные программы) делает не то, что ты хочешь, а то, что ты ей прикажешь. В общем, будет срезать углы максимально, лишь бы достичь результата, но необязательно тем путём, который ты ожидаешь.

                              0
                              Сложный проект. Самого факта публикации чего-то подобного с большой вероятностью говорит о том, что в конце статьи у автора не получилось заработать свои миллионы. Иначе не публиковалось бы. Но это не значит, что надо сдаваться. Хотя я бы порекомендовал забить на нейросеть, обычный технический анализ в совокупности со статистикой даст результаты быстрее.
                                0

                                Интересно накинуть sentiment-analysis на все популярные новостные ленты о блокчейнах и поймать хоть какую-то корреляцию с ценой. Пытался это делать своей биологической нейросетью — ничего не ловится, вернее, изменение цены всегда влияет на новостной тон лент, но не наоборот.

                                  +1
                                  изменение цены всегда влияет на новостной тон лент, но не наоборот.

                                  Ага. В этом и прикол: выходные данные (курс чего-то завтра) и входные данные (курс текущий, аналитические параметры) взаимозависимые в реальности. То есть в реальности всегда идет не действие, а взаимодействие. Если это не учитывать — то возникает ошибка номер 3.
                                  Ошибка номер 2: моделирование в статике, а не в динамике.
                                  Ошибка номер 1: не понимание разницы между мало-мерной репрезентацией системы и много-мерной реальной системой.
                                  Ошибка номер 0: применение математического аппарата для построения моделей реального мира без доказательства адекватности этого аппарата решаемой задаче. Кто и почему решил, что для задачи моделирования финансовых систем можно применять статистику, вероятностные модели, да и сами нейросети?
                                  То, что статистику (и эконометрику) нельзя применять для такого класса задач доказано более 50 лет назад, Бенуа Мандельбро. И потом были сотни исследований.
                                  Вероятностные подходы — финансисты и экономисты не понимают их и не умеют ими пользоваться. Пример: вероятность по ансамблю (группе) данных путают с вероятностью по времени.
                                  Про метрологию (что меряем? как? каковы оценки достоверности данных?) тоже никто не думает.
                                  Нейросети для анализа и синтеза временных рядов применять можно. Только результат будет в рамках этих временных рядов. Прогноз (по сути сложная корреляция) имеющихся данных по курсу биткойна и уровня осадков в Монголии может быть всегда найдена. Причем чем больше выборка — тем более вероятность такой корреляции. Но она ничего не значит, она случайная.
                                  Прогноз курса (и поведения сложных систем) невозможен! Никак, никакими методами. От слова «совсем». Даже если научится решать n-полные задачи. Даже если применять всю вычислительную мощность всех компьютеров в мире.
                                  Не тот инструмент для этой задачи.
                                  Это не я все придумал! Я только привел несколько соображений от Николаса Талеба. Прочитайте! И не «делайте людям нервы»…
                                  +1

                                  Интересно сравнить ваш предиктор vs martingale модель:
                                  close{t+1} = close{t} + \varepsilon_{t}
                                  Т.е. оценка цены закрытия следующего дня — цена закрытия текущего дня плюс шум. Подозреваю он будет точнее, чем все эти навороты с нейросетями)

                                    0

                                    Представьте, что вы нашли алгоритм устойчивого получения высокой доходности с рынка. Фактически, это денежная машина. Какая вероятность того, что вы броситесь этим делиться?

                                      0

                                      Общей концепцией, в общем-то можно поделиться. Идея не стоит ничего. Концепция — ничто без реализации. А реализация у таких вещей, обычно, сложнее, чем представленный в статье код.

                                        0

                                        Зачем? Какая мотивация показать, где копать?

                                          +1

                                          А что в этом плохого? Кроме личного шкурного интереса есть же еще интерес общий, академический, так сказать.

                                            0

                                            Ага, отдать деньги другим.

                                              0
                                              У вас, случайно, нет ответа на вопрос, зачем некоторое время назад Тесла открыла все свои патенты по электромобилям для всех желающих, включая конкурентов?
                                                0

                                                Есть. Только это совсем другое. Хотя бы то, что патенты изначально открыты… Впрочем, я не могу помешать верить в чудо

                                                  0
                                                  Впрочем, я не могу помешать верить в чудо

                                                  Дело не в этом. Просто мир сложнее, чем вам представляется.
                                        +2
                                        Представьте, ...

                                        Представил. Это не сложно.
                                        Сложнее проверить, что мое представление как-то соответствует реальности.
                                        Если программа работает в автоматическом режиме значительное время, без вмешательства человека — значит действительно это алгоритм.
                                        Если же надо периодически что-то «допиливать» руками — тогда это не алгоритм, а еще один костыль для трейдера.
                                        Кстати, если кто-то используя программу получил один раз доход — это не доказательство корректной работы. Просто обычно нет информации, что 1023 человека из 1024 получили убытки используя эту программу. Случайное предсказание из 10 шагов дает такой результат.
                                        Схема известная: посылаете 1024 человекам 512 предсказаний «рост» и 512 «падение».
                                        В реальности курс упал. Повторяете то же самое для тех 512, кому прислали «падение» на 1 шаге. И так все 10 раз подряд. В конце остается один человек, которому вы точно предсказали 10 раз рост или падение курса биткойна. Продаете ему свою программу: он будет уверен, что она работает, ведь 10 раз точно — это не случайность! Не случайность для него.
                                        Профит.
                                        0
                                        Прежде чем бросаться нейросетями, всегда нужно пробовать простые линейные модели. Они легко интерпретируются, так что вы легко выясните, что лучше всего цена на сегодня прогнозируется ценой за вчера, а все остальные данные модели и нафик не нужны.
                                        Если рассматривать не цены на рынке, а какие-то другие данные из разряда «временные ряды», то там ещё могут быть всякие интересности типа сезонности и там можно строить модели типа ARIMA/SARIMA/ARIMAX и т.д., которые выводят таргет за сегодня через таргет и его усреднение за некие предыдущие периоды. На биржевых котировках эти модели, к сожалению, не работают от слова совсем.
                                          +1
                                          Здравствуй Хабр! Читаю тебя около 4 лет.
                                          Ув. автор статьи, Вы вообще не поняли о чем пишет Ваш оппонент в замечательной и остроумной статье «Мечтают ли нейросети об электроденьгах?». Суть статьи в последнем пункте раздела заключение (для Вас укажу конкретно пп.11 ).
                                          Ну и для тех кто все равно не понимает, что же можно исследовать в фин. временных рядах — там очень мало нужных данных! Все что там есть это проверка Вашей стратегии, а не предсказание будущего!
                                          Специально для AnkyDu77 попробую «объяснить на пальцах»… отстранимся от мира финансовых воротил и вернемся в добрые игры, пусть это будут шахматы.
                                          AnkyDu77, Вы пытаетесь с помощью нейросетей угадать какой сделает следующий ход соперник, согласитесь, что так не работают шахматные программы!
                                            0
                                            Признаться, я не эксперт в архитектуре шахматных программ. Тем не менее, я попытаюсь предположить как выглядит ключевой компонент логики, лежащей в основе подобного ПО.

                                            Шахматы — игра с фиксированным набором правил и очень большим, но все же конечным количеством возможных комбинаций ходов. Количество комбинаций, ведущих в выигрышу или проигрышу под влиянием стратегий игроков друг на друга с течением времени игры существенно сокращается. Это открывает возможность к построению выигрышной стратегии по принципу:

                                            «Если я схожу таким образом, это оставляет для моего оппонента такой-то ряд возможностей. Если будет реализована возможность (а) я схожу следующим образом, что для оппонента откроет ряд возможностей (а1), если возможность (б), то у оппонента будут возможности (б1)… », и так далее.

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

                                            Более того, если мы будем регистрировать набор возможных стратегий для каждого состояния доски во время игры, мы получим не что иное, как многомерный временной ряд, анализ которого как раз имеет своей целью построение выигрышной стратегии.
                                            Это к тому, что временной ряд временному ряду — рознь. Fell-x27 в своей — здесь я с вами абсолютно согласен — замечательной статье говорил об анализе одномерных временных рядов, построенных на основе значений цен актива за предыдущие периоды. Я в своей работе предпринял попытку поэкспериментировать с составом анализируемых данных. Этот состав описан в статье. Там же приведены и результаты.

                                            При этом с вами сложно не согласиться относительно небольшого количества полезных данных, содержащихся в общедоступных источниках. Чтобы найти существенную связь между данными в них содержащимися и процессом ценообразования, нужно изрядно попотеть, применяя часто нетривиальные подходы. А если принять во внимание, что рынок система динамичная — те правила, что работают сегодня, могут утратить свою актуальность завтра — задача становится многократно сложнее, чем блестящая игра в шахматы. Но именно по этой причине рассматриваемая задача становится такой привлекательной)
                                              0
                                              Просто замените строго детерминированную игру «шахматы» на стохастическую, но, при этом, зависящую от навыка игрока игру «покер» и все встанет на места.
                                                0
                                                да — шахматные программы именно что стремятся рассчитать следующих ход соперника, исходя из (а) текущей расстановки фигур на доске и (б) собственного множества возможных ходов с тем, чтобы получить информацию для расчета последующей выигрышной стратегии.

                                                я тоже не знаю как работают шахматные программы
                                                но суть игры в шахматы получить преимущество, а не угадать какой ход сделает соперник
                                                Так и в контексте статьи и самих рыночных данных — не нужно искать прогноз, нужно делать ходы (открывать и закрывать ордера) с целью (надеждой? ) получить преимущество… но при таком подходе возникает другая проблема трейдинга, проблема в увеличении риска.
                                                Ну а предсказывать рынок — наибесмысленейшее занятие, т.к. цена всегда ходит в 2 стороны — и вверх и вниз, но когда? насколько длительно? а когда прогноз считать недействительным? — тут вопросов всегда больше чем ответов, да и не может быть этих ответов, если опять «на пальцах» — то примерно как: Вы учите нейросеть управлять автомобилем смотря в зеркало заднего вида — согласитесь, что это бессмысленно на новых данных

                                            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                            Самое читаемое