solanaexpert commited on
Commit
8870588
·
verified ·
1 Parent(s): 63d13bc

Update mltechnicalscanner.py

Browse files

Option added : "--compare" to read the results.txt file and compare to current prices <=> to check if the predictions were ok.

Files changed (1) hide show
  1. mltechnicalscanner.py +155 -26
mltechnicalscanner.py CHANGED
@@ -11,6 +11,7 @@ from sklearn.model_selection import train_test_split
11
  from sklearn.metrics import accuracy_score
12
  import pickle
13
  import warnings
 
14
 
15
  # Suppress warnings
16
  warnings.filterwarnings('ignore')
@@ -26,6 +27,7 @@ class MLTechnicalScanner:
26
  self.model = None
27
  self.model_file = "technical_ml_model.pkl"
28
  self.training_data_file = "training_data.csv"
 
29
  self.min_training_samples = 100
30
  self.load_ml_model()
31
 
@@ -48,33 +50,58 @@ class MLTechnicalScanner:
48
 
49
  # Training data collection
50
  self.training_data = pd.DataFrame(columns=self.feature_columns + ['target'])
51
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  def load_ml_model(self):
53
  """Load trained ML model if exists"""
54
  if os.path.exists(self.model_file):
55
  with open(self.model_file, 'rb') as f:
56
  self.model = pickle.load(f)
57
- print("Loaded trained model from file")
 
 
58
  else:
59
- print("Initializing new model")
 
 
60
  self.model = RandomForestClassifier(n_estimators=100, random_state=42)
61
 
62
  def save_ml_model(self):
63
  """Save trained ML model"""
64
  with open(self.model_file, 'wb') as f:
65
  pickle.dump(self.model, f)
66
- print("Saved model to file")
 
 
67
 
68
  def load_training_data(self):
69
  """Load existing training data if available"""
70
  if os.path.exists(self.training_data_file):
71
  self.training_data = pd.read_csv(self.training_data_file)
72
- print(f"Loaded {len(self.training_data)} training samples")
 
 
73
 
74
  def save_training_data(self):
75
  """Save training data to file"""
76
  self.training_data.to_csv(self.training_data_file, index=False)
77
- print(f"Saved {len(self.training_data)} training samples")
 
 
78
 
79
  def calculate_features(self, df):
80
  """Calculate technical indicators"""
@@ -103,7 +130,9 @@ class MLTechnicalScanner:
103
 
104
  return df
105
  except Exception as e:
106
- print(f"Error calculating features: {str(e)}")
 
 
107
  return None
108
 
109
  def train_initial_model(self):
@@ -123,12 +152,16 @@ class MLTechnicalScanner:
123
  # Evaluate model
124
  preds = self.model.predict(X_test)
125
  accuracy = accuracy_score(y_test, preds)
126
- print(f"Initial model trained with accuracy: {accuracy:.2f}")
 
 
127
 
128
  self.save_ml_model()
129
  return True
130
  else:
131
- print(f"Not enough training data ({len(self.training_data)} samples). Need at least {self.min_training_samples}.")
 
 
132
  return False
133
 
134
  def predict_direction(self, features):
@@ -140,7 +173,9 @@ class MLTechnicalScanner:
140
  features = features[self.feature_columns].values.reshape(1, -1)
141
  return self.model.predict(features)[0]
142
  except Exception as e:
143
- print(f"Prediction error: {str(e)}")
 
 
144
  return 0
145
 
146
  def collect_training_sample(self, symbol, exchange, timeframe='1h'):
@@ -166,13 +201,17 @@ class MLTechnicalScanner:
166
 
167
  new_row = pd.DataFrame([features])
168
  self.training_data = pd.concat([self.training_data, new_row], ignore_index=True)
169
- print(f"Collected training sample for {symbol}")
 
 
170
 
171
  if len(self.training_data) % 10 == 0:
172
  self.save_training_data()
173
 
174
  except Exception as e:
175
- print(f"Error collecting training sample: {str(e)}")
 
 
176
 
177
  def scan_symbol(self, symbol, exchange, timeframes):
178
  """Scan symbol for trading opportunities"""
@@ -214,33 +253,106 @@ class MLTechnicalScanner:
214
  self.alert(symbol, "DOWNTREND", timeframes, price)
215
 
216
  except Exception as e:
217
- print(f"Error scanning {symbol}: {str(e)}")
 
 
218
 
219
  def alert(self, symbol, trend_type, timeframes, current_price):
220
  """Generate alert for detected trend"""
221
- message = f"({trend_type}) detected for {symbol} at price {current_price} on {timeframes} at {datetime.now()}"
 
222
  print(message)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
223
 
224
  # Main execution
225
  if __name__ == "__main__":
226
  parser = argparse.ArgumentParser()
227
- parser.add_argument("-e", "--exchange", help="Exchange name", required=True)
228
- parser.add_argument("-f", "--filter", help="Asset filter", required=True)
229
- parser.add_argument("-tf", "--timeframes", help="Timeframes to scan (comma separated)", required=True)
230
  parser.add_argument("--train", help="Run in training mode", action="store_true")
 
231
  args = parser.parse_args()
232
 
 
 
 
 
 
 
 
 
 
 
 
 
233
  scanner = MLTechnicalScanner(training_mode=args.train)
234
 
 
 
 
235
  exchange = scanner.exchanges.get(args.exchange.lower())
236
  if not exchange:
237
- print(f"Exchange {args.exchange} not supported")
 
 
238
  sys.exit(1)
239
 
240
  try:
241
  markets = exchange.fetch_markets()
242
  except Exception as e:
243
- print(f"Error fetching markets: {str(e)}")
 
 
244
  sys.exit(1)
245
 
246
  symbols = [
@@ -249,25 +361,42 @@ if __name__ == "__main__":
249
  ]
250
 
251
  if not symbols:
252
- print(f"No symbols found matching filter {args.filter}")
 
 
253
  sys.exit(1)
254
 
255
  if args.train:
256
- print(f"Running in training mode for {len(symbols)} symbols")
 
 
257
  for symbol in symbols:
258
  scanner.collect_training_sample(symbol, exchange)
259
 
260
  if scanner.train_initial_model():
261
- print("Training completed successfully")
 
 
262
  else:
263
- print("Not enough data collected for training")
 
 
264
  sys.exit(0)
265
 
266
  if not hasattr(scanner.model, 'classes_'):
267
- print("Warning: No trained model available. Running with basic scanning only.")
 
 
268
 
269
  timeframes = args.timeframes.split(',')
270
- print(f"Scanning {len(symbols)} symbols on timeframes {timeframes}")
 
 
271
 
272
  for symbol in symbols:
273
- scanner.scan_symbol(symbol, exchange, timeframes)
 
 
 
 
 
 
11
  from sklearn.metrics import accuracy_score
12
  import pickle
13
  import warnings
14
+ import re
15
 
16
  # Suppress warnings
17
  warnings.filterwarnings('ignore')
 
27
  self.model = None
28
  self.model_file = "technical_ml_model.pkl"
29
  self.training_data_file = "training_data.csv"
30
+ self.results_file = "results.txt"
31
  self.min_training_samples = 100
32
  self.load_ml_model()
33
 
 
50
 
51
  # Training data collection
52
  self.training_data = pd.DataFrame(columns=self.feature_columns + ['target'])
53
+
54
+ def init_results_file(self):
55
+ """Initialize results file only when starting a new scan"""
56
+ with open(self.results_file, 'w') as f:
57
+ f.write("Scan Results Log\n")
58
+ f.write("="*50 + "\n")
59
+ f.write(f"Scan started at {datetime.now()}\n\n")
60
+
61
+ def log_result(self, message):
62
+ """Log message to results file"""
63
+ try:
64
+ with open(self.results_file, 'a') as f:
65
+ f.write(message + '\n')
66
+ except Exception as e:
67
+ print(f"Error writing to results file: {str(e)}")
68
+
69
  def load_ml_model(self):
70
  """Load trained ML model if exists"""
71
  if os.path.exists(self.model_file):
72
  with open(self.model_file, 'rb') as f:
73
  self.model = pickle.load(f)
74
+ msg = "Loaded trained model from file"
75
+ print(msg)
76
+ self.log_result(msg)
77
  else:
78
+ msg = "Initializing new model"
79
+ print(msg)
80
+ self.log_result(msg)
81
  self.model = RandomForestClassifier(n_estimators=100, random_state=42)
82
 
83
  def save_ml_model(self):
84
  """Save trained ML model"""
85
  with open(self.model_file, 'wb') as f:
86
  pickle.dump(self.model, f)
87
+ msg = "Saved model to file"
88
+ print(msg)
89
+ self.log_result(msg)
90
 
91
  def load_training_data(self):
92
  """Load existing training data if available"""
93
  if os.path.exists(self.training_data_file):
94
  self.training_data = pd.read_csv(self.training_data_file)
95
+ msg = f"Loaded {len(self.training_data)} training samples"
96
+ print(msg)
97
+ self.log_result(msg)
98
 
99
  def save_training_data(self):
100
  """Save training data to file"""
101
  self.training_data.to_csv(self.training_data_file, index=False)
102
+ msg = f"Saved {len(self.training_data)} training samples"
103
+ print(msg)
104
+ self.log_result(msg)
105
 
106
  def calculate_features(self, df):
107
  """Calculate technical indicators"""
 
130
 
131
  return df
132
  except Exception as e:
133
+ error_msg = f"Error calculating features: {str(e)}"
134
+ print(error_msg)
135
+ self.log_result(error_msg)
136
  return None
137
 
138
  def train_initial_model(self):
 
152
  # Evaluate model
153
  preds = self.model.predict(X_test)
154
  accuracy = accuracy_score(y_test, preds)
155
+ msg = f"Initial model trained with accuracy: {accuracy:.2f}"
156
+ print(msg)
157
+ self.log_result(msg)
158
 
159
  self.save_ml_model()
160
  return True
161
  else:
162
+ msg = f"Not enough training data ({len(self.training_data)} samples). Need at least {self.min_training_samples}."
163
+ print(msg)
164
+ self.log_result(msg)
165
  return False
166
 
167
  def predict_direction(self, features):
 
173
  features = features[self.feature_columns].values.reshape(1, -1)
174
  return self.model.predict(features)[0]
175
  except Exception as e:
176
+ error_msg = f"Prediction error: {str(e)}"
177
+ print(error_msg)
178
+ self.log_result(error_msg)
179
  return 0
180
 
181
  def collect_training_sample(self, symbol, exchange, timeframe='1h'):
 
201
 
202
  new_row = pd.DataFrame([features])
203
  self.training_data = pd.concat([self.training_data, new_row], ignore_index=True)
204
+ msg = f"Collected training sample for {symbol}"
205
+ print(msg)
206
+ self.log_result(msg)
207
 
208
  if len(self.training_data) % 10 == 0:
209
  self.save_training_data()
210
 
211
  except Exception as e:
212
+ error_msg = f"Error collecting training sample: {str(e)}"
213
+ print(error_msg)
214
+ self.log_result(error_msg)
215
 
216
  def scan_symbol(self, symbol, exchange, timeframes):
217
  """Scan symbol for trading opportunities"""
 
253
  self.alert(symbol, "DOWNTREND", timeframes, price)
254
 
255
  except Exception as e:
256
+ error_msg = f"Error scanning {symbol}: {str(e)}"
257
+ print(error_msg)
258
+ self.log_result(error_msg)
259
 
260
  def alert(self, symbol, trend_type, timeframes, current_price):
261
  """Generate alert for detected trend"""
262
+ timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
263
+ message = f"({trend_type}) detected for {symbol} at price {current_price} on {timeframes} at {timestamp}"
264
  print(message)
265
+ self.log_result(message)
266
+
267
+ def compare_results(self, exchange_name):
268
+ """Compare previous results with current prices"""
269
+ try:
270
+ if not os.path.exists(self.results_file):
271
+ print("No results file found to compare")
272
+ return
273
+
274
+ exchange = self.exchanges.get(exchange_name.lower())
275
+ if not exchange:
276
+ print(f"Exchange {exchange_name} not supported")
277
+ return
278
+
279
+ # Pattern to extract symbol and price from log entries
280
+ pattern = r"\((.*?)\) detected for (.*?) at price ([\d.]+) on"
281
+
282
+ with open(self.results_file, 'r') as f:
283
+ lines = f.readlines()
284
+
285
+ print("\n=== Price Comparison Report ===")
286
+ print(f"Generated at: {datetime.now()}\n")
287
+
288
+ for line in lines:
289
+ match = re.search(pattern, line)
290
+ if match:
291
+ trend_type = match.group(1)
292
+ symbol = match.group(2)
293
+ old_price = float(match.group(3))
294
+ timestamp = line.split(' at ')[-1].strip()
295
+
296
+ try:
297
+ ticker = exchange.fetch_ticker(symbol)
298
+ current_price = ticker['last']
299
+ price_change = current_price - old_price
300
+ percent_change = (price_change / old_price) * 100
301
+
302
+ print(f"Symbol: {symbol}")
303
+ print(f"Previous: {trend_type} at {old_price} ({timestamp})")
304
+ print(f"Current: {current_price} ({datetime.now().strftime('%Y-%m-%d %H:%M:%S')})")
305
+ print(f"Change: {price_change:.4f} ({percent_change:.2f}%)")
306
+ print("-" * 50)
307
+ except Exception as e:
308
+ print(f"Error fetching current price for {symbol}: {str(e)}")
309
+ continue
310
+
311
+ print("\n=== End of Report ===")
312
+
313
+ except Exception as e:
314
+ print(f"Error comparing results: {str(e)}")
315
 
316
  # Main execution
317
  if __name__ == "__main__":
318
  parser = argparse.ArgumentParser()
319
+ parser.add_argument("-e", "--exchange", help="Exchange name", required=False)
320
+ parser.add_argument("-f", "--filter", help="Asset filter", required=False)
321
+ parser.add_argument("-tf", "--timeframes", help="Timeframes to scan (comma separated)", required=False)
322
  parser.add_argument("--train", help="Run in training mode", action="store_true")
323
+ parser.add_argument("--compare", help="Compare previous results with current prices", action="store_true")
324
  args = parser.parse_args()
325
 
326
+ if args.compare:
327
+ scanner = MLTechnicalScanner()
328
+ if args.exchange:
329
+ scanner.compare_results(args.exchange)
330
+ else:
331
+ print("Please specify an exchange with -e/--exchange when using --compare")
332
+ sys.exit(0)
333
+
334
+ if not all([args.exchange, args.filter, args.timeframes]):
335
+ print("Error: --exchange, --filter, and --timeframes are required when not using --compare")
336
+ sys.exit(1)
337
+
338
  scanner = MLTechnicalScanner(training_mode=args.train)
339
 
340
+ # Initialize results file only for actual scans, not comparisons
341
+ scanner.init_results_file()
342
+
343
  exchange = scanner.exchanges.get(args.exchange.lower())
344
  if not exchange:
345
+ error_msg = f"Exchange {args.exchange} not supported"
346
+ print(error_msg)
347
+ scanner.log_result(error_msg)
348
  sys.exit(1)
349
 
350
  try:
351
  markets = exchange.fetch_markets()
352
  except Exception as e:
353
+ error_msg = f"Error fetching markets: {str(e)}"
354
+ print(error_msg)
355
+ scanner.log_result(error_msg)
356
  sys.exit(1)
357
 
358
  symbols = [
 
361
  ]
362
 
363
  if not symbols:
364
+ error_msg = f"No symbols found matching filter {args.filter}"
365
+ print(error_msg)
366
+ scanner.log_result(error_msg)
367
  sys.exit(1)
368
 
369
  if args.train:
370
+ train_msg = f"Running in training mode for {len(symbols)} symbols"
371
+ print(train_msg)
372
+ scanner.log_result(train_msg)
373
  for symbol in symbols:
374
  scanner.collect_training_sample(symbol, exchange)
375
 
376
  if scanner.train_initial_model():
377
+ success_msg = "Training completed successfully"
378
+ print(success_msg)
379
+ scanner.log_result(success_msg)
380
  else:
381
+ fail_msg = "Not enough data collected for training"
382
+ print(fail_msg)
383
+ scanner.log_result(fail_msg)
384
  sys.exit(0)
385
 
386
  if not hasattr(scanner.model, 'classes_'):
387
+ warn_msg = "Warning: No trained model available. Running with basic scanning only."
388
+ print(warn_msg)
389
+ scanner.log_result(warn_msg)
390
 
391
  timeframes = args.timeframes.split(',')
392
+ scan_msg = f"Scanning {len(symbols)} symbols on timeframes {timeframes}"
393
+ print(scan_msg)
394
+ scanner.log_result(scan_msg)
395
 
396
  for symbol in symbols:
397
+ scanner.scan_symbol(symbol, exchange, timeframes)
398
+
399
+ # Add final summary
400
+ end_msg = f"\nScan completed at {datetime.now()}"
401
+ print(end_msg)
402
+ scanner.log_result(end_msg)