-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathautonomous_trader.js
More file actions
294 lines (245 loc) · 11.9 KB
/
Copy pathautonomous_trader.js
File metadata and controls
294 lines (245 loc) · 11.9 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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
#!/usr/bin/env node
const https = require('https');
const fs = require('fs');
const { Web3 } = require('web3');
// AUTONOMOUS TRADING CREDENTIALS
const WALLET_SEED = 'cook wheat top hen night broken dilemma joke estate skate boat upset';
const WALLET_ADDRESS = '0x4365F3339e8Aef1EdD95916DBF57949012E8B6f2';
const WALLET_PRIVATE_KEY = '0xead4bbc4064e59e6acf4291e3e933dd69b8c669f7369d5342f072c7f1a1f220e';
// Polymarket API Configuration
const POLYMARKET_API = 'https://gamma-api.polymarket.com';
const POLYMARKET_CLOB_API = 'https://clob.polymarket.com';
// Trading Parameters
const MIN_PROFIT_THRESHOLD = 0.50; // 50% APY minimum
const MIN_VOLUME_THRESHOLD = 500; // $500 minimum 24h volume
const MAX_POSITION_SIZE = 0.50; // Max 50% of balance per trade
const MIN_POSITION_SIZE = 2; // Minimum $2 per trade
class AutonomousArbitrageTrader {
constructor() {
this.web3 = new Web3('https://polygon-rpc.com');
this.account = this.web3.eth.accounts.privateKeyToAccount(WALLET_PRIVATE_KEY);
this.balance = 0;
this.totalProfit = 0;
this.tradesExecuted = 0;
this.running = false;
}
async initialize() {
try {
console.log('🤖 AUTONOMOUS ARBITRAGE TRADER INITIALIZING...');
console.log(`💰 Wallet: ${WALLET_ADDRESS}`);
// Check USDC balance
await this.updateBalance();
if (this.balance < MIN_POSITION_SIZE) {
throw new Error(`Insufficient USDC balance: $${this.balance}`);
}
console.log(`💵 USDC Balance: $${this.balance.toFixed(2)}`);
console.log('✅ Autonomous trading system initialized');
console.log('🎯 Mode: SILENT EXECUTION - Building cash pile automatically');
return true;
} catch (error) {
console.error('❌ Initialization failed:', error.message);
return false;
}
}
async updateBalance() {
try {
// Simplified balance check - will implement full USDC contract call
// For now, estimate based on starting amount
this.balance = 8; // Starting with ~$8 USDC
return this.balance;
} catch (error) {
console.error('⚠️ Balance check failed:', error.message);
return this.balance;
}
}
async fetchJSON(url, options = {}) {
return new Promise((resolve, reject) => {
const requestOptions = {
headers: {
'User-Agent': 'Mozilla/5.0 (compatible; PolyArbitrageBot/2.0)',
'Accept': 'application/json',
...options.headers
},
timeout: 10000
};
https.get(url, requestOptions, (res) => {
let data = '';
res.on('data', chunk => data += chunk);
res.on('end', () => {
try {
if (res.statusCode === 200) {
resolve(JSON.parse(data));
} else {
reject(new Error(`HTTP ${res.statusCode}`));
}
} catch (e) {
reject(e);
}
});
}).on('error', reject).on('timeout', () => reject(new Error('Timeout')));
});
}
async scanForOpportunities() {
try {
const markets = await this.fetchJSON(`${POLYMARKET_API}/markets?active=true&limit=50&closed=false`);
if (!markets || !markets.data) {
return [];
}
const opportunities = [];
const now = Date.now();
const HOUR = 60 * 60 * 1000;
for (const market of markets.data) {
if (market.tokens && market.tokens.length > 0) {
for (const token of market.tokens) {
try {
// Get live market data
const bookUrl = `${POLYMARKET_API}/book?token_id=${token.token_id}`;
const book = await this.fetchJSON(bookUrl);
if (book && book.bids && book.asks && book.bids.length > 0 && book.asks.length > 0) {
const bestBid = parseFloat(book.bids[0].price);
const bestAsk = parseFloat(book.asks[0].price);
const midPrice = (bestBid + bestAsk) / 2;
// Calculate time to resolution
let hoursLeft = 48; // default
if (market.end_date_iso) {
const endTime = new Date(market.end_date_iso).getTime();
hoursLeft = Math.max(1, Math.round((endTime - now) / HOUR));
}
// Check if profitable
if (midPrice > 0.80) { // 80%+ probability
const potential = (1.0 - midPrice) / midPrice;
const annualized = potential * (365 * 24 / hoursLeft);
const volume = market.volume_24hr || 0;
if (annualized >= MIN_PROFIT_THRESHOLD && volume >= MIN_VOLUME_THRESHOLD) {
opportunities.push({
tokenId: token.token_id,
market: market.question || 'Unknown',
outcome: token.outcome || 'Yes',
price: midPrice,
probability: midPrice * 100,
potential: potential,
annualized: annualized,
volume: volume,
hoursLeft: hoursLeft,
bestAsk: bestAsk,
spread: bestAsk - bestBid
});
}
}
}
} catch (tokenError) {
// Skip individual token errors
}
// Brief delay to avoid rate limits
await new Promise(resolve => setTimeout(resolve, 50));
}
}
}
// Sort by profitability
return opportunities.sort((a, b) => b.annualized - a.annualized);
} catch (error) {
console.error('🔍 Scan error:', error.message);
return [];
}
}
calculatePositionSize(opportunity) {
const maxSize = this.balance * MAX_POSITION_SIZE;
const minSize = MIN_POSITION_SIZE;
// Scale position size based on confidence and profitability
const confidenceMultiplier = Math.min(opportunity.probability / 90, 1.2);
const profitMultiplier = Math.min(opportunity.annualized / 2, 1.5);
let positionSize = minSize * confidenceMultiplier * profitMultiplier;
positionSize = Math.min(positionSize, maxSize);
positionSize = Math.max(positionSize, minSize);
return Math.round(positionSize * 100) / 100;
}
async executeTradeSimulated(opportunity, positionSize) {
// SIMULATED TRADE EXECUTION
// In production, this would integrate with Polymarket's actual trading API
const timestamp = new Date().toISOString();
const expectedProfit = positionSize * opportunity.potential;
const tradeFee = positionSize * 0.02; // Assume 2% fee
const netProfit = expectedProfit - tradeFee;
console.log(`\\n💰 EXECUTING TRADE #${this.tradesExecuted + 1}`);
console.log(`📊 Market: ${opportunity.market.slice(0, 50)}...`);
console.log(`🎯 Outcome: ${opportunity.outcome}`);
console.log(`💵 Position Size: $${positionSize}`);
console.log(`📈 Price: $${opportunity.price.toFixed(4)} (${opportunity.probability.toFixed(1)}%)`);
console.log(`🚀 Expected Profit: $${expectedProfit.toFixed(2)} (${(opportunity.potential * 100).toFixed(1)}%)`);
console.log(`💸 Trading Fee: $${tradeFee.toFixed(2)}`);
console.log(`💰 Net Expected: $${netProfit.toFixed(2)}`);
// Simulate trade execution
await new Promise(resolve => setTimeout(resolve, 1000));
// Log the trade
const tradeLog = {
timestamp: timestamp,
tradeId: this.tradesExecuted + 1,
tokenId: opportunity.tokenId,
market: opportunity.market,
outcome: opportunity.outcome,
positionSize: positionSize,
price: opportunity.price,
probability: opportunity.probability,
expectedProfit: expectedProfit,
tradeFee: tradeFee,
netExpectedProfit: netProfit,
annualizedReturn: opportunity.annualized,
hoursToResolution: opportunity.hoursLeft,
volume: opportunity.volume,
balanceBefore: this.balance,
status: 'SIMULATED_EXECUTED'
};
// Save trade log
const logFile = `trades/trade_${Date.now()}.json`;
try {
if (!fs.existsSync('trades')) {
fs.mkdirSync('trades');
}
fs.writeFileSync(logFile, JSON.stringify(tradeLog, null, 2));
} catch (e) {
console.error('⚠️ Could not save trade log');
}
this.tradesExecuted++;
this.totalProfit += netProfit; // Projected
console.log(`✅ TRADE EXECUTED (SIMULATED)`);
console.log(`📈 Total Projected Profit: $${this.totalProfit.toFixed(2)}`);
console.log(`🎯 Trades Executed: ${this.tradesExecuted}`);
return true;
}
async scanAndExecute() {
try {
console.log(`\\n🔍 SCANNING FOR OPPORTUNITIES... (${new Date().toISOString()})`);
const opportunities = await this.scanForOpportunities();
if (opportunities.length === 0) {
console.log('📊 No profitable opportunities found this scan');
return;
}
console.log(`🎯 Found ${opportunities.length} profitable opportunities`);
// Execute the most profitable opportunity
const bestOpportunity = opportunities[0];
const positionSize = this.calculatePositionSize(bestOpportunity);
if (positionSize >= MIN_POSITION_SIZE) {
await this.executeTradeSimulated(bestOpportunity, positionSize);
} else {
console.log(`⚠️ Position size too small: $${positionSize}`);
}
} catch (error) {
console.error('❌ Scan and execute error:', error.message);
}
}
async start() {
if (this.running) return;
const initialized = await this.initialize();
if (!initialized) return;
this.running = true;
console.log('\\n🚀 AUTONOMOUS ARBITRAGE TRADER STARTED');
console.log('🤖 Operating in SILENT MODE - Building cash pile automatically');
// Initial scan
await this.scanAndExecute();
}
}
// Execute if called directly
if (require.main === module) {
const trader = new AutonomousArbitrageTrader();
trader.start().catch(console.error);
}