← back to Ken
kalshi-dash/place-manual-trade.mjs
66 lines
// One-off DELIBERATE real-money order — mirrors autoTrader's proven v2 signed path.
// Steve, 2026-08-04: "go. trade something today." Bounded, single contract, favorite market.
import crypto from 'crypto';
import pg from 'pg';
const TICKER = process.env.TK || 'KXHIGHLAX-26AUG04-B77.5';
const YES_PRICE_CENTS = parseInt(process.env.PX || '74', 10); // limit bid, crosses the 0.73 ask
const COUNT = parseInt(process.env.CT || '1', 10);
const BASE = 'https://api.elections.kalshi.com/trade-api/v2';
const bertha = new pg.Client({ connectionString: 'postgresql://localhost/bertha_betting?host=/tmp' });
const ken = new pg.Client({ connectionString: 'postgresql://localhost/ken?host=/tmp' });
await bertha.connect(); await ken.connect();
const { rows } = await bertha.query('SELECT config FROM risk_state ORDER BY updated_at DESC LIMIT 1');
const cfg = rows[0].config;
const apiKey = cfg.kalshi_api_key, pem = cfg.kalshi_private_key;
if (cfg.safe_mode) { console.error('ABORT: safe_mode is ON'); process.exit(1); }
if (!apiKey || !pem) { console.error('ABORT: no keys'); process.exit(1); }
function sign(ts, method, path) {
return crypto.sign('sha256', Buffer.from(ts + method.toUpperCase() + path), {
key: pem, padding: crypto.constants.RSA_PKCS1_PSS_PADDING, saltLength: 32,
}).toString('base64');
}
async function kalshi(method, apiPath, body) {
const ts = Date.now().toString();
const sig = sign(ts, method, '/trade-api/v2' + apiPath);
const r = await fetch(BASE + apiPath, {
method,
headers: { 'KALSHI-ACCESS-KEY': apiKey, 'KALSHI-ACCESS-TIMESTAMP': ts,
'KALSHI-ACCESS-SIGNATURE': sig, 'Content-Type': 'application/json', 'Accept': 'application/json' },
body: body ? JSON.stringify(body) : undefined,
});
const text = await r.text(); let d; try { d = JSON.parse(text); } catch { d = { raw: text }; }
if (!r.ok) throw new Error(`HTTP ${r.status}: ${JSON.stringify(d)}`);
return d;
}
const clientOrderId = crypto.randomUUID();
const payload = {
ticker: TICKER,
side: 'bid', // bid = BUY YES
count: COUNT.toFixed(2),
price: (YES_PRICE_CENTS / 100).toFixed(2),
time_in_force: 'good_till_canceled',
self_trade_prevention_type: 'taker_at_cross',
client_order_id: clientOrderId,
};
console.log('PLACING (real money):', JSON.stringify(payload));
const res = await kalshi('POST', '/portfolio/events/orders', payload);
console.log('ORDER RESPONSE:', JSON.stringify(res, null, 2));
const orderId = res.order_id || res.order?.order_id || `ken_${Date.now()}`;
const status = res.order?.status || res.status || 'open';
const costCents = COUNT * YES_PRICE_CENTS;
await ken.query(
`INSERT INTO ken_trades (ticker,event_ticker,title,side,action,price_cents,count,cost_cents,order_id,signal_type,confidence,reasoning,status)
VALUES ($1,$2,$3,'yes','buy',$4,$5,$6,$7,'manual',$8,$9,$10)`,
[TICKER, TICKER.split('-').slice(0,2).join('-'), 'LA daily high 77-78°F band', YES_PRICE_CENTS, COUNT, costCents, orderId, 100,
'Steve directive 2026-08-04: deliberate proof-of-life real order; liquid same-day-settle favorite', status]
).catch(e => console.error('ken_trades insert note:', e.message));
console.log(`\nRECORDED ken_trades: order_id=${orderId} status=${status} cost=$${(costCents/100).toFixed(2)}`);
await bertha.end(); await ken.end();