File size: 6,657 Bytes
e0ff5fb 1e81e10 03e6a37 1e81e10 e0ff5fb 1e81e10 22a0f86 024bb73 1e81e10 0559530 e0ff5fb 0559530 1e81e10 0559530 1e81e10 0559530 1e81e10 0559530 1e81e10 e0ff5fb 1e81e10 e0ff5fb 1e81e10 e0ff5fb 1e81e10 e0ff5fb 0559530 e0ff5fb 03e6a37 e0ff5fb 1e81e10 e0ff5fb 1e81e10 e0ff5fb 0559530 03e6a37 e0ff5fb 0559530 03e6a37 e0ff5fb 1e81e10 0559530 1e81e10 03e6a37 e0ff5fb 024bb73 03e6a37 024bb73 03e6a37 e0ff5fb 0559530 03e6a37 1e81e10 e0ff5fb 0559530 22a0f86 |
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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
import os
import pandas as pd
import numpy as np
from datetime import timedelta
from binance.client import Client
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report
import ta
# Function to log results to both console and file
# Does not insert blank lines; blank lines added explicitly after each asset block
def log_results(message, filename="predictions_results.txt"):
print(message)
with open(filename, "a") as f:
f.write(message + "\n")
# Initialize Binance client
client = Client()
# Settings
interval = Client.KLINE_INTERVAL_4HOUR
result_file = "predictions_results.txt"
# Delete the results file if it exists for a fresh start
if os.path.exists(result_file):
os.remove(result_file)
# Initialize result file header
with open(result_file, "w") as f:
f.write("Asset,Time,Price,Prediction,Optimal_UP_TP,Optimal_UP_SL,Optimal_DN_TP,Optimal_DN_SL\n")
# Get USDT-quoted trading symbols
symbols = [s['symbol'] for s in client.get_exchange_info()['symbols']
if s['status']=='TRADING' and s['quoteAsset']=='USDT']
# Optimize take-profit / stop-loss function
def optimize_tp_sl(df, signals, side, pgrid, lgrid):
best = (0, 0, -np.inf)
prices = df['close'].values
idxs = np.where(signals == side)[0]
for tp in pgrid:
for sl in lgrid:
rets = []
for i in idxs:
entry = prices[i]
for j in range(i+1, min(i+11, len(prices))):
ret = (prices[j] - entry) / entry if side == 1 else (entry - prices[j]) / entry
if ret >= tp or ret <= -sl:
rets.append(np.sign(ret) * min(abs(ret), max(tp, sl)))
break
if rets:
avg_ret = np.mean(rets)
if avg_ret > best[2]:
best = (tp, sl, avg_ret)
return best
# Process each symbol
for symbol in symbols:
log_results(f"=== {symbol} ===", result_file)
# Load or download historical data
data_file = f"{symbol}_data_4h_full.csv"
if os.path.exists(data_file):
df = pd.read_csv(data_file, index_col=0, parse_dates=True)
last_ts = df.index[-1]
start = (last_ts + timedelta(hours=4)).strftime("%d %B %Y %H:%M:%S")
new = client.get_historical_klines(symbol, interval, start)
if new:
new_df = pd.DataFrame(new, columns=['timestamp','open','high','low','close','volume',
'close_time','quote_av','trades','tb_base_av','tb_quote_av','ignore'])
new_df = new_df[['timestamp','open','high','low','close','volume']].astype(float)
new_df['timestamp'] = pd.to_datetime(new_df['timestamp'], unit='ms')
new_df.set_index('timestamp', inplace=True)
df = pd.concat([df, new_df]).drop_duplicates()
df.to_csv(data_file)
else:
klines = client.get_historical_klines(symbol, interval, "01 December 2021")
df = pd.DataFrame(klines, columns=['timestamp','open','high','low','close','volume',
'close_time','quote_av','trades','tb_base_av','tb_quote_av','ignore'])
df = df[['timestamp','open','high','low','close','volume']].astype(float)
df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
df.set_index('timestamp', inplace=True)
df.to_csv(data_file)
# Compute technical indicators
df['rsi'] = ta.momentum.RSIIndicator(df['close'], window=14).rsi()
df['macd'] = ta.trend.MACD(df['close']).macd()
for s in [10, 20, 50, 100]: df[f'ema_{s}'] = df['close'].ewm(span=s).mean()
for w in [10, 20, 50, 100]: df[f'sma_{w}'] = df['close'].rolling(window=w).mean()
bb = ta.volatility.BollingerBands(df['close'], window=20, window_dev=2)
df['bbw'] = (bb.bollinger_hband() - bb.bollinger_lband()) / bb.bollinger_mavg()
df['atr'] = ta.volatility.AverageTrueRange(df['high'], df['low'], df['close'], window=14).average_true_range()
df['adx'] = ta.trend.ADXIndicator(df['high'], df['low'], df['close'], window=14).adx()
st = ta.momentum.StochasticOscillator(df['high'], df['low'], df['close'], window=14)
df['st_k'] = st.stoch(); df['st_d'] = st.stoch_signal()
df['wr'] = ta.momentum.WilliamsRIndicator(df['high'], df['low'], df['close'], lbp=14).williams_r()
df['cci'] = ta.trend.CCIIndicator(df['high'], df['low'], df['close'], window=20).cci()
df['mom'] = df['close'] - df['close'].shift(10)
ichi = ta.trend.IchimokuIndicator(df['high'], df['low'], window1=9, window2=26, window3=52)
df['span_a'] = ichi.ichimoku_a(); df['span_b'] = ichi.ichimoku_b()
df.dropna(inplace=True)
# Label signals based on Ichimoku cloud
df['signal'] = np.select([
(df['close'] > df['span_a']) & (df['close'] > df['span_b']),
(df['close'] < df['span_a']) & (df['close'] < df['span_b'])
], [1, 0], default=-1)
# Train/test split
features = [c for c in df.columns if c not in ['open', 'high', 'low', 'close', 'volume', 'signal']]
X, y = df[features], df['signal']
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.2, shuffle=False)
model = RandomForestClassifier(n_estimators=200, class_weight='balanced', random_state=42)
model.fit(Xtr, ytr)
ypr = model.predict(Xte)
# Log classification report
report = classification_report(yte, ypr, zero_division=0)
log_results(f"Classification report for {symbol}: {report}", result_file)
# Predict latest trend and log time & price
latest_df = X.iloc[-1:] # DataFrame for prediction
trend_label = model.predict(latest_df)[0]
pred_time = df.index[-1]
pred_price = df['close'].iloc[-1]
trend_str = {1:'Uptrend', 0:'Downtrend', -1:'Neutral'}[trend_label]
log_results(f"Time: {pred_time}, Price: {pred_price:.2f}, Prediction: {trend_str}", result_file)
# Optimize TP/SL and log results
hist_sign = model.predict(X) # Pass DataFrame to avoid warning
pgrid = np.arange(0.01, 0.1, 0.01)
lgrid = np.arange(0.01, 0.1, 0.01)
up_tp, up_sl, _ = optimize_tp_sl(df, hist_sign, 1, pgrid, lgrid)
dn_tp, dn_sl, _ = optimize_tp_sl(df, hist_sign, 0, pgrid, lgrid)
log_results(f"Optimal UP TP/SL: +{up_tp*100:.1f}% / -{up_sl*100:.1f}%", result_file)
log_results(f"Optimal DN TP/SL: +{dn_tp*100:.1f}% / -{dn_sl*100:.1f}%", result_file)
# Add a blank line after each asset block
with open(result_file, "a") as f:
f.write("\n")
# End of processing
log_results("All assets processed.", result_file)
|