Машинное обучение в трейдинге: теория, модели, практика и алготорговля - страница 3516

 
Maxim Dmitrievsky #:

посмотри у себя, вроди не пустышка, по моим первым тестам

 
Maxim Dmitrievsky #:

Есть, в общем-то, простая до гениальности вещь, которая позволяет определить, будет ли ваше МО работать на новых данных.

Для этого достаточно иметь только набор меток :) Потому что они являются бинаризованным представлением исходного ряда.

Нужны пруфы с графиками :)

 

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

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

Эксперимент проводим 100 раз и наблюдаем разные графики баланса и гистограмму их распределения.

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

import numpy as np
import matplotlib.pyplot as plt

# Параметры нормальных распределений
mean_N1, std_N1 = -50, 25  # для первого распределения (от -100 до 0)
mean_N2, std_N2 = 100, 25  # для второго распределения (от 0 до 200)

# Заданная последовательность
sequence = np.array([1, 1, -1, 1, 1, -1, -1, -1, 1, -1])

# Количество экспериментов
num_experiments = 100

# Массив для сохранения результатов баланса
balances = []

# Проведение экспериментов
for _ in range(num_experiments):
    values = np.where(sequence == 1, np.random.normal(mean_N2, std_N2, len(sequence)), np.random.normal(mean_N1, std_N1, len(sequence)))
    balance = np.cumsum(values)  # Используем кумулятивную сумму для отслеживания баланса на каждом этапе
    balances.append(balance)

# Визуализация балансов
plt.figure(figsize=(12, 6))

# Построение графиков баланса
plt.subplot(1, 2, 1)
for i, balance_curve in enumerate(balances):
    plt.plot(balance_curve, label=f'Experiment {i + 1}', alpha=0.7)  # Используем alpha для прозрачности
plt.title('Balances Over Experiments')
plt.xlabel('Step')
plt.ylabel('Balance')
#plt.legend()

# Построение гистограммы распределения итоговых балансов
plt.subplot(1, 2, 2)
final_balances = [balance[-1] for balance in balances]
plt.hist(final_balances, bins=20, color='skyblue', edgecolor='black')
plt.title('Distribution of Final Balances')
plt.xlabel('Balance')
plt.ylabel('Frequency')

plt.tight_layout()
plt.show()
 
СанСаныч Фоменко #:
lstm работает с радикально разбалансированными классами - для 2 классов в десятки раз?

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

[Удален]  
Aleksey Vyazmikin #:

Нужны пруфы с графиками :)

Пруфов пока нет, потому что делаю случайный семплинг и энтропия такого ряда всегда стремится к 1, то есть рэндом

[Удален]  
mytarmailS #:

посмотри у себя, вроди не пустышка, по моим первым тестам

ниче не понятно

[Удален]  
Maxim Dmitrievsky #:

Пруфов пока нет, потому что делаю случайный семплинг и энтропия такого ряда всегда стремится к 1, то есть рэндом

Если найду корреляцию между результатами на ООС и оценкой меток, например, через энтропию, то это будет красноречиво

[Удален]  

PE - permutation entropy лэйблов до обучения

Ниже R2 обученной модели на них, с учетом ООС

Iteration: 0, Cluster: 4, PE: 1.4114993035356607
R2: 0.9750027827074201
Iteration: 0, Cluster: 14, PE: 1.4024791111873602
R2: 0.9254099918204924
Iteration: 0, Cluster: 8, PE: 1.41096302580775
R2: 0.9713689561861256
Iteration: 0, Cluster: 0, PE: 1.4269597630754562
R2: 0.9807136795397998
Iteration: 0, Cluster: 1, PE: 1.391583598392451
R2: 0.9600008089806283
Iteration: 0, Cluster: 11, PE: 1.4537902469647772
R2: 0.9720898913608796
Iteration: 0, Cluster: 10, PE: 1.3738852280483222
R2: 0.9536059212630769
Iteration: 0, Cluster: 7, PE: 1.37156426933497
R2: 0.9702039222164988
Iteration: 0, Cluster: 3, PE: 1.433485632603243
R2: 0.9846474447504004
Iteration: 0, Cluster: 12, PE: 1.4031034270604625
R2: 0.9480575294534516
Iteration: 0, Cluster: 2, PE: 1.3916341170184174
R2: 0.9587764283979536
Iteration: 0, Cluster: 9, PE: 1.4121627190055983
R2: 0.9449264868011292
Iteration: 0, Cluster: 6, PE: 1.4026169498968089
R2: 0.5991722238532007
Iteration: 0, Cluster: 5, PE: 1.321808319045704
R2: 0.9698055619808859
Iteration: 0, Cluster: 13, PE: 1.4465424887848997
R2: -0.05071422654396962

все значения очень похожи и нельзя ничего определить :)

Это потому что способ разметки всегда один и тот же. Нужны другие датасеты, можете посчитать на своих. Пример расчета.

import numpy as np
from itertools import permutations

def permutation_entropy(time_series, order=5, delay=1):
    # Create a list of all possible permutations of the given order
    permutations_list = list(permutations(range(order)))
    perm_count = {perm: 0 for perm in permutations_list}
    
    # Calculate the permutation patterns in the time series
    for i in range(len(time_series) - delay * (order - 1)):
        # Extract the sequence
        sequence = time_series[i:i + delay * (order - 1) + 1:delay]
        # Find the permutation pattern
        sorted_index_tuple = tuple(np.argsort(sequence))
        # Increment the permutation count
        perm_count[sorted_index_tuple] += 1

    # Normalize the counts to get a probability distribution
    perm_count_values = np.array(list(perm_count.values()))
    perm_probabilities = perm_count_values / np.sum(perm_count_values)
    
    # Calculate the permutation entropy
    pe = -np.sum([p * np.log2(p) for p in perm_probabilities if p > 0])
    
    return pe

# Example usage
time_series = np.array([4, 7, 9, 10, 6, 11, 3])
order = 2
delay = 1
pe = permutation_entropy(time_series, order, delay)
print(f"Permutation Entropy: {pe}")
[Удален]  

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

Тогда как если в метках нет структуры, значит они просто подогнаны под шум.

[Удален]  

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

Позже сделаю более подробные тесты с результатами. Пока что сложно сравнить.

Iteration: 0, Cluster: 5, PE: 0.4486169556211518
R2: 0.9768988376324667
Iteration: 0, Cluster: 10, PE: 0.4669088793243399
R2: 0.9741796468253388
Iteration: 0, Cluster: 2, PE: 0.46459273655864924
R2: 0.9574754821062279
Iteration: 0, Cluster: 9, PE: 0.4617870814003918
R2: 0.9710405592188178
Iteration: 0, Cluster: 7, PE: 0.44973808720127306
R2: 0.9756506928909877
Iteration: 0, Cluster: 14, PE: 0.4659979449727183
R2: 0.9517591162928314
Iteration: 0, Cluster: 11, PE: 0.4459637631384201
R2: 0.9734964538920183
Iteration: 0, Cluster: 1, PE: 0.47443727646415623
R2: 0.969078168370678
Iteration: 0, Cluster: 8, PE: 0.46687563336247373
R2: 0.9791214350912251
Iteration: 0, Cluster: 4, PE: 0.4566470188416623
R2: 0.9812114918306366
Iteration: 0, Cluster: 12, PE: 0.47363779551886176
R2: 0.9336815818695965
Iteration: 0, Cluster: 0, PE: 0.4478528064300205
R2: 0.9741209899697653
Iteration: 0, Cluster: 3, PE: 0.4375103321344003
R2: 0.9036380849528642
Iteration: 0, Cluster: 6, PE: 0.433662587848933
R2: 0.9280739709436694