feat: refresh exit orders after TP1 and add dry-run harness
This commit is contained in:
103
scripts/dry-run-tp1-test.js
Normal file
103
scripts/dry-run-tp1-test.js
Normal file
@@ -0,0 +1,103 @@
|
||||
process.env.TS_NODE_COMPILER_OPTIONS = JSON.stringify({
|
||||
module: 'CommonJS',
|
||||
moduleResolution: 'node',
|
||||
esModuleInterop: true,
|
||||
allowSyntheticDefaultImports: true,
|
||||
})
|
||||
|
||||
const Module = require('module')
|
||||
const originalRequire = Module.prototype.require
|
||||
Module.prototype.require = function mockHelius(moduleId, ...args) {
|
||||
if (moduleId === 'helius-laserstream' || moduleId.startsWith('helius-laserstream/')) {
|
||||
console.log('⚠️ Mocking helius-laserstream module for dry run')
|
||||
return {}
|
||||
}
|
||||
return originalRequire.apply(this, [moduleId, ...args])
|
||||
}
|
||||
|
||||
require('ts-node/register')
|
||||
|
||||
const { Keypair } = require('@solana/web3.js')
|
||||
const tradesModule = require('../lib/database/trades')
|
||||
|
||||
// Stub Prisma interactions for dry run so we don't need a database
|
||||
tradesModule.getOpenTrades = async () => {
|
||||
console.log('ℹ️ Mock getOpenTrades returning empty list for dry run')
|
||||
return []
|
||||
}
|
||||
tradesModule.updateTradeState = async () => {
|
||||
console.log('ℹ️ Mock updateTradeState no-op')
|
||||
}
|
||||
|
||||
const { getInitializedPositionManager } = require('../lib/trading/position-manager')
|
||||
const driftOrders = require('../lib/drift/orders')
|
||||
|
||||
// Stub Drift order helpers so we avoid needing an on-chain connection
|
||||
driftOrders.cancelAllOrders = async (symbol) => {
|
||||
console.log(`ℹ️ Mock cancelAllOrders invoked for ${symbol}`)
|
||||
return { success: true, cancelledCount: 0 }
|
||||
}
|
||||
|
||||
driftOrders.placeExitOrders = async (options) => {
|
||||
console.log('ℹ️ Mock placeExitOrders called with:', options)
|
||||
return { success: true, signatures: ['MOCK_TP', 'MOCK_SL'] }
|
||||
}
|
||||
|
||||
async function main() {
|
||||
process.env.DRY_RUN = 'true'
|
||||
process.env.DRIFT_ENV = 'devnet'
|
||||
process.env.SOLANA_RPC_URL = process.env.SOLANA_RPC_URL || 'https://api.devnet.solana.com'
|
||||
|
||||
const kp = Keypair.generate()
|
||||
process.env.DRIFT_WALLET_PRIVATE_KEY = JSON.stringify(Array.from(kp.secretKey))
|
||||
|
||||
console.log('🧪 Starting TP1 refresh dry-run test')
|
||||
|
||||
const manager = await getInitializedPositionManager()
|
||||
|
||||
const entryPrice = 150
|
||||
const trade = {
|
||||
id: `dry-run-${Date.now()}`,
|
||||
positionId: 'DRY_RUN_POSITION',
|
||||
symbol: 'SOL-PERP',
|
||||
direction: 'long',
|
||||
entryPrice,
|
||||
entryTime: Date.now(),
|
||||
positionSize: 200,
|
||||
leverage: 10,
|
||||
stopLossPrice: entryPrice * 0.985,
|
||||
tp1Price: entryPrice * 1.004,
|
||||
tp2Price: entryPrice * 1.007,
|
||||
emergencyStopPrice: entryPrice * 0.98,
|
||||
currentSize: 200 * 0.25,
|
||||
tp1Hit: true,
|
||||
tp2Hit: false,
|
||||
slMovedToBreakeven: false,
|
||||
slMovedToProfit: false,
|
||||
trailingStopActive: false,
|
||||
realizedPnL: 10,
|
||||
unrealizedPnL: 0,
|
||||
peakPnL: 12,
|
||||
peakPrice: entryPrice * 1.01,
|
||||
maxFavorableExcursion: 1.2,
|
||||
maxAdverseExcursion: -0.6,
|
||||
maxFavorablePrice: entryPrice * 1.01,
|
||||
maxAdversePrice: entryPrice * 0.99,
|
||||
priceCheckCount: 0,
|
||||
lastPrice: entryPrice,
|
||||
lastUpdateTime: Date.now(),
|
||||
}
|
||||
|
||||
await manager.addTrade(trade)
|
||||
|
||||
console.log('➡️ Invoking handlePostTp1Adjustments...')
|
||||
await manager.handlePostTp1Adjustments(trade, 'dry-run script')
|
||||
|
||||
console.log('✅ Dry run complete. Review logs above for refreshed exit order placement.')
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error('❌ Dry run test failed:', err)
|
||||
process.exit(1)
|
||||
})
|
||||
Reference in New Issue
Block a user