@@ -10,6 +10,7 @@ import {
1010import { IExchangeNormalizer } from '../interfaces' ;
1111import { addBinaryOutcomes } from '../../utils/market-utils' ;
1212import { buildSourceMetadata } from '../../utils/metadata' ;
13+ import { averageDecimals , complementDecimal , multiplyDecimals , roundDecimalPlaces , subtractDecimals } from '../../utils/decimal-math' ;
1314import { toMarketId , toOutcomeId } from './utils' ;
1415import { TICK_SIZE } from './config' ;
1516import {
@@ -106,11 +107,8 @@ function extractDescription(desc: unknown): string {
106107 return '' ;
107108}
108109
109- /**
110- * Round to 2 decimal places to avoid floating point noise.
111- */
112110function roundPrice ( n : number ) : number {
113- return Math . round ( n * 100 ) / 100 ;
111+ return roundDecimalPlaces ( n , 2 ) ;
114112}
115113
116114// ----------------------------------------------------------------------------
@@ -211,18 +209,20 @@ export class GeminiNormalizer implements IExchangeNormalizer<GeminiRawEvent, Gem
211209 const marketId = toMarketId ( instrumentSymbol ) ;
212210
213211 // Extract prices
214- const bestBid = contract . prices ?. bestBid ? parseFloat ( contract . prices . bestBid ) : 0.5 ;
215- const bestAsk = contract . prices ?. bestAsk ? parseFloat ( contract . prices . bestAsk ) : 0.5 ;
212+ const bestBidRaw = contract . prices ?. bestBid ?? '0.5' ;
213+ const bestAskRaw = contract . prices ?. bestAsk ?? '0.5' ;
214+ const bestBid = parseFloat ( bestBidRaw ) ;
215+ const bestAsk = parseFloat ( bestAskRaw ) ;
216216 const buyYes = contract . prices ?. buy ?. yes ? parseFloat ( contract . prices . buy . yes ) : undefined ;
217217 const sellYes = contract . prices ?. sell ?. yes ? parseFloat ( contract . prices . sell . yes ) : undefined ;
218218 const buyNo = contract . prices ?. buy ?. no ? parseFloat ( contract . prices . buy . no ) : undefined ;
219219 const sellNo = contract . prices ?. sell ?. no ? parseFloat ( contract . prices . sell . no ) : undefined ;
220220 const lastPrice = contract . prices ?. lastTradePrice
221221 ? parseFloat ( contract . prices . lastTradePrice )
222- : ( bestBid + bestAsk ) / 2 ;
222+ : averageDecimals ( bestBidRaw , bestAskRaw ) ;
223223
224224 const yesPriceSource = buyYes ?? sellYes ?? lastPrice ;
225- const noPriceSource = buyNo ?? sellNo ?? ( 1 - yesPriceSource ) ;
225+ const noPriceSource = buyNo ?? sellNo ?? complementDecimal ( yesPriceSource ) ;
226226
227227 const yesPrice = roundPrice ( Math . max ( 0 , Math . min ( 1 , yesPriceSource ) ) ) ;
228228 const noPrice = roundPrice ( Math . max ( 0 , Math . min ( 1 , noPriceSource ) ) ) ;
@@ -325,6 +325,7 @@ export class GeminiNormalizer implements IExchangeNormalizer<GeminiRawEvent, Gem
325325 : 0 ;
326326 const entryPrice = parseFloat ( raw . avgPrice ) ;
327327 const size = parseFloat ( raw . totalQuantity ) ;
328+ const priceDelta = subtractDecimals ( raw . prices ?. bestBid ?? '0' , raw . avgPrice ) ;
328329
329330 return {
330331 marketId : toMarketId ( raw . symbol ) ,
@@ -333,7 +334,7 @@ export class GeminiNormalizer implements IExchangeNormalizer<GeminiRawEvent, Gem
333334 size,
334335 entryPrice,
335336 currentPrice,
336- unrealizedPnL : ( currentPrice - entryPrice ) * size ,
337+ unrealizedPnL : multiplyDecimals ( priceDelta , raw . totalQuantity ) ,
337338 } ;
338339 }
339340}
0 commit comments