Files
trading_bot_v4/tests
mindesbunister cf4178251a docs: Add Bug #87 to Common Pitfalls + create state persistence test suite
- Added Bug #87 (Position Manager state lost on restart) to TOP 10 Critical Pitfalls
- Comprehensive documentation with incident details, root cause, fix implementation
- Created state-persistence.test.ts to validate all 18 critical state fields
- Test suite validates tp2Hit, trailingStopActive, peakPrice (critical for runner recovery)
- Testing notes: TypeScript , npm test ⏱ timeout (120s), Docker deployment 
- Real-world validation pending: Next trade with container restart

Bug #87 Impact:
- Financial: ~$18.56 runner profit lost
- Root Cause: Race condition in nested Prisma query
- Fix: 4-step bulletproof atomic persistence with verification
- Status:  DEPLOYED Dec 17, 2025 15:14 UTC (commit 341341d)
2025-12-17 15:25:16 +01:00
..
2025-12-05 00:20:11 +00:00

Position Manager Tests

Overview

Comprehensive integration test suite for the Position Manager (lib/trading/position-manager.ts), which manages ~1,938 lines of critical trading logic handling real capital.

Quick Start

# Run all tests
npm test

# Run tests in watch mode (development)
npm run test:watch

# Run tests with coverage report
npm run test:coverage

# Run tests for CI (with JUnit reporter)
npm run test:ci

Test Structure

tests/
├── setup.ts                          # Global test configuration and mocks
├── helpers/
│   └── trade-factory.ts              # Factory functions for creating mock trades
├── integration/
│   └── position-manager/
│       ├── tp1-detection.test.ts     # Take Profit 1 detection tests
│       ├── breakeven-sl.test.ts      # Breakeven SL after TP1 tests
│       ├── adx-runner-sl.test.ts     # ADX-based runner SL tests
│       ├── trailing-stop.test.ts     # Trailing stop functionality tests
│       ├── edge-cases.test.ts        # Edge cases and common pitfalls
│       ├── price-verification.test.ts # Price verification before TP flags
│       └── decision-helpers.test.ts  # Decision helper function tests
└── README.md                         # This file

Test Coverage

These tests verify the logic of Position Manager functions in isolation:

  • Decision helper functions (shouldStopLoss, shouldTakeProfit1, etc.)
  • Price calculation functions (calculatePrice, calculateProfitPercent)
  • ADX-based SL positioning logic
  • Trailing stop mechanics
  • Token vs USD conversion requirements
  • Price verification requirements

Note: Coverage metrics are calculated against lib/trading/position-manager.ts but will be low because tests extract and validate logic patterns without importing the file directly. This avoids complex mocking while still validating critical trading logic.

The tests extract and validate the pure calculation logic without importing the actual Position Manager, avoiding complex mocking of:

  • Drift blockchain connections
  • Pyth price feeds
  • Database operations
  • WebSocket subscriptions

This approach:

  1. Validates critical trading logic is correct
  2. Prevents regression of known bugs (Common Pitfalls)
  3. Enables safe refactoring of calculation functions
  4. Runs quickly without external dependencies

Test Data Standards

All tests use standardized test data based on actual trading conditions:

TEST_DEFAULTS = {
  entry: 140.00,      // Entry price
  atr: 0.43,          // ATR value
  adx: 26.9,          // ADX (strong trend)
  qualityScore: 95,   // Signal quality
  positionSize: 8000, // Position size USD
  leverage: 15,       // Leverage multiplier
  
  // LONG targets
  long: {
    tp1: 141.20,      // +0.86%
    tp2: 142.41,      // +1.72%
    sl: 138.71,       // -0.92%
    emergencySl: 137.20, // -2%
  },
  
  // SHORT targets
  short: {
    tp1: 138.80,      // -0.86%
    tp2: 137.59,      // -1.72%
    sl: 141.29,       // +0.92%
    emergencySl: 142.80, // +2%
  },
}

Common Pitfalls Covered

These tests specifically prevent known bugs documented in the codebase:

Pitfall # Issue Test File
#24 Position.size as tokens, not USD edge-cases.test.ts
#43 TP1 false detection without price check price-verification.test.ts
#45 Wrong entry price for breakeven SL breakeven-sl.test.ts
#52 ADX-based runner SL positioning adx-runner-sl.test.ts
#54 MAE/MFE as percentages, not dollars edge-cases.test.ts
#67 Duplicate closures (atomic deduplication) Covered by mock structure

Test Helpers

Trade Factory (tests/helpers/trade-factory.ts)

import { createLongTrade, createShortTrade, createTradeAfterTP1, createTradeAfterTP2 } from '../helpers/trade-factory'

// Create a basic LONG trade
const longTrade = createLongTrade()

// Create a SHORT trade with custom entry
const shortTrade = createShortTrade({ entryPrice: 150 })

// Create a trade after TP1 hit (40% runner remaining)
const runnerTrade = createTradeAfterTP1('long')

// Create a trade with trailing stop active
const trailingTrade = createTradeAfterTP2('short')

Custom Matchers

// Check if value is within a range
expect(0.86).toBeWithinRange(0.8, 0.9) // passes

Why These Tests Matter

  1. Financial Protection: Position Manager handles real money ($540+ capital). Bugs cost real dollars.

  2. Regression Prevention: 71+ documented bugs in the codebase. Tests prevent reintroduction.

  3. Safe Refactoring: With test coverage, code can be improved without fear of breaking existing functionality.

  4. Documentation: Tests serve as executable documentation of expected behavior.

  5. CI/CD Pipeline: Automated testing ensures changes don't break critical trading logic.

Writing New Tests

Guidelines

  1. Use Factories: Always use createLongTrade() or createShortTrade() instead of manual object creation
  2. Test Both Directions: Every price-based test should cover both LONG and SHORT positions
  3. Test Edge Cases: Include boundary conditions and error scenarios
  4. Clear Names: Test names should describe the exact behavior being tested
  5. Reference Pitfalls: When testing a known bug, reference the pitfall number in comments

Example Test

import { createLongTrade, createShortTrade, TEST_DEFAULTS } from '../../helpers/trade-factory'

describe('New Feature', () => {
  it('should handle LONG position correctly', () => {
    const trade = createLongTrade()
    // ... test logic
    expect(result).toBe(expected)
  })
  
  it('should handle SHORT position correctly', () => {
    const trade = createShortTrade()
    // ... test logic
    expect(result).toBe(expected)
  })
  
  // Reference known bugs
  it('should NOT trigger false positive (Pitfall #XX)', () => {
    // ... regression test
  })
})

Mocked Dependencies

The test setup mocks external dependencies to isolate tests:

  • Drift Service: No actual blockchain calls
  • Pyth Price Monitor: No WebSocket connections
  • Database Operations: No actual DB queries
  • Telegram Notifications: No actual messages sent
  • Drift Orders: No actual order placement

Running Specific Tests

# Run a specific test file
npm test -- tests/integration/position-manager/tp1-detection.test.ts

# Run tests matching a pattern
npm test -- --testNamePattern="LONG"

# Run tests in a specific directory
npm test -- tests/integration/position-manager/

CI Integration

Tests run automatically in CI with:

  • JUnit XML reports for test results
  • Coverage reports in HTML and text formats

Run tests with coverage report:

npm run test:coverage

Run tests in CI mode with JUnit reporter:

npm run test:ci