-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstart.py
More file actions
123 lines (103 loc) · 3.71 KB
/
start.py
File metadata and controls
123 lines (103 loc) · 3.71 KB
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
"""
Main entry point for the market making strategy.
This module sets up logging, imports necessary dependencies,
and initializes the perpetual futures market making strategy.
It also handles graceful shutdown and exception handling.
This is the place where you can define the overrides for the strategy;
pricer and the risk modules.
"""
import logging
import structlog
import argparse
import asyncio
import os
import signal
import traceback
import sys
from strategy import PerpMarketMaker
from pricer_perps import PerpPricer
# Configure structlog
def configure_logging():
logging_level = os.environ.get('LOG_LEVEL', 'INFO').upper()
# Convert string level name to numeric value
numeric_level = getattr(logging, logging_level, logging.INFO)
# Define processors for structlog
processors = [
structlog.stdlib.add_logger_name,
structlog.processors.CallsiteParameterAdder(
[
structlog.processors.CallsiteParameter.PATHNAME,
structlog.processors.CallsiteParameter.LINENO,
structlog.processors.CallsiteParameter.FUNC_NAME,
]
),
structlog.stdlib.add_log_level,
structlog.processors.TimeStamper(fmt='%Y-%m-%d %H:%M:%S.%f'),
structlog.processors.StackInfoRenderer(),
structlog.processors.format_exc_info,
structlog.dev.ConsoleRenderer(), # Use ConsoleRenderer for pretty output
]
# Configure structlog
structlog.configure(
processors=processors,
wrapper_class=structlog.make_filtering_bound_logger(numeric_level),
context_class=dict,
logger_factory=structlog.stdlib.LoggerFactory(),
cache_logger_on_first_use=True,
)
# Configure root logger
logging.basicConfig(
format="%(message)s",
stream=sys.stdout,
level=numeric_level,
)
configure_logging()
parser = argparse.ArgumentParser()
parser.add_argument('--config', default='strategy_settings.yaml')
args = parser.parse_args()
async def shutdown(signal: signal.Signals, loop: asyncio.AbstractEventLoop, my_process: PerpMarketMaker) -> None:
"""
Shutdown the strategy gracefully.
"""
my_process.logger.info(f"Received exit signal {signal.name}...")
my_process.graceful_shutdown()
tasks = [t for t in asyncio.all_tasks() if t is not asyncio.current_task()]
[task.cancel() for task in tasks]
my_process.logger.info(f"Cancelling {len(tasks)} outstanding tasks")
await asyncio.gather(*tasks, return_exceptions=True)
loop.stop()
def handle_exception(loop: asyncio.AbstractEventLoop, context: dict) -> None:
"""
Handle exceptions that are not handled in tasks.
"""
msg = context.get("exception", context["message"])
structlog.get_logger().error("Caught exception", exception=msg)
async def main():
loop=asyncio.get_running_loop()
strategy = PerpMarketMaker(
loop=loop,
PricerClass=PerpPricer,
config_path=args.config
)
# Set up signal handlers
signals = (signal.SIGHUP, signal.SIGTERM, signal.SIGINT)
for s in signals:
loop.add_signal_handler(
s, lambda s=s: asyncio.create_task(shutdown(s, loop, strategy))
)
# Set up exception handler
loop.set_exception_handler(handle_exception)
try:
# Initialize and run your strategy
await strategy.run()
except Exception as e:
strategy.logger.error(f"Error running strategy: {e}")
strategy.logger.error(traceback.format_exc())
finally:
try:
strategy.stop()
except Exception as stop_error:
strategy.logger.error(f"Error stopping strategy: {stop_error}")
return 1
if __name__ == "__main__":
sys.exit(asyncio.run(main()))