@@ -189,7 +189,7 @@ describe('UTA — getState', () => {
189189 broker . setPositions ( [ makePosition ( ) ] )
190190
191191 // Push a limit order to create a pending entry in git history
192- uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , symbol : 'AAPL' , side : 'buy ' , type : 'limit ' , qty : 5 , price : 145 } )
192+ uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , symbol : 'AAPL' , action : 'BUY ' , orderType : 'LMT ' , totalQuantity : 5 , lmtPrice : 145 } )
193193 uta . commit ( 'limit buy' )
194194 await uta . push ( )
195195
@@ -242,98 +242,126 @@ describe('UTA — stagePlaceOrder', () => {
242242 ( { uta } = createUTA ( ) )
243243 } )
244244
245- it ( 'maps buy side to BUY action' , ( ) => {
246- uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , side : 'buy ' , type : 'market ' , qty : 10 } )
245+ it ( 'sets BUY action' , ( ) => {
246+ uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , action : 'BUY ' , orderType : 'MKT ' , totalQuantity : 10 } )
247247 const { order } = getStagedPlaceOrder ( uta )
248248 expect ( order . action ) . toBe ( 'BUY' )
249249 } )
250250
251- it ( 'maps sell side to SELL action' , ( ) => {
252- uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , side : 'sell ' , type : 'market ' , qty : 10 } )
251+ it ( 'sets SELL action' , ( ) => {
252+ uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , action : 'SELL ' , orderType : 'MKT ' , totalQuantity : 10 } )
253253 const { order } = getStagedPlaceOrder ( uta )
254254 expect ( order . action ) . toBe ( 'SELL' )
255255 } )
256256
257- it ( 'maps order types correctly' , ( ) => {
258- const cases : Array < [ string , string ] > = [
259- [ 'market' , 'MKT' ] ,
260- [ 'limit' , 'LMT' ] ,
261- [ 'stop' , 'STP' ] ,
262- [ 'stop_limit' , 'STP LMT' ] ,
263- [ 'trailing_stop' , 'TRAIL' ] ,
264- ]
265- for ( const [ input , expected ] of cases ) {
257+ it ( 'passes order types through' , ( ) => {
258+ const types = [ 'MKT' , 'LMT' , 'STP' , 'STP LMT' , 'TRAIL' ]
259+ for ( const orderType of types ) {
266260 const { uta : u } = createUTA ( )
267- u . stagePlaceOrder ( { aliceId : 'mock-paper|X' , side : 'buy ' , type : input , qty : 1 } )
261+ u . stagePlaceOrder ( { aliceId : 'mock-paper|X' , action : 'BUY ' , orderType , totalQuantity : 1 } )
268262 const { order } = getStagedPlaceOrder ( u )
269- expect ( order . orderType ) . toBe ( expected )
263+ expect ( order . orderType ) . toBe ( orderType )
270264 }
271265 } )
272266
273- it ( 'maps qty to totalQuantity as Decimal' , ( ) => {
274- uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , side : 'buy ' , type : 'market ' , qty : 42 } )
267+ it ( 'sets totalQuantity as Decimal' , ( ) => {
268+ uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , action : 'BUY ' , orderType : 'MKT ' , totalQuantity : 42 } )
275269 const { order } = getStagedPlaceOrder ( uta )
276270 expect ( order . totalQuantity ) . toBeInstanceOf ( Decimal )
277271 expect ( order . totalQuantity . toNumber ( ) ) . toBe ( 42 )
278272 } )
279273
280- it ( 'maps notional to cashQty' , ( ) => {
281- uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , side : 'buy ' , type : 'market ' , notional : 5000 } )
274+ it ( 'sets cashQty' , ( ) => {
275+ uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , action : 'BUY ' , orderType : 'MKT ' , cashQty : 5000 } )
282276 const { order } = getStagedPlaceOrder ( uta )
283277 expect ( order . cashQty ) . toBe ( 5000 )
284278 } )
285279
286- it ( 'maps price to lmtPrice and stopPrice to auxPrice' , ( ) => {
287- uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , side : 'buy ' , type : 'stop_limit ' , qty : 10 , price : 150 , stopPrice : 145 } )
280+ it ( 'sets lmtPrice and auxPrice' , ( ) => {
281+ uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , action : 'BUY ' , orderType : 'STP LMT ' , totalQuantity : 10 , lmtPrice : 150 , auxPrice : 145 } )
288282 const { order } = getStagedPlaceOrder ( uta )
289283 expect ( order . lmtPrice ) . toBe ( 150 )
290284 expect ( order . auxPrice ) . toBe ( 145 )
291285 } )
292286
293- it ( 'maps trailingAmount to trailStopPrice (not auxPrice) ' , ( ) => {
294- uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , side : 'sell ' , type : 'trailing_stop ' , qty : 10 , trailingAmount : 5 } )
287+ it ( 'auxPrice sets trailing offset for TRAIL orders ' , ( ) => {
288+ uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , action : 'SELL ' , orderType : 'TRAIL ' , totalQuantity : 10 , auxPrice : 5 } )
295289 const { order } = getStagedPlaceOrder ( uta )
296- expect ( order . trailStopPrice ) . toBe ( 5 )
290+ expect ( order . auxPrice ) . toBe ( 5 )
297291 expect ( order . orderType ) . toBe ( 'TRAIL' )
298292 } )
299293
300- it ( 'trailingAmount and stopPrice use separate fields ' , ( ) => {
301- uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , side : 'sell ' , type : 'trailing_stop ' , qty : 10 , stopPrice : 145 , trailingAmount : 5 } )
294+ it ( 'TRAIL order with trailStopPrice and auxPrice ' , ( ) => {
295+ uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , action : 'SELL ' , orderType : 'TRAIL ' , totalQuantity : 10 , trailStopPrice : 145 , auxPrice : 5 } )
302296 const { order } = getStagedPlaceOrder ( uta )
303- expect ( order . auxPrice ) . toBe ( 145 )
304- expect ( order . trailStopPrice ) . toBe ( 5 )
297+ expect ( order . trailStopPrice ) . toBe ( 145 )
298+ expect ( order . auxPrice ) . toBe ( 5 )
305299 } )
306300
307- it ( 'maps trailingPercent to trailingPercent' , ( ) => {
308- uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , side : 'sell ' , type : 'trailing_stop ' , qty : 10 , trailingPercent : 2.5 } )
301+ it ( 'sets trailingPercent' , ( ) => {
302+ uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , action : 'SELL ' , orderType : 'TRAIL ' , totalQuantity : 10 , trailingPercent : 2.5 } )
309303 const { order } = getStagedPlaceOrder ( uta )
310304 expect ( order . trailingPercent ) . toBe ( 2.5 )
311305 } )
312306
313- it ( 'defaults timeInForce to DAY' , ( ) => {
314- uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , side : 'buy ' , type : 'market ' , qty : 10 } )
307+ it ( 'defaults tif to DAY' , ( ) => {
308+ uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , action : 'BUY ' , orderType : 'MKT ' , totalQuantity : 10 } )
315309 const { order } = getStagedPlaceOrder ( uta )
316310 expect ( order . tif ) . toBe ( 'DAY' )
317311 } )
318312
319- it ( 'allows overriding timeInForce ' , ( ) => {
320- uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , side : 'buy ' , type : 'limit ' , qty : 10 , price : 150 , timeInForce : 'gtc ' } )
313+ it ( 'allows overriding tif ' , ( ) => {
314+ uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , action : 'BUY ' , orderType : 'LMT ' , totalQuantity : 10 , lmtPrice : 150 , tif : 'GTC ' } )
321315 const { order } = getStagedPlaceOrder ( uta )
322316 expect ( order . tif ) . toBe ( 'GTC' )
323317 } )
324318
325- it ( 'maps extendedHours to outsideRth' , ( ) => {
326- uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , side : 'buy ' , type : 'limit ' , qty : 10 , price : 150 , extendedHours : true } )
319+ it ( 'sets outsideRth' , ( ) => {
320+ uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , action : 'BUY ' , orderType : 'LMT ' , totalQuantity : 10 , lmtPrice : 150 , outsideRth : true } )
327321 const { order } = getStagedPlaceOrder ( uta )
328322 expect ( order . outsideRth ) . toBe ( true )
329323 } )
330324
331325 it ( 'sets aliceId and symbol on contract' , ( ) => {
332- uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , symbol : 'AAPL' , side : 'buy ' , type : 'market ' , qty : 10 } )
326+ uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , symbol : 'AAPL' , action : 'BUY ' , orderType : 'MKT ' , totalQuantity : 10 } )
333327 const { contract } = getStagedPlaceOrder ( uta )
334328 expect ( contract . aliceId ) . toBe ( 'mock-paper|AAPL' )
335329 expect ( contract . symbol ) . toBe ( 'AAPL' )
336330 } )
331+
332+ it ( 'sets tpsl with takeProfit only' , ( ) => {
333+ uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , action : 'BUY' , orderType : 'MKT' , totalQuantity : 10 , takeProfit : { price : '160' } } )
334+ const staged = uta . status ( ) . staged
335+ const op = staged [ 0 ] as Extract < Operation , { action : 'placeOrder' } >
336+ expect ( op . tpsl ) . toEqual ( { takeProfit : { price : '160' } , stopLoss : undefined } )
337+ } )
338+
339+ it ( 'sets tpsl with stopLoss only' , ( ) => {
340+ uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , action : 'BUY' , orderType : 'MKT' , totalQuantity : 10 , stopLoss : { price : '140' } } )
341+ const staged = uta . status ( ) . staged
342+ const op = staged [ 0 ] as Extract < Operation , { action : 'placeOrder' } >
343+ expect ( op . tpsl ) . toEqual ( { takeProfit : undefined , stopLoss : { price : '140' } } )
344+ } )
345+
346+ it ( 'sets tpsl with both TP and SL' , ( ) => {
347+ uta . stagePlaceOrder ( {
348+ aliceId : 'mock-paper|AAPL' , action : 'BUY' , orderType : 'MKT' , totalQuantity : 10 ,
349+ takeProfit : { price : '160' } , stopLoss : { price : '140' , limitPrice : '139.50' } ,
350+ } )
351+ const staged = uta . status ( ) . staged
352+ const op = staged [ 0 ] as Extract < Operation , { action : 'placeOrder' } >
353+ expect ( op . tpsl ) . toEqual ( {
354+ takeProfit : { price : '160' } ,
355+ stopLoss : { price : '140' , limitPrice : '139.50' } ,
356+ } )
357+ } )
358+
359+ it ( 'omits tpsl when neither TP nor SL provided' , ( ) => {
360+ uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , action : 'BUY' , orderType : 'MKT' , totalQuantity : 10 } )
361+ const staged = uta . status ( ) . staged
362+ const op = staged [ 0 ] as Extract < Operation , { action : 'placeOrder' } >
363+ expect ( op . tpsl ) . toBeUndefined ( )
364+ } )
337365} )
338366
339367// ==================== stageModifyOrder ====================
@@ -345,8 +373,8 @@ describe('UTA — stageModifyOrder', () => {
345373 ( { uta } = createUTA ( ) )
346374 } )
347375
348- it ( 'maps provided fields to Partial<Order>' , ( ) => {
349- uta . stageModifyOrder ( { orderId : 'ord-1' , qty : 20 , price : 155 , type : 'limit ' , timeInForce : 'gtc ' } )
376+ it ( 'sets provided fields on Partial<Order>' , ( ) => {
377+ uta . stageModifyOrder ( { orderId : 'ord-1' , totalQuantity : 20 , lmtPrice : 155 , orderType : 'LMT ' , tif : 'GTC ' } )
350378 const staged = uta . status ( ) . staged
351379 expect ( staged ) . toHaveLength ( 1 )
352380 const op = staged [ 0 ] as Extract < Operation , { action : 'modifyOrder' } >
@@ -360,7 +388,7 @@ describe('UTA — stageModifyOrder', () => {
360388 } )
361389
362390 it ( 'omits fields not provided' , ( ) => {
363- uta . stageModifyOrder ( { orderId : 'ord-1' , price : 160 } )
391+ uta . stageModifyOrder ( { orderId : 'ord-1' , lmtPrice : 160 } )
364392 const staged = uta . status ( ) . staged
365393 const op = staged [ 0 ] as Extract < Operation , { action : 'modifyOrder' } >
366394 expect ( op . changes . lmtPrice ) . toBe ( 160 )
@@ -425,23 +453,23 @@ describe('UTA — git flow', () => {
425453 } )
426454
427455 it ( 'push throws when not committed' , async ( ) => {
428- uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , side : 'buy ' , type : 'market ' , qty : 10 } )
456+ uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , action : 'BUY ' , orderType : 'MKT ' , totalQuantity : 10 } )
429457 await expect ( uta . push ( ) ) . rejects . toThrow ( 'please commit first' )
430458 } )
431459
432460 it ( 'executes multiple operations in a single push' , async ( ) => {
433461 const { uta : u , broker : b } = createUTA ( )
434462 const spy = vi . spyOn ( b , 'placeOrder' )
435- u . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , side : 'buy ' , type : 'market ' , qty : 10 } )
436- u . stagePlaceOrder ( { aliceId : 'mock-paper|MSFT' , symbol : 'MSFT' , side : 'buy ' , type : 'market ' , qty : 5 } )
463+ u . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , action : 'BUY ' , orderType : 'MKT ' , totalQuantity : 10 } )
464+ u . stagePlaceOrder ( { aliceId : 'mock-paper|MSFT' , symbol : 'MSFT' , action : 'BUY ' , orderType : 'MKT ' , totalQuantity : 5 } )
437465 u . commit ( 'buy both' )
438466 await u . push ( )
439467
440468 expect ( spy ) . toHaveBeenCalledTimes ( 2 )
441469 } )
442470
443471 it ( 'clears staging area after push' , async ( ) => {
444- uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , side : 'buy ' , type : 'market ' , qty : 10 } )
472+ uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , action : 'BUY ' , orderType : 'MKT ' , totalQuantity : 10 } )
445473 uta . commit ( 'buy' )
446474 await uta . push ( )
447475
@@ -462,7 +490,7 @@ describe('UTA — sync', () => {
462490 const { uta, broker } = createUTA ( )
463491
464492 // Limit order → MockBroker keeps it pending naturally
465- uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , symbol : 'AAPL' , side : 'buy ' , type : 'limit ' , qty : 10 , price : 150 } )
493+ uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , symbol : 'AAPL' , action : 'BUY ' , orderType : 'LMT ' , totalQuantity : 10 , lmtPrice : 150 } )
466494 uta . commit ( 'limit buy' )
467495 const pushResult = await uta . push ( )
468496 const orderId = pushResult . submitted [ 0 ] ?. orderId
@@ -481,7 +509,7 @@ describe('UTA — sync', () => {
481509 const { uta, broker } = createUTA ( )
482510
483511 // Limit order → pending
484- uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , symbol : 'AAPL' , side : 'buy ' , type : 'limit ' , qty : 10 , price : 150 } )
512+ uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , symbol : 'AAPL' , action : 'BUY ' , orderType : 'LMT ' , totalQuantity : 10 , lmtPrice : 150 } )
485513 uta . commit ( 'limit buy' )
486514 const pushResult = await uta . push ( )
487515 const orderId = pushResult . submitted [ 0 ] ?. orderId
@@ -503,7 +531,7 @@ describe('UTA — guards', () => {
503531 } )
504532 const spy = vi . spyOn ( broker , 'placeOrder' )
505533
506- uta . stagePlaceOrder ( { aliceId : 'mock-paper|TSLA' , symbol : 'TSLA' , side : 'buy ' , type : 'market ' , qty : 10 } )
534+ uta . stagePlaceOrder ( { aliceId : 'mock-paper|TSLA' , symbol : 'TSLA' , action : 'BUY ' , orderType : 'MKT ' , totalQuantity : 10 } )
507535 uta . commit ( 'buy TSLA (should be blocked)' )
508536 const result = await uta . push ( )
509537
@@ -518,7 +546,7 @@ describe('UTA — guards', () => {
518546 } )
519547 const spy = vi . spyOn ( broker , 'placeOrder' )
520548
521- uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , symbol : 'AAPL' , side : 'buy ' , type : 'market ' , qty : 10 } )
549+ uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , symbol : 'AAPL' , action : 'BUY ' , orderType : 'MKT ' , totalQuantity : 10 } )
522550 uta . commit ( 'buy AAPL (allowed)' )
523551 await uta . push ( )
524552
@@ -532,7 +560,7 @@ describe('UTA — constructor', () => {
532560 it ( 'restores from savedState' , async ( ) => {
533561 // Create a UTA, push a commit, export state
534562 const { uta : original } = createUTA ( )
535- original . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , symbol : 'AAPL' , side : 'buy ' , type : 'market ' , qty : 10 } )
563+ original . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , symbol : 'AAPL' , action : 'BUY ' , orderType : 'MKT ' , totalQuantity : 10 } )
536564 original . commit ( 'initial buy' )
537565 await original . push ( )
538566
@@ -660,7 +688,7 @@ describe('UTA — health tracking', () => {
660688 await expect ( uta . getAccount ( ) ) . rejects . toThrow ( )
661689 }
662690
663- uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , side : 'buy ' , type : 'market ' , qty : 10 } )
691+ uta . stagePlaceOrder ( { aliceId : 'mock-paper|AAPL' , action : 'BUY ' , orderType : 'MKT ' , totalQuantity : 10 } )
664692 uta . commit ( 'buy AAPL' )
665693 await expect ( uta . push ( ) ) . rejects . toThrow ( / o f f l i n e / )
666694 await uta . close ( )
0 commit comments