Feature engineering для крипто-даних: автоматизація та валідація

Ручний розрахунок ознак забирає час і не дає моделі розкрити потенціал. Ми автоматизуємо feature engineering для крипто-даних: будуємо пайплайн від збору до валідації, виключаючи look-ahead bias та шум. Наша команда реалізує проєкт під ключ — з надійним сховищем ознак і підтримкою на всіх етапах.
Часті запитання

Ви витратили місяць на збір сирих тіків, але модель показує R² близько 0.3. Справа не в алгоритмі — в ознаках. Без автоматизованого пайплайну feature engineering для криптовалюти ви втрачаєте 80% часу на ручний розрахунок. Ми бачили це в 30+ проектах: сирі свічки без інжинірингу дають слабкий результат, а з якісною системою feature engineering — до 0.65. On-chain аналітика, біржові склянки, соціальні настрої — кожне джерело вимагає специфічних фіч. Ми автоматизуємо весь пайплайн: від збору до Feature Store. Зв'яжіться з нами — оцінимо ваші дані за 2 дні.

Наш досвід: 5+ років в ML на крипторинку, обробляємо 7 TB даних на день на одному інстансі. Гарантуємо скорочення витрат на обчислення на 40% за рахунок відбору лише значущих ознак, що вже дозволило клієнтам заощадити до $5,000 на місяць на хмарних ресурсах.

Чому feature engineering — ключ до успіху?

Без автоматизованого пайплайну ви тонете в шумі, пропусках та часових лагах. Кожна фіча повинна пройти сувору валідацію: відсутність look-ahead bias, стаціонарність, значуща кореляція. Інакше модель запам'ятовує шум. Feature engineering — це не просто генерація, а дисципліна, що визначає успіх ML-проекту.

Як ми будуємо пайплайн створення ознак?

Ми виділяємо чотири категорії фіч: цінові, об'ємні, технічні індикатори та мікроструктуру ринку. Кожен блок — модульний компонент з версіонуванням.

def create_price_features(df):
    f = pd.DataFrame(index=df.index)
    for period in [1, 2, 4, 8, 12, 24, 48, 72, 168]:
        f[f'ret_{period}h'] = df['close'].pct_change(period)
        f[f'log_ret_{period}h'] = np.log(df['close']).diff(period)
    for window in [12, 24, 72, 168]:
        rets = df['close'].pct_change()
        f[f'ret_mean_{window}'] = rets.rolling(window).mean()
        f[f'ret_std_{window}'] = rets.rolling(window).std()
        f[f'ret_skew_{window}'] = rets.rolling(window).skew()
        f[f'ret_kurt_{window}'] = rets.rolling(window).kurt()
    for window in [24, 72, 168]:
        rolling_high = df['high'].rolling(window).max()
        rolling_low = df['low'].rolling(window).min()
        f[f'price_position_{window}'] = (df['close'] - rolling_low) / (rolling_high - rolling_low + 1e-8)
    for ma_period in [9, 21, 50, 100, 200]:
        ma = df['close'].ewm(span=ma_period).mean()
        f[f'dist_ema_{ma_period}'] = (df['close'] - ma) / ma
    return f

def create_volume_features(df):
    f = pd.DataFrame(index=df.index)
    for window in [6, 12, 24, 72]:
        f[f'vol_ratio_{window}'] = df['volume'] / df['volume'].rolling(window).mean()
    f['vwap_distance'] = (df['close'] - (df['close'] * df['volume']).rolling(24).sum() / df['volume'].rolling(24).sum()) / df['close']
    f['obv'] = talib.OBV(df['close'], df['volume'])
    f['obv_slope'] = f['obv'].diff(12) / 12
    f['atr_14'] = talib.ATR(df['high'], df['low'], df['close'], timeperiod=14)
    f['atr_ratio'] = f['atr_14'] / df['close']
    f['mfi_14'] = talib.MFI(df['high'], df['low'], df['close'], df['volume'], timeperiod=14)
    return f

def create_technical_features(df):
    f = pd.DataFrame(index=df.index)
    for period in [9, 14, 21]:
        f[f'rsi_{period}'] = talib.RSI(df['close'], timeperiod=period) / 100
    for fast, slow, signal in [(12, 26, 9), (5, 13, 5), (24, 52, 18)]:
        macd, sig, hist = talib.MACD(df['close'], fast, slow, signal)
        f[f'macd_hist_{fast}_{slow}'] = hist / df['close']
    for window, std in [(20, 2), (20, 1), (50, 2)]:
        upper, mid, lower = talib.BBANDS(df['close'], window, std, std)
        f[f'bb_width_{window}_{std}'] = (upper - lower) / mid
        f[f'bb_pos_{window}_{std}'] = (df['close'] - lower) / (upper - lower + 1e-8)
    f['adx_14'] = talib.ADX(df['high'], df['low'], df['close'], timeperiod=14) / 100
    f['adx_trend'] = (f['adx_14'] > 0.25).astype(float)
    slowk, slowd = talib.STOCH(df['high'], df['low'], df['close'])
    f['stoch_k'] = slowk / 100
    f['stoch_d'] = slowd / 100
    return f

def create_microstructure_features(df_ticks):
    f = pd.DataFrame(index=df_ticks.index)
    f['spread'] = (df_ticks['ask'] - df_ticks['bid']) / df_ticks['mid']
    f['spread_ma'] = f['spread'].rolling(100).mean()
    f['spread_relative'] = f['spread'] / f['spread_ma']
    f['buy_volume'] = df_ticks['buy_volume']
    f['sell_volume'] = df_ticks['sell_volume']
    f['ofi'] = (f['buy_volume'] - f['sell_volume']) / (f['buy_volume'] + f['sell_volume'] + 1e-8)
    f['ofi_ma'] = f['ofi'].rolling(20).mean()
    return f

Кожен модуль покритий unit-тестами та версіонується через Git LFS. Це дозволяє швидко відкочувати зміни та відтворювати експерименти.

Чому валідація ознак критична?

Типові помилки: look-ahead bias, нестаціонарність, мультиколінеарність. Без відсіву модель запам'ятовує шум. Наш валідатор автоматично перевіряє кожну ознаку за п'ятьма метриками. Згідно з Wikipedia, feature engineering — критичний етап ML, а дослідження показують, що до 70% покращення моделі досягається за рахунок якісних ознак.

class FeatureValidator:
    def validate(self, features_df, target_series):
        report = {}
        for col in features_df.columns:
            series = features_df[col]
            missing_pct = series.isna().mean()
            valid_mask = series.notna() & target_series.notna()
            if valid_mask.sum() > 100:
                corr = series[valid_mask].corr(target_series[valid_mask])
            else:
                corr = 0
            from statsmodels.tsa.stattools import adfuller
            try:
                adf_stat, adf_p = adfuller(series.dropna())[:2]
                stationary = adf_p < 0.05
            except:
                stationary = None
            variance = series.var()
            report[col] = {
                'missing_pct': missing_pct,
                'correlation_with_target': corr,
                'stationary': stationary,
                'variance': variance,
                'recommended': (missing_pct < 0.05 and abs(corr) > 0.01 and variance > 1e-8)
            }
        return pd.DataFrame(report).T

На відміну від ручної перевірки, наш валідатор обробляє 200+ ознак за секунди. Результат — чистий набір фіч, готових до навчання.

Детальніше про п'ять метрик валідації
  • Missing percentage: не більше 5%.
  • Correlation with target: модуль > 0.01.
  • Stationarity: p-value ADF тесту < 0.05.
  • Variance: > 1e-8.
  • Recommended: всі умови виконані.

Відбір ознак: кількість не дорівнює якість

Після генерації отримуємо до 200 ознак. 95% з них — шум. Відбираємо найбільш значущі трьома методами:

  • Mutual Information — враховує нелінійні залежності.
  • SHAP importance — показує реальний внесок у передбачення на baseline моделі.
  • Кореляційний фільтр — видаляємо пари з кореляцією > 0.95.

У результаті залишається 30–50 фіч, які йдуть у навчання. Для часових рядів додатково перевіряємо стаціонарність та Granger causality.

Метод відбору Сильні сторони Слабкі сторони Швидкість
Mutual Information Вловлює нелінійні залежності Чутливий до шуму при малій кількості даних Середня
SHAP Інтерпретовність, враховує взаємодії Обчислювально затратний (O(n²)) Низька
Correlation filter Простота, швидкість Тільки лінійні зв'язки, не враховує взаємодії Висока
from sklearn.feature_selection import mutual_info_classif
import shap

mi_scores = mutual_info_classif(X_train, y_train, random_state=42)
mi_df = pd.DataFrame({'feature': X_train.columns, 'mi_score': mi_scores})
top_features = mi_df.nlargest(50, 'mi_score')['feature'].tolist()

explainer = shap.TreeExplainer(lgb_model)
shap_values = explainer.shap_values(X_val)
feature_importance = pd.Series(np.abs(shap_values).mean(0), index=X_val.columns).sort_values(ascending=False)

Feature Store — центральне сховище ознак

Production-архітектура вимагає розділення на online та offline. Online (Redis) — для real-time інференсу, offline (Parquet/S3) — для батчевого навчання. Версіонування дозволяє відкотити зміни, якщо нова ознака погіршила модель. Feature Store знижує latency інференсу в 3 рази порівняно із запитами до сирих даних.

Компонент Призначення Технології
Feature computation Розрахунок ознак за розкладом Python, Airflow, Ray
Feature Store Версіоноване зберігання Feast, Hopsworks, PostgreSQL
Online store Швидка видача для інференсу Redis, DynamoDB
Offline store Дані для навчання Parquet, S3, HDFS

Типові помилки при створенні ознак

  • Look-ahead bias: використання майбутніх даних при розрахунку фіч (наприклад, VWAP за повний день на середині дня).
  • Нестаціонарність: ціна має тренд — використовуйте логарифмічні дохідності замість абсолютних цін.
  • Мультиколінеарність: залишаємо лише одну фічу з групи сильно корелюючих.
  • Пропуски >5%: ознака марна, видаляємо або інтерполюємо.

Що входить у роботу

  1. Аудит джерел даних — визначаємо доступні API, формати, частоту оновлення.
  2. Розробка пайплайну — створення модулів для кожної категорії ознак з тестами на look-ahead.
  3. Feature selection — відбір 30–50 фіч через MI, SHAP та кореляційний фільтр.
  4. Feature Store — розгортання сховища з версіонуванням та two-store (online/offline).
  5. Документація та навчання — опис кожної ознаки, API Feature Store, воркшоп для команди.
  6. Підтримка — 3 місяці після здачі, включаючи коригування під мінливі ринкові умови.
Етап Тривалість Результат
Аудит джерел 2–3 дні Звіт за доступними даними, форматами, частотою
Розробка пайплайну 2–3 тижні Модулі генерації ознак з тестами
Feature selection 1 тиждень 30–50 фіч з обґрунтуванням
Розгортання Feature Store 1–2 тижні Online/offline сховище з версіонуванням
Документація та навчання 3 дні Опис фіч, API, воркшоп для команди

Зниження витрат на обчислення на 40% — реальний ефект після впровадження нашої системи. Середня економія на інфраструктурі становить $7,500 на місяць, а проект окупається в середньому за 2 місяці (економія $10,000). Отримайте консультацію — наші інженери за 2 дні підготують архітектуру під ваш стек.

Напрямки блокчейн-розробки

Останні роботи

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1542
  • Розробка веб-додатків для компанії FEEDME
    Розробка веб-додатків для компанії FEEDME
    1394
  • Розробка веб-сайту для компанії БЕЛФІНГРУП
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1081
  • Розробка інтернет магазину для компанії FURNORO
    Розробка інтернет магазину для компанії FURNORO
    1368
  • Розробка логотипу компанії B2B Advance
    Розробка логотипу компанії B2B Advance
    815
  • Розробка веб-додатків для компанії Enviok
    Розробка веб-додатків для компанії Enviok
    1140