live market websocket and monitoring wallets
This commit is contained in:
85
strategy_runner.py
Normal file
85
strategy_runner.py
Normal file
@ -0,0 +1,85 @@
|
||||
import argparse
|
||||
import logging
|
||||
import sys
|
||||
import time
|
||||
import pandas as pd
|
||||
import sqlite3
|
||||
import json
|
||||
import os
|
||||
from datetime import datetime, timezone
|
||||
import importlib
|
||||
|
||||
from logging_utils import setup_logging
|
||||
from strategies.base_strategy import BaseStrategy
|
||||
|
||||
class StrategyRunner:
|
||||
"""
|
||||
A generic runner that can execute any strategy that adheres to the
|
||||
BaseStrategy blueprint. It handles the main logic loop, including data
|
||||
loading, signal calculation, status saving, and sleeping.
|
||||
"""
|
||||
|
||||
def __init__(self, strategy_name: str, log_level: str):
|
||||
self.strategy_name = strategy_name
|
||||
self.log_level = log_level
|
||||
self.config = self._load_strategy_config()
|
||||
if not self.config:
|
||||
print(f"FATAL: Strategy '{strategy_name}' not found in configuration.")
|
||||
sys.exit(1)
|
||||
|
||||
# Dynamically import and instantiate the strategy logic class
|
||||
try:
|
||||
module_path, class_name = self.config['class'].rsplit('.', 1)
|
||||
module = importlib.import_module(module_path)
|
||||
StrategyClass = getattr(module, class_name)
|
||||
self.strategy_instance = StrategyClass(strategy_name, self.config['parameters'], self.log_level)
|
||||
except (ImportError, AttributeError, KeyError) as e:
|
||||
print(f"FATAL: Could not load strategy class for '{strategy_name}': {e}")
|
||||
sys.exit(1)
|
||||
|
||||
def _load_strategy_config(self) -> dict:
|
||||
"""Loads the configuration for the specified strategy."""
|
||||
config_path = os.path.join("_data", "strategies.json")
|
||||
try:
|
||||
with open(config_path, 'r') as f:
|
||||
all_configs = json.load(f)
|
||||
return all_configs.get(self.strategy_name)
|
||||
except (FileNotFoundError, json.JSONDecodeError) as e:
|
||||
print(f"FATAL: Could not load strategy configuration: {e}")
|
||||
return None
|
||||
|
||||
def run(self):
|
||||
"""Main loop: loads data, calculates signals, saves status, and sleeps."""
|
||||
logging.info(f"Starting main logic loop for {self.strategy_instance.coin} on {self.strategy_instance.timeframe}.")
|
||||
while True:
|
||||
df = self.strategy_instance.load_data()
|
||||
if df.empty:
|
||||
logging.warning("No data loaded. Waiting 1 minute before retrying...")
|
||||
time.sleep(60)
|
||||
continue
|
||||
|
||||
# The strategy instance calculates signals and updates its internal state
|
||||
self.strategy_instance.calculate_signals_and_state(df.copy())
|
||||
self.strategy_instance._save_status() # Save the new state
|
||||
|
||||
logging.info(f"Current Signal: {self.strategy_instance.current_signal}")
|
||||
|
||||
# Simple 1-minute wait for the next cycle
|
||||
# A more precise timing mechanism could be implemented here if needed
|
||||
time.sleep(60)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="A generic runner for trading strategies.")
|
||||
parser.add_argument("--name", required=True, help="The name of the strategy instance from strategies.json.")
|
||||
parser.add_argument("--log-level", default="normal", choices=['off', 'normal', 'debug'])
|
||||
args = parser.parse_args()
|
||||
|
||||
try:
|
||||
runner = StrategyRunner(strategy_name=args.name, log_level=args.log_level)
|
||||
runner.run()
|
||||
except KeyboardInterrupt:
|
||||
logging.info("Strategy runner stopped.")
|
||||
except Exception as e:
|
||||
logging.error(f"A critical error occurred in the strategy runner: {e}")
|
||||
sys.exit(1)
|
||||
Reference in New Issue
Block a user