- Removed incorrect exclusion of *.test.ts and *.test.js files - Added coverage/ folder to .gitignore - Removed accidentally committed coverage files Co-authored-by: mindesbunister <32161838+mindesbunister@users.noreply.github.com>
178 lines
6.0 KiB
TypeScript
178 lines
6.0 KiB
TypeScript
/**
|
||
* TP1 Detection Tests
|
||
*
|
||
* Tests for Take Profit 1 detection in Position Manager.
|
||
* TP1 is calculated as ATR × 2.0 (typically ~0.86% at ATR 0.43)
|
||
*
|
||
* Key behaviors tested:
|
||
* - LONG: TP1 triggers when price >= tp1Price
|
||
* - SHORT: TP1 triggers when price <= tp1Price
|
||
* - Must NOT trigger below threshold
|
||
* - Must NOT trigger when price moves against position
|
||
*/
|
||
|
||
import {
|
||
createLongTrade,
|
||
createShortTrade,
|
||
TEST_DEFAULTS,
|
||
calculateExpectedProfitPercent
|
||
} from '../../helpers/trade-factory'
|
||
|
||
describe('TP1 Detection', () => {
|
||
// Test the shouldTakeProfit1 logic extracted from Position Manager
|
||
// We test the pure calculation logic rather than the full Position Manager
|
||
|
||
function shouldTakeProfit1(price: number, trade: { direction: 'long' | 'short', tp1Price: number }): boolean {
|
||
if (trade.direction === 'long') {
|
||
return price >= trade.tp1Price
|
||
} else {
|
||
return price <= trade.tp1Price
|
||
}
|
||
}
|
||
|
||
describe('LONG positions', () => {
|
||
it('should detect TP1 when price reaches +0.86% (ATR 0.43 × 2.0)', () => {
|
||
// Test data: entry $140, TP1 at $141.20 (+0.86%)
|
||
const trade = createLongTrade()
|
||
|
||
expect(trade.tp1Price).toBe(TEST_DEFAULTS.long.tp1)
|
||
|
||
// Price at TP1 should trigger
|
||
const result = shouldTakeProfit1(141.20, trade)
|
||
expect(result).toBe(true)
|
||
|
||
// Verify profit calculation
|
||
const profitPercent = calculateExpectedProfitPercent(140, 141.20, 'long')
|
||
expect(profitPercent).toBeCloseTo(0.857, 1) // ~0.86%
|
||
})
|
||
|
||
it('should detect TP1 when price exceeds tp1Price', () => {
|
||
const trade = createLongTrade()
|
||
|
||
// Price above TP1 should also trigger
|
||
const result = shouldTakeProfit1(142.00, trade)
|
||
expect(result).toBe(true)
|
||
})
|
||
|
||
it('should NOT detect TP1 when price is below threshold (+0.5%)', () => {
|
||
const trade = createLongTrade()
|
||
|
||
// Price at +0.5% ($140.70) should NOT trigger TP1
|
||
const result = shouldTakeProfit1(140.70, trade)
|
||
expect(result).toBe(false)
|
||
|
||
// Verify profit percent is below TP1 threshold
|
||
const profitPercent = calculateExpectedProfitPercent(140, 140.70, 'long')
|
||
expect(profitPercent).toBeCloseTo(0.5, 2)
|
||
expect(profitPercent).toBeLessThan(0.86)
|
||
})
|
||
|
||
it('should NOT detect TP1 when price moves against position (negative)', () => {
|
||
const trade = createLongTrade()
|
||
|
||
// Price drop for LONG should NOT trigger TP1
|
||
const result = shouldTakeProfit1(139.00, trade)
|
||
expect(result).toBe(false)
|
||
|
||
// Verify this is a loss
|
||
const profitPercent = calculateExpectedProfitPercent(140, 139.00, 'long')
|
||
expect(profitPercent).toBeLessThan(0)
|
||
})
|
||
|
||
it('should NOT detect TP1 at entry price', () => {
|
||
const trade = createLongTrade()
|
||
|
||
const result = shouldTakeProfit1(140.00, trade)
|
||
expect(result).toBe(false)
|
||
})
|
||
})
|
||
|
||
describe('SHORT positions', () => {
|
||
it('should detect TP1 when price reaches -0.86% (ATR 0.43 × 2.0)', () => {
|
||
// Test data: entry $140, TP1 at $138.80 (-0.86%)
|
||
const trade = createShortTrade()
|
||
|
||
expect(trade.tp1Price).toBe(TEST_DEFAULTS.short.tp1)
|
||
|
||
// Price at TP1 should trigger
|
||
const result = shouldTakeProfit1(138.80, trade)
|
||
expect(result).toBe(true)
|
||
|
||
// Verify profit calculation (SHORT profits when price drops)
|
||
const profitPercent = calculateExpectedProfitPercent(140, 138.80, 'short')
|
||
expect(profitPercent).toBeCloseTo(0.857, 1) // ~0.86%
|
||
})
|
||
|
||
it('should detect TP1 when price is below tp1Price', () => {
|
||
const trade = createShortTrade()
|
||
|
||
// Price below TP1 should also trigger (better for short)
|
||
const result = shouldTakeProfit1(138.00, trade)
|
||
expect(result).toBe(true)
|
||
})
|
||
|
||
it('should NOT detect TP1 when price is above threshold (-0.5%)', () => {
|
||
const trade = createShortTrade()
|
||
|
||
// Price at -0.5% ($139.30) should NOT trigger TP1
|
||
const result = shouldTakeProfit1(139.30, trade)
|
||
expect(result).toBe(false)
|
||
|
||
// Verify profit percent is below TP1 threshold
|
||
const profitPercent = calculateExpectedProfitPercent(140, 139.30, 'short')
|
||
expect(profitPercent).toBeCloseTo(0.5, 2)
|
||
expect(profitPercent).toBeLessThan(0.86)
|
||
})
|
||
|
||
it('should NOT detect TP1 when price moves against position (rises)', () => {
|
||
const trade = createShortTrade()
|
||
|
||
// Price rise for SHORT should NOT trigger TP1
|
||
const result = shouldTakeProfit1(141.00, trade)
|
||
expect(result).toBe(false)
|
||
|
||
// Verify this is a loss for SHORT
|
||
const profitPercent = calculateExpectedProfitPercent(140, 141.00, 'short')
|
||
expect(profitPercent).toBeLessThan(0)
|
||
})
|
||
|
||
it('should NOT detect TP1 at entry price', () => {
|
||
const trade = createShortTrade()
|
||
|
||
const result = shouldTakeProfit1(140.00, trade)
|
||
expect(result).toBe(false)
|
||
})
|
||
})
|
||
|
||
describe('Edge cases', () => {
|
||
it('should handle exact TP1 price (boundary condition)', () => {
|
||
const longTrade = createLongTrade()
|
||
const shortTrade = createShortTrade()
|
||
|
||
// Exact TP1 price should trigger
|
||
expect(shouldTakeProfit1(longTrade.tp1Price, longTrade)).toBe(true)
|
||
expect(shouldTakeProfit1(shortTrade.tp1Price, shortTrade)).toBe(true)
|
||
})
|
||
|
||
it('should handle custom TP1 prices', () => {
|
||
const trade = createLongTrade({ tp1Price: 145.00 })
|
||
|
||
expect(trade.tp1Price).toBe(145.00)
|
||
expect(shouldTakeProfit1(144.99, trade)).toBe(false)
|
||
expect(shouldTakeProfit1(145.00, trade)).toBe(true)
|
||
expect(shouldTakeProfit1(145.01, trade)).toBe(true)
|
||
})
|
||
|
||
it('should work with different entry prices', () => {
|
||
// ETH-PERP style entry at $3500
|
||
const trade = createLongTrade({
|
||
entryPrice: 3500,
|
||
tp1Price: 3530, // +0.86%
|
||
})
|
||
|
||
expect(shouldTakeProfit1(3529, trade)).toBe(false)
|
||
expect(shouldTakeProfit1(3530, trade)).toBe(true)
|
||
})
|
||
})
|
||
})
|