Spaces:
Sleeping
Sleeping
File size: 6,693 Bytes
1cf986c f5de412 1cf986c f5de412 1cf986c f5de412 1cf986c f5de412 1cf986c f5de412 1cf986c f5de412 1cf986c f5de412 1cf986c f5de412 1cf986c f5de412 1cf986c f5de412 1cf986c f5de412 1cf986c f5de412 1cf986c f5de412 1cf986c f5de412 1cf986c f5de412 1cf986c f5de412 1cf986c f5de412 1cf986c f5de412 1cf986c f5de412 1cf986c |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
import pandas as pd
import config as cfg
import json # Используем json вместо pandas.io.json для большей стандартности
def get_target_signal(current_close, next_day_close, threshold):
"""
Определяет сигнал (BUY, SELL, HOLD) на основе next_day_close.
"""
if pd.isna(next_day_close) or pd.isna(current_close) or current_close == 0:
return "HOLD" # Недостаточно данных или некорректные данные
price_change_ratio = (next_day_close - current_close) / current_close
if price_change_ratio > threshold:
return "BUY"
elif price_change_ratio < -threshold:
return "SELL"
else:
return "HOLD"
def format_input_for_llm(row, all_indicator_columns):
"""
Форматирует текущее состояние рынка и индикаторы в текстовый промпт для LLM.
"""
# Базовая информация
prompt_parts = [
f"Current open: {row['open']:.2f}",
f"high: {row['high']:.2f}",
f"low: {row['low']:.2f}",
f"close: {row['close']:.2f}",
f"volume: {row['volume']:.0f}."
]
# Добавляем все остальные индикаторы
indicator_descs = []
for col in all_indicator_columns:
# Исключаем уже добавленные и целевую переменную
if col not in ['date', 'open', 'high', 'low', 'close', 'volume', 'next_day_close'] and col in row and pd.notna(row[col]):
# Убираем префиксы rsi_, cci_, sma_, ema_, atr_ для более естественного языка, если хотим
# cleaned_col_name = col.replace("rsi_", "RSI ").replace("cci_", "CCI ").replace("sma_", "SMA ").replace("ema_", "EMA ").replace("atr_", "ATR ")
# indicator_descs.append(f"{cleaned_col_name.replace('_', ' ')}: {row[col]:.2f}")
indicator_descs.append(f"{col.replace('_', ' ')}: {row[col]:.2f}") # Простой вариант
if indicator_descs:
prompt_parts.append("Technical indicators: " + ", ".join(indicator_descs) + ".")
return " ".join(prompt_parts)
def main():
try:
df = pd.read_csv(cfg.CSV_FILE_PATH)
except FileNotFoundError:
print(f"Ошибка: CSV файл не найден по пути: {cfg.CSV_FILE_PATH}")
print("Пожалуйста, убедитесь, что файл существует и путь в config.py указан верно.")
return
# Преобразуем 'date' в datetime и установим как индекс
if 'date' not in df.columns:
print("Ошибка: колонка 'date' отсутствует в CSV файле.")
return
df['date'] = pd.to_datetime(df['date'])
df.set_index('date', inplace=True)
df.sort_index(inplace=True) # Убедимся, что данные отсортированы по времени
# Получаем список всех колонок-индикаторов (кроме date и next_day_close)
# 'open', 'high', 'low', 'close', 'volume' будут обработаны отдельно в format_input_for_llm
all_feature_columns = [col for col in df.columns if col not in ['next_day_close']]
# Удаляем строки, где есть NaN в фичах или в 'close'/'next_day_close'
# (кроме 'next_day_close' для последней строки, это обработается в цикле)
df.dropna(subset=[col for col in all_feature_columns if col != 'next_day_close'], inplace=True) # Удаляем NaN в фичах
# df.dropna(subset=['close', 'next_day_close'], inplace=True) # Удаляем если нет таргета или текущей цены
if df.empty:
print("Датафрейм пуст после удаления NaN. Проверьте данные.")
return
print(f"Количество строк после начальной обработки: {len(df)}")
processed_data = []
# Идем почти до конца, так как для последней строки может не быть next_day_close
# или next_day_close может быть NaN, что обработает get_target_signal
for i in range(len(df)):
current_row = df.iloc[i]
# Проверяем, есть ли next_day_close для текущей строки (особенно актуально для последней строки файла)
if 'next_day_close' not in current_row or pd.isna(current_row['next_day_close']):
if i == len(df) - 1: # Если это последняя строка и нет next_day_close, просто пропускаем ее
print(f"Пропускаем последнюю строку {current_row.name}, т.к. отсутствует 'next_day_close'.")
continue
else: # Если это не последняя строка, но 'next_day_close' NaN, это странно, но get_target_signal вернет HOLD
pass
market_description = format_input_for_llm(current_row, all_feature_columns)
current_close_price = current_row['close']
next_day_close_price = current_row['next_day_close']
signal = get_target_signal(current_close_price, next_day_close_price, cfg.PRICE_CHANGE_THRESHOLD_SIGNAL)
# Формат для SFTTrainer
formatted_text = f"<s>[INST] Анализ рынка BTC/USDT на основе следующих данных: {market_description} Какое торговое действие (BUY, SELL, или HOLD) следует предпринять? [/INST] {signal}</s>"
processed_data.append({"text": formatted_text})
# Сохраняем в формате JSONL
with open(cfg.TRAINING_DATA_JSONL, 'w', encoding='utf-8') as f:
for item in processed_data:
f.write(json.dumps(item) + '\n')
print(f"Данные подготовлены и сохранены в {cfg.TRAINING_DATA_JSONL}. Количество примеров: {len(processed_data)}")
if processed_data:
print("Пример первой строки данных для обучения:")
print(processed_data[0]['text'])
else:
print("Не было сгенерировано ни одного примера для обучения. Проверьте логику и данные.")
if __name__ == "__main__":
main() |