run-modular-strategy.ts 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. #!/usr/bin/env tsx
  2. /**
  3. * Modular Delta Neutral Strategy Entry Point
  4. * Clean, maintainable, and extensible
  5. */
  6. import { ModularDeltaNeutralStrategy } from '../src/strategies/ModularDeltaNeutralStrategy';
  7. interface RunOptions {
  8. /**
  9. * When true (CLI mode), the process will exit automatically after shutdown.
  10. */
  11. exitOnShutdown?: boolean;
  12. }
  13. let activeStrategy: ModularDeltaNeutralStrategy | null = null;
  14. let handlersRegistered = false;
  15. let shutdownInProgress = false;
  16. let exitAfterShutdown = false;
  17. const shutdownSignals: NodeJS.Signals[] = ['SIGINT', 'SIGTERM'];
  18. function ensureProcessHandlers(): void {
  19. if (handlersRegistered) {
  20. return;
  21. }
  22. const requestShutdown = (source: string, exitCode = 0) => {
  23. void performShutdown(source, exitCode);
  24. };
  25. shutdownSignals.forEach((signal) => {
  26. process.on(signal, () => requestShutdown(signal, 0));
  27. });
  28. process.on('uncaughtException', (error: Error) => {
  29. console.error('❌ Uncaught Exception:', error);
  30. requestShutdown('uncaughtException', 1);
  31. });
  32. process.on('unhandledRejection', (reason: unknown, promise: Promise<unknown>) => {
  33. console.error('❌ Unhandled Rejection at:', promise, 'reason:', reason);
  34. requestShutdown('unhandledRejection', 1);
  35. });
  36. handlersRegistered = true;
  37. }
  38. async function performShutdown(source: string, exitCode: number): Promise<void> {
  39. if (shutdownInProgress) {
  40. console.log('\n⚠️ Shutdown already in progress...');
  41. return;
  42. }
  43. shutdownInProgress = true;
  44. console.log(`\n\n📡 Received ${source}, initiating graceful shutdown...`);
  45. const strategy = activeStrategy;
  46. try {
  47. if (strategy) {
  48. await strategy.stop();
  49. }
  50. console.log('👋 Shutdown complete.');
  51. } catch (error) {
  52. console.error('❌ Error during shutdown:', error);
  53. exitCode = exitCode || 1;
  54. } finally {
  55. activeStrategy = null;
  56. shutdownInProgress = false;
  57. if (exitAfterShutdown) {
  58. process.exit(exitCode);
  59. }
  60. }
  61. }
  62. /**
  63. * Main entry point
  64. */
  65. export async function main(options: RunOptions = {}): Promise<void> {
  66. console.log('╔═══════════════════════════════════════════════╗');
  67. console.log('║ Modular Delta Neutral Strategy ║');
  68. console.log('║ Clean Architecture | Maintainable | Scalable ║');
  69. console.log('╚═══════════════════════════════════════════════╝\n');
  70. const strategy = new ModularDeltaNeutralStrategy();
  71. activeStrategy = strategy;
  72. exitAfterShutdown = Boolean(options.exitOnShutdown);
  73. shutdownInProgress = false;
  74. ensureProcessHandlers();
  75. try {
  76. await strategy.initialize();
  77. await strategy.start();
  78. } catch (error) {
  79. console.error('❌ Failed to start strategy:', error);
  80. try {
  81. await strategy.stop();
  82. } catch (stopError) {
  83. console.error('❌ Failed to stop strategy after initialization error:', stopError);
  84. } finally {
  85. activeStrategy = null;
  86. }
  87. throw error;
  88. }
  89. }
  90. // Run the strategy when executed directly from the CLI
  91. if (require.main === module) {
  92. main({ exitOnShutdown: true })
  93. .then(() => {
  94. // keep process alive to allow the trading cycle to run; exit handled by signal shutdown
  95. })
  96. .catch((error) => {
  97. console.error('Fatal error:', error);
  98. process.exit(1);
  99. });
  100. }