solanaexpert commited on
Commit
9440b66
·
verified ·
1 Parent(s): 9ce424f

Upload 3 files

Browse files
ichimoku_ml_model.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f121fee76b570d40604262b41e7ed4bde13ea5be972334f1f9b557477e0ed2e6
3
+ size 37801
ml_ichimoku_scanner.py ADDED
@@ -0,0 +1,420 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+ import os
3
+ import ccxt
4
+ import pandas as pd
5
+ import numpy as np
6
+ from datetime import datetime, timedelta
7
+ import time
8
+ import threading
9
+ import ta
10
+ import argparse
11
+ import signal
12
+ from sklearn.ensemble import RandomForestClassifier
13
+ from sklearn.model_selection import train_test_split
14
+ from sklearn.metrics import accuracy_score
15
+ import tweepy
16
+ from textblob import TextBlob
17
+ import pickle
18
+ import warnings
19
+
20
+ # Suppress warnings
21
+ warnings.filterwarnings('ignore')
22
+
23
+ # Configuration
24
+ pd.set_option('display.max_columns', None)
25
+ pd.set_option('display.max_rows', None)
26
+ pd.set_option('display.expand_frame_repr', True)
27
+
28
+ class MLIchimokuScanner:
29
+ def __init__(self, training_mode=False):
30
+ self.enable_tweet = True
31
+ self.training_mode = training_mode
32
+ self.model = None
33
+ self.model_file = "ichimoku_ml_model.pkl"
34
+ self.training_data_file = "training_data.csv"
35
+ self.min_training_samples = 100
36
+ self.load_ml_model()
37
+
38
+ # Initialize exchanges
39
+ self.exchanges = {}
40
+ for id in ccxt.exchanges:
41
+ exchange = getattr(ccxt, id)
42
+ self.exchanges[id] = exchange()
43
+
44
+ # Twitter API config
45
+ self.twitter_auth_keys = {
46
+ "consumer_key": "replaceme",
47
+ "consumer_secret": "replaceme",
48
+ "access_token": "replaceme",
49
+ "access_token_secret": "replaceme"
50
+ }
51
+
52
+ # ML features configuration
53
+ self.feature_columns = [
54
+ 'ichimoku_a', 'ichimoku_b', 'kijun_sen', 'tenkan_sen', 'chikou_span',
55
+ 'rsi', 'macd', 'bollinger_upper', 'bollinger_lower', 'volume_ma',
56
+ 'sentiment_score', 'price_above_cloud', 'cloud_color'
57
+ ]
58
+
59
+ # Performance tracking
60
+ self.performance_history = pd.DataFrame(columns=[
61
+ 'timestamp', 'symbol', 'prediction', 'actual', 'profit'
62
+ ])
63
+
64
+ # Training data collection
65
+ self.training_data = pd.DataFrame(columns=self.feature_columns + ['target'])
66
+
67
+ def load_ml_model(self):
68
+ """Load trained ML model if exists"""
69
+ if os.path.exists(self.model_file):
70
+ with open(self.model_file, 'rb') as f:
71
+ self.model = pickle.load(f)
72
+ print("Loaded trained model from file")
73
+ else:
74
+ print("Initializing new model")
75
+ self.model = RandomForestClassifier(n_estimators=100, random_state=42)
76
+
77
+ def save_ml_model(self):
78
+ """Save trained ML model"""
79
+ with open(self.model_file, 'wb') as f:
80
+ pickle.dump(self.model, f)
81
+ print("Saved model to file")
82
+
83
+ def load_training_data(self):
84
+ """Load existing training data if available"""
85
+ if os.path.exists(self.training_data_file):
86
+ self.training_data = pd.read_csv(self.training_data_file)
87
+ print(f"Loaded {len(self.training_data)} training samples")
88
+
89
+ def save_training_data(self):
90
+ """Save training data to file"""
91
+ self.training_data.to_csv(self.training_data_file, index=False)
92
+ print(f"Saved {len(self.training_data)} training samples")
93
+
94
+ def calculate_features(self, df):
95
+ """Calculate technical indicators and features for ML"""
96
+ try:
97
+ # Ichimoku Cloud
98
+ high = df['high'].astype(float)
99
+ low = df['low'].astype(float)
100
+ close = df['close'].astype(float)
101
+ volume = df['volume'].astype(float)
102
+
103
+ df['ichimoku_a'] = ta.trend.ichimoku_a(high, low, window1=9, window2=26).shift(26)
104
+ df['ichimoku_b'] = ta.trend.ichimoku_b(high, low, window2=26, window3=52).shift(26)
105
+ df['kijun_sen'] = ta.trend.ichimoku_base_line(high, low)
106
+ df['tenkan_sen'] = ta.trend.ichimoku_conversion_line(high, low)
107
+ df['chikou_span'] = close.shift(-26)
108
+
109
+ # Additional technical indicators
110
+ df['rsi'] = ta.momentum.rsi(close, window=14)
111
+ df['macd'] = ta.trend.macd_diff(close)
112
+ bollinger = ta.volatility.BollingerBands(close)
113
+ df['bollinger_upper'] = bollinger.bollinger_hband()
114
+ df['bollinger_lower'] = bollinger.bollinger_lband()
115
+ df['volume_ma'] = volume.rolling(window=20).mean()
116
+
117
+ # Derived features
118
+ df['price_above_cloud'] = (close > df[['ichimoku_a', 'ichimoku_b']].max(axis=1)).astype(int)
119
+ df['cloud_color'] = (df['ichimoku_a'] > df['ichimoku_b']).astype(int)
120
+
121
+ return df
122
+ except Exception as e:
123
+ print(f"Error calculating features: {str(e)}")
124
+ return None
125
+
126
+ def get_sentiment_score(self, symbol):
127
+ """Get sentiment score from Twitter for given symbol"""
128
+ if not self.enable_tweet:
129
+ return 0
130
+
131
+ try:
132
+ auth = tweepy.OAuthHandler(
133
+ self.twitter_auth_keys['consumer_key'],
134
+ self.twitter_auth_keys['consumer_secret']
135
+ )
136
+ auth.set_access_token(
137
+ self.twitter_auth_keys['access_token'],
138
+ self.twitter_auth_keys['access_token_secret']
139
+ )
140
+ api = tweepy.API(auth, wait_on_rate_limit=True)
141
+
142
+ # Use search_tweets instead of the deprecated search method
143
+ tweets = api.search_tweets(q=f"${symbol.replace('USDT', '')}", count=100)
144
+ sentiments = []
145
+ for tweet in tweets:
146
+ analysis = TextBlob(tweet.text)
147
+ sentiments.append(analysis.sentiment.polarity)
148
+
149
+ return np.mean(sentiments) if sentiments else 0
150
+ except tweepy.Unauthorized as e:
151
+ #print(f"Twitter API authentication failed: {str(e)}")
152
+ return 0
153
+ except Exception as e:
154
+ #print(f"Error getting sentiment: {str(e)}")
155
+ return 0
156
+
157
+ def train_initial_model(self):
158
+ """Train initial model if we have enough data"""
159
+ self.load_training_data()
160
+
161
+ if len(self.training_data) >= self.min_training_samples:
162
+ X = self.training_data[self.feature_columns]
163
+ y = self.training_data['target']
164
+
165
+ X_train, X_test, y_train, y_test = train_test_split(
166
+ X, y, test_size=0.2, random_state=42
167
+ )
168
+
169
+ self.model.fit(X_train, y_train)
170
+
171
+ # Evaluate model
172
+ preds = self.model.predict(X_test)
173
+ accuracy = accuracy_score(y_test, preds)
174
+ print(f"Initial model trained with accuracy: {accuracy:.2f}")
175
+
176
+ self.save_ml_model()
177
+ return True
178
+ else:
179
+ print(f"Not enough training data ({len(self.training_data)} samples). Need at least {self.min_training_samples}.")
180
+ return False
181
+
182
+ def predict_direction(self, features):
183
+ """Predict price direction using ML model"""
184
+ try:
185
+ if self.model is None or not hasattr(self.model, 'classes_'):
186
+ return 0 # Neutral if no model
187
+
188
+ # Ensure features are in correct order
189
+ features = features[self.feature_columns].values.reshape(1, -1)
190
+ return self.model.predict(features)[0]
191
+ except Exception as e:
192
+ print(f"Prediction error: {str(e)}")
193
+ return 0
194
+
195
+ def collect_training_sample(self, symbol, exchange, timeframe='1h'):
196
+ """Collect data sample for training"""
197
+ try:
198
+ # Get historical data
199
+ ohlcv = exchange.fetch_ohlcv(symbol, timeframe, limit=100)
200
+ if len(ohlcv) < 52: # Need enough data for Ichimoku
201
+ return
202
+
203
+ df = pd.DataFrame(ohlcv, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
204
+ df = self.calculate_features(df)
205
+ if df is None:
206
+ return
207
+
208
+ # Get current and future price for target
209
+ current_price = df['close'].iloc[-1]
210
+ future_price = df['close'].iloc[-1] # Placeholder - in real use, would get future price
211
+
212
+ # Determine target (1 for up, -1 for down, 0 for neutral)
213
+ price_change = future_price - current_price
214
+ target = 1 if price_change > 0 else (-1 if price_change < 0 else 0)
215
+
216
+ # Get features from last complete row
217
+ features = df.iloc[-2].copy()
218
+ features['sentiment_score'] = self.get_sentiment_score(symbol)
219
+ features['target'] = target
220
+
221
+ # Add to training data using concat instead of append
222
+ new_row = pd.DataFrame([features])
223
+ self.training_data = pd.concat([self.training_data, new_row], ignore_index=True)
224
+ print(f"Collected training sample for {symbol}")
225
+
226
+ # Periodically save data
227
+ if len(self.training_data) % 10 == 0:
228
+ self.save_training_data()
229
+
230
+ except Exception as e:
231
+ print(f"Error collecting training sample: {str(e)}")
232
+
233
+ def scan_symbol(self, symbol, exchange, timeframes):
234
+ """Enhanced scanning with ML predictions"""
235
+ try:
236
+ # Get data for primary timeframe
237
+ primary_tf = timeframes[0]
238
+ ohlcv = exchange.fetch_ohlcv(symbol, primary_tf, limit=100)
239
+ if len(ohlcv) < 52: # Need enough data for Ichimoku
240
+ return
241
+
242
+ df = pd.DataFrame(ohlcv, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
243
+ df = self.calculate_features(df)
244
+ if df is None:
245
+ return
246
+
247
+ # Get sentiment data
248
+ sentiment = self.get_sentiment_score(symbol)
249
+
250
+ # Prepare features for ML prediction
251
+ latest = df.iloc[-1].copy()
252
+ latest['sentiment_score'] = sentiment
253
+ features = pd.DataFrame([latest[self.feature_columns]])
254
+
255
+ # In training mode, just collect data
256
+ if self.training_mode:
257
+ self.collect_training_sample(symbol, exchange, primary_tf)
258
+ return
259
+
260
+ # Make prediction (returns -1, 0, or 1)
261
+ prediction = self.predict_direction(features)
262
+
263
+ # Check Ichimoku conditions
264
+ uptrend = all(
265
+ self.check_timeframe_up(symbol, tf, exchange)
266
+ for tf in timeframes
267
+ )
268
+
269
+ downtrend = all(
270
+ self.check_timeframe_down(symbol, tf, exchange)
271
+ for tf in timeframes
272
+ )
273
+
274
+ # Generate appropriate alert
275
+ if uptrend and prediction == 1:
276
+ self.alert(symbol, "STRONG UPTREND", timeframes)
277
+ elif downtrend and prediction == -1:
278
+ self.alert(symbol, "STRONG DOWNTREND", timeframes)
279
+ elif uptrend:
280
+ self.alert(symbol, "UPTREND", timeframes)
281
+ elif downtrend:
282
+ self.alert(symbol, "DOWNTREND", timeframes)
283
+
284
+ except Exception as e:
285
+ print(f"Error scanning {symbol}: {str(e)}")
286
+
287
+ def check_timeframe_up(self, symbol, timeframe, exchange):
288
+ """Check if symbol is in uptrend on given timeframe"""
289
+ try:
290
+ ohlcv = exchange.fetch_ohlcv(symbol, timeframe, limit=100)
291
+ df = pd.DataFrame(ohlcv, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
292
+ df = self.calculate_features(df)
293
+
294
+ ssb = df['ichimoku_b'].iloc[-1]
295
+ ssa = df['ichimoku_a'].iloc[-1]
296
+ kijun = df['kijun_sen'].iloc[-1]
297
+ tenkan = df['tenkan_sen'].iloc[-1]
298
+ chikou = df['chikou_span'].iloc[-27] if len(df) > 27 else 0
299
+ price_close = df['close'].iloc[-1]
300
+ price_open = df['open'].iloc[-1]
301
+
302
+ # Basic uptrend conditions
303
+ above_cloud = (price_close > max(ssa, ssb))
304
+ above_kijun = (price_close > kijun)
305
+ above_tenkan = (price_close > tenkan)
306
+ rising = (price_close > price_open)
307
+
308
+ return above_cloud and above_kijun and above_tenkan and rising
309
+ except:
310
+ return False
311
+
312
+ def check_timeframe_down(self, symbol, timeframe, exchange):
313
+ """Check if symbol is in downtrend on given timeframe"""
314
+ try:
315
+ ohlcv = exchange.fetch_ohlcv(symbol, timeframe, limit=100)
316
+ df = pd.DataFrame(ohlcv, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
317
+ df = self.calculate_features(df)
318
+
319
+ ssb = df['ichimoku_b'].iloc[-1]
320
+ ssa = df['ichimoku_a'].iloc[-1]
321
+ kijun = df['kijun_sen'].iloc[-1]
322
+ tenkan = df['tenkan_sen'].iloc[-1]
323
+ chikou = df['chikou_span'].iloc[-27] if len(df) > 27 else 0
324
+ price_close = df['close'].iloc[-1]
325
+ price_open = df['open'].iloc[-1]
326
+
327
+ # Basic downtrend conditions
328
+ below_cloud = (price_close < min(ssa, ssb))
329
+ below_kijun = (price_close < kijun)
330
+ below_tenkan = (price_close < tenkan)
331
+ falling = (price_close < price_open)
332
+
333
+ return below_cloud and below_kijun and below_tenkan and falling
334
+ except:
335
+ return False
336
+
337
+ def alert(self, symbol, trend_type, timeframes):
338
+ """Generate alert for detected trend"""
339
+ message = f"({trend_type}) detected for {symbol} on {timeframes} at {datetime.now()}"
340
+ print(message)
341
+
342
+ if self.enable_tweet:
343
+ self.tweet(message)
344
+
345
+ def tweet(self, message):
346
+ return
347
+ """Send tweet with trading alert"""
348
+ try:
349
+ auth = tweepy.OAuthHandler(
350
+ self.twitter_auth_keys['consumer_key'],
351
+ self.twitter_auth_keys['consumer_secret']
352
+ )
353
+ auth.set_access_token(
354
+ self.twitter_auth_keys['access_token'],
355
+ self.twitter_auth_keys['access_token_secret']
356
+ )
357
+ api = tweepy.API(auth, wait_on_rate_limit=True)
358
+
359
+ tweet_msg = f"{message} #Ichimoku #ML #Trading #Crypto"
360
+ api.update_status(status=tweet_msg)
361
+ except Exception as e:
362
+ print(f"Error tweeting: {str(e)}")
363
+
364
+ # Main execution
365
+ if __name__ == "__main__":
366
+ parser = argparse.ArgumentParser()
367
+ parser.add_argument("-e", "--exchange", help="Exchange name", required=True)
368
+ parser.add_argument("-f", "--filter", help="Asset filter", required=True)
369
+ parser.add_argument("-tf", "--timeframes", help="Timeframes to scan (comma separated)", required=True)
370
+ parser.add_argument("--train", help="Run in training mode", action="store_true")
371
+ args = parser.parse_args()
372
+
373
+ scanner = MLIchimokuScanner(training_mode=args.train)
374
+
375
+ # Initialize exchange
376
+ exchange = scanner.exchanges.get(args.exchange.lower())
377
+ if not exchange:
378
+ print(f"Exchange {args.exchange} not supported")
379
+ sys.exit(1)
380
+
381
+ # Get markets
382
+ try:
383
+ markets = exchange.fetch_markets()
384
+ except Exception as e:
385
+ print(f"Error fetching markets: {str(e)}")
386
+ sys.exit(1)
387
+
388
+ # Filter symbols
389
+ symbols = [
390
+ m['id'] for m in markets
391
+ if m['active'] and args.filter in m['id']
392
+ ]
393
+
394
+ if not symbols:
395
+ print(f"No symbols found matching filter {args.filter}")
396
+ sys.exit(1)
397
+
398
+ # In training mode, collect data first
399
+ if args.train:
400
+ print(f"Running in training mode for {len(symbols)} symbols")
401
+ for symbol in symbols:
402
+ scanner.collect_training_sample(symbol, exchange)
403
+
404
+ # After collecting data, train model
405
+ if scanner.train_initial_model():
406
+ print("Training completed successfully")
407
+ else:
408
+ print("Not enough data collected for training")
409
+ sys.exit(0)
410
+
411
+ # In scanning mode, check if we have a trained model
412
+ if not hasattr(scanner.model, 'classes_'):
413
+ print("Warning: No trained model available. Running with basic Ichimoku scanning only.")
414
+
415
+ # Scan symbols
416
+ timeframes = args.timeframes.split(',')
417
+ print(f"Scanning {len(symbols)} symbols on timeframes {timeframes}")
418
+
419
+ for symbol in symbols:
420
+ scanner.scan_symbol(symbol, exchange, timeframes)
training_data.csv ADDED
The diff for this file is too large to render. See raw diff