@@ -1339,6 +1339,218 @@ export function createDefaultCommands(): CommandDefinition[] {
13391339 }
13401340 } ,
13411341 } ,
1342+ {
1343+ name : 'strategy' ,
1344+ description : 'Create or manage trading strategies' ,
1345+ usage : '/strategy [create|list|delete|templates] [args]' ,
1346+ aliases : [ 'strat' ] ,
1347+ handler : async ( args , ctx ) => {
1348+ const trading = ( ctx as any ) . trading ;
1349+ if ( ! trading ?. builder ) {
1350+ return 'Strategy builder not initialized.' ;
1351+ }
1352+
1353+ const parts = args . trim ( ) . split ( / \s + / ) ;
1354+ const subcommand = parts [ 0 ] ?. toLowerCase ( ) || 'list' ;
1355+ const rest = parts . slice ( 1 ) . join ( ' ' ) ;
1356+
1357+ switch ( subcommand ) {
1358+ case 'templates' : {
1359+ const templates = trading . builder . listTemplates ( ) ;
1360+ const lines = [ 'Available Strategy Templates' , '' ] ;
1361+ for ( const tmpl of templates ) {
1362+ lines . push ( `**${ tmpl . name } **` ) ;
1363+ lines . push ( ` ${ tmpl . description } ` ) ;
1364+ }
1365+ lines . push ( '' , 'Use: /strategy create <description>' ) ;
1366+ return lines . join ( '\n' ) ;
1367+ }
1368+
1369+ case 'create' : {
1370+ if ( ! rest ) {
1371+ return [
1372+ 'Usage: /strategy create <natural language description>' ,
1373+ '' ,
1374+ 'Examples:' ,
1375+ ' /strategy create buy the dip on polymarket when price drops 5%' ,
1376+ ' /strategy create momentum strategy with 10% take profit' ,
1377+ ' /strategy create arbitrage between polymarket and kalshi' ,
1378+ ] . join ( '\n' ) ;
1379+ }
1380+
1381+ const result = trading . builder . parseNaturalLanguage ( rest ) ;
1382+ if ( 'error' in result ) {
1383+ return `Error: ${ result . error } ` ;
1384+ }
1385+
1386+ const validation = trading . builder . validate ( result ) ;
1387+ if ( ! validation . valid ) {
1388+ return `Validation errors:\n${ validation . errors . map ( ( e : string ) => `- ${ e } ` ) . join ( '\n' ) } ` ;
1389+ }
1390+
1391+ // Save the definition
1392+ const defId = trading . builder . saveDefinition ( ctx . session . userId , result ) ;
1393+
1394+ // Create and register the strategy
1395+ const strategy = trading . builder . createStrategy ( result ) ;
1396+ trading . bots . registerStrategy ( strategy ) ;
1397+
1398+ return [
1399+ `Strategy Created: ${ result . name } ` ,
1400+ '' ,
1401+ `ID: ${ strategy . config . id } ` ,
1402+ `Template: ${ result . template } ` ,
1403+ `Platforms: ${ result . platforms . join ( ', ' ) } ` ,
1404+ '' ,
1405+ 'Entry conditions:' ,
1406+ ...result . entry . map ( ( e : any ) => ` - ${ e . type } : ${ e . value } ` ) ,
1407+ '' ,
1408+ 'Exit conditions:' ,
1409+ ...result . exit . map ( ( e : any ) => ` - ${ e . type } : ${ e . value } ` ) ,
1410+ '' ,
1411+ 'Risk:' ,
1412+ ` - Max position: $${ result . risk . maxPositionSize } ` ,
1413+ ` - Stop loss: ${ result . risk . stopLossPct } %` ,
1414+ ` - Take profit: ${ result . risk . takeProfitPct } %` ,
1415+ '' ,
1416+ 'Mode: DRY RUN (use /bot start to begin)' ,
1417+ '' ,
1418+ `Use /bot start ${ strategy . config . id } to start trading.` ,
1419+ ] . join ( '\n' ) ;
1420+ }
1421+
1422+ case 'list' : {
1423+ const definitions = trading . builder . loadDefinitions ( ctx . session . userId ) ;
1424+ if ( definitions . length === 0 ) {
1425+ return 'No strategies saved. Use /strategy create to create one.' ;
1426+ }
1427+
1428+ const lines = [ 'Your Strategies' , '' ] ;
1429+ for ( const def of definitions ) {
1430+ lines . push ( `**${ def . definition . name } ** (${ def . id } )` ) ;
1431+ lines . push ( ` Template: ${ def . definition . template } | Platforms: ${ def . definition . platforms . join ( ', ' ) } ` ) ;
1432+ lines . push ( ` Created: ${ def . createdAt . toLocaleDateString ( ) } ` ) ;
1433+ }
1434+ return lines . join ( '\n' ) ;
1435+ }
1436+
1437+ case 'delete' : {
1438+ if ( ! rest ) {
1439+ return 'Usage: /strategy delete <strategy-id>' ;
1440+ }
1441+ const deleted = trading . builder . deleteDefinition ( ctx . session . userId , rest ) ;
1442+ return deleted ? `Strategy ${ rest } deleted.` : `Strategy ${ rest } not found.` ;
1443+ }
1444+
1445+ default :
1446+ return [
1447+ 'Usage: /strategy [command]' ,
1448+ '' ,
1449+ 'Commands:' ,
1450+ ' create <description> - Create strategy from natural language' ,
1451+ ' list - List your strategies' ,
1452+ ' delete <id> - Delete a strategy' ,
1453+ ' templates - Show available templates' ,
1454+ ] . join ( '\n' ) ;
1455+ }
1456+ } ,
1457+ } ,
1458+ {
1459+ name : 'stream' ,
1460+ description : 'Configure trading activity streaming' ,
1461+ usage : '/stream [on|off|status|channel] [args]' ,
1462+ handler : async ( args , ctx ) => {
1463+ const trading = ( ctx as any ) . trading ;
1464+ if ( ! trading ?. stream ) {
1465+ return 'Trading stream not initialized.' ;
1466+ }
1467+
1468+ const parts = args . trim ( ) . split ( / \s + / ) ;
1469+ const subcommand = parts [ 0 ] ?. toLowerCase ( ) || 'status' ;
1470+ const rest = parts . slice ( 1 ) ;
1471+
1472+ switch ( subcommand ) {
1473+ case 'status' : {
1474+ const config = trading . stream . getConfig ( ) ;
1475+ return [
1476+ 'Trading Stream Status' ,
1477+ '' ,
1478+ `Privacy: ${ config . privacy } ` ,
1479+ `Channels: ${ config . channels . length } ` ,
1480+ `Events: ${ config . events . join ( ', ' ) } ` ,
1481+ '' ,
1482+ 'Privacy settings:' ,
1483+ ` Show platforms: ${ config . showPlatforms } ` ,
1484+ ` Show markets: ${ config . showMarkets } ` ,
1485+ ` Show exact prices: ${ config . showExactPrices } ` ,
1486+ ` Show sizes: ${ config . showSizes } ` ,
1487+ ` Show PnL amounts: ${ config . showPnL } ` ,
1488+ ] . join ( '\n' ) ;
1489+ }
1490+
1491+ case 'on' : {
1492+ // Subscribe to console output
1493+ trading . stream . addChannel ( { type : 'console' , id : 'console' } ) ;
1494+ return 'Streaming enabled (console output). Use /stream webhook <url> to add webhook.' ;
1495+ }
1496+
1497+ case 'off' : {
1498+ trading . stream . removeChannel ( 'console' ) ;
1499+ return 'Streaming disabled.' ;
1500+ }
1501+
1502+ case 'privacy' : {
1503+ const level = rest [ 0 ] ?. toLowerCase ( ) ;
1504+ if ( ! level || ! [ 'public' , 'obscured' , 'private' ] . includes ( level ) ) {
1505+ return 'Usage: /stream privacy [public|obscured|private]' ;
1506+ }
1507+ trading . stream . configure ( { privacy : level } ) ;
1508+ return `Privacy set to: ${ level } ` ;
1509+ }
1510+
1511+ case 'webhook' : {
1512+ const url = rest [ 0 ] ;
1513+ if ( ! url || ! url . startsWith ( 'http' ) ) {
1514+ return 'Usage: /stream webhook <url>' ;
1515+ }
1516+ trading . stream . addChannel ( { type : 'webhook' , id : `wh_${ Date . now ( ) } ` , webhookUrl : url } ) ;
1517+ return `Webhook added: ${ url } ` ;
1518+ }
1519+
1520+ case 'discord' : {
1521+ const url = rest [ 0 ] ;
1522+ if ( ! url || ! url . includes ( 'discord' ) ) {
1523+ return 'Usage: /stream discord <webhook-url>' ;
1524+ }
1525+ trading . stream . addChannel ( { type : 'discord' , id : `discord_${ Date . now ( ) } ` , webhookUrl : url } ) ;
1526+ return 'Discord webhook added.' ;
1527+ }
1528+
1529+ case 'slack' : {
1530+ const url = rest [ 0 ] ;
1531+ if ( ! url || ! url . includes ( 'slack' ) ) {
1532+ return 'Usage: /stream slack <webhook-url>' ;
1533+ }
1534+ trading . stream . addChannel ( { type : 'slack' , id : `slack_${ Date . now ( ) } ` , webhookUrl : url } ) ;
1535+ return 'Slack webhook added.' ;
1536+ }
1537+
1538+ default :
1539+ return [
1540+ 'Usage: /stream [command]' ,
1541+ '' ,
1542+ 'Commands:' ,
1543+ ' status - Show stream configuration' ,
1544+ ' on - Enable console streaming' ,
1545+ ' off - Disable streaming' ,
1546+ ' privacy <level> - Set privacy (public/obscured/private)' ,
1547+ ' webhook <url> - Add webhook endpoint' ,
1548+ ' discord <url> - Add Discord webhook' ,
1549+ ' slack <url> - Add Slack webhook' ,
1550+ ] . join ( '\n' ) ;
1551+ }
1552+ } ,
1553+ } ,
13421554 {
13431555 name : 'trades' ,
13441556 description : 'View trade history and stats' ,
0 commit comments