Skip to content

Releases: TimelordUK/jspurefix

Importing as external module - Index.ts

26 Jan 21:36
Compare
Choose a tag to compare

https://github.com/TimelordUK/jspurefix/issues/1

now install jspurefix

and import types such as below

import { AsciiSession, MsgView, IJsFixConfig, IJsFixLogger, MsgType, MsgTag } from 'jspurefix'
import { SessionRejectReason, SubscriptionRequestType, TradeRequestStatus, ITradeCaptureReport, ITradeCaptureReportRequest } from 'jspurefix/dist/types/FIX4.4/repo'

// interfaces generated by compiler to make messages easy in an IDE

import { TradeFactory } from './trade-factory'

export class TradeCaptureServer extends AsciiSession {
  private readonly logger: IJsFixLogger
  private readonly fixLog: IJsFixLogger
  private readonly tradeFactory: TradeFactory = new TradeFactory()
  private timerHandle: NodeJS.Timer = null

  constructor (public readonly config: IJsFixConfig) {
    super(config)
    this.logReceivedMsgs = true
    this.logger = config.logFactory.logger(`${this.me}:TradeCaptureServer`)
    this.fixLog = config.logFactory.plain(`jsfix.${config!.description!.application!.name}.txt`)
  }

  protected onApplicationMsg (msgType: string, view: MsgView): void {
    this.logger.info(`${view.toJson()}`)
    switch (msgType) {
      case MsgType.TradeCaptureReportRequest: {
        this.tradeCaptureReportRequest(view.toObject())
        break
      }

      default: {
        const seqNum = view.getTyped(MsgTag.MsgSeqNum)
        this.send(msgType, this.config.factory.reject(msgType, seqNum, `${this.me}: unexpected msg type '${msgType}'`, SessionRejectReason.InvalidMsgType))
        break
      }
    }
  }

  protected onReady (view: MsgView): void {
    // server waits for client to make a request
    this.logger.info('ready for requests.')
  }

  protected onStopped (): void {
    this.logger.info('stopped')
    if (this.timerHandle) {
      clearInterval(this.timerHandle)
    }
  }

  protected onLogon (view: MsgView, user: string, password: string): boolean {
    return true
  }

  // use msgType for example to persist only trade capture messages to database
  protected onDecoded (msgType: string, txt: string): void {
    this.fixLog.info(txt)
  }

  // no delimiter substitution on transmit messages
  protected onEncoded (msgType: string, txt: string): void {
    this.fixLog.info(AsciiSession.asPiped(txt))
  }

  private tradeCaptureReportRequest (tcr: ITradeCaptureReportRequest): void {
    this.logger.info(`received tcr ${tcr.TradeRequestID}`)
    // send back an ack.
    this.send(MsgType.TradeCaptureReportRequestAck, TradeFactory.tradeCaptureReportRequestAck(tcr, TradeRequestStatus.Accepted))
    // send some trades
    const batch: ITradeCaptureReport[] = this.tradeFactory.batchOfTradeCaptureReport()
    batch.forEach((tc: ITradeCaptureReport) => {
      this.send(MsgType.TradeCaptureReport, tc)
    })
    this.send(MsgType.TradeCaptureReportRequestAck, TradeFactory.tradeCaptureReportRequestAck(tcr, TradeRequestStatus.Completed))
    // start sending the odd 'live' trade
    switch (tcr.SubscriptionRequestType) {
      case SubscriptionRequestType.SnapshotAndUpdates: {
        this.timerHandle = setInterval(() => {
          if (Math.random() < 0.4) {
            const tc: ITradeCaptureReport = this.tradeFactory.singleTradeCaptureReport()
            this.send(MsgType.TradeCaptureReport, tc)
          }
        }, 5000)
        break
      }
    }
  }
}

README / Unit Test

25 Nov 16:38
Compare
Choose a tag to compare
  1. slightly reword README description
  2. add unit test for dot notation nested fetch
test('nested view fetch' , () => {
  const legGrpView = view.getView('InstrmtLegGrp.NoLegs')
  expect(legGrpView).toBeTruthy()
  const legGrp: IInstrumentLeg[] = legGrpView.toObject()
  expect(legGrp).toBeTruthy()
  expect(Array.isArray(legGrp))
  expect(legGrp.length).toEqual(2)
})

FIXML sample application

07 Oct 12:02
Compare
Choose a tag to compare

this release fixes compiled fixml interfaces where previously certain fields were not named correctly due to collisions in their abbreviations. An INewSingleOrder should be equivalent whether compiling from fixml or from repo based definitions.

also included is a simple demo app run with npm run http-oms which shows how fximl over http can be used. The message below shows how an object in javascript is rendered into FIXML notation.

  public createOrder (symbol: string, side: Side, qty: number, price: number): INewOrderSingle {
    const id: number = this.id++
    return {
      ClOrdID: `Cli${id}`,
      Account: this.account,
      Side: side,
      Price: price,
      OrdType: OrdType.Limit,
      OrderQtyData: {
        OrderQty: qty
      } as IOrderQtyData,
      Instrument: {
        Symbol: symbol,
        SecurityID: '459200101',
        SecurityIDSource: SecurityIDSource.IsinNumber
      } as IInstrument,
      TimeInForce: TimeInForce.GoodTillCancelGtc
    } as INewOrderSingle
  }
<FIXML>
	<Order ID="Cli1" Acct="TradersRUs" Side="1" Typ="2" Px="100.12" TmInForce="1">
		<Hdr SID="accept-comp" TID="init-comp" SSub="user123" TSub="INC"/>
		<Instrmt Sym="IBM" ID="459200101" Src="4"/>
		<OrdQty Qty="10000"/>
	</Order>
</FIXML>
   public fillOrder (order: INewOrderSingle): IExecutionReport {
    const id: number = this.execId++
    return {
      ClOrdID: order.ClOrdID,
      OrdType: order.OrdType,
      TransactTime: new Date(),
      AvgPx: order.Price,
      LeavesQty: 0,
      LastPx: order.Price,
      ExecType: ExecType.OrderStatus,
      OrdStatus: OrdStatus.Filled,
      ExecID: `exec${id}`,
      Side: order.Side,
      Price: order.Price,
      OrderQtyData: {
        OrderQty: order.OrderQtyData.OrderQty
      } as IOrderQtyData,
      Instrument: {
        Symbol: order.Instrument.Symbol,
        SecurityID: order.Instrument.SecurityID,
        SecurityIDSource: SecurityIDSource.IsinNumber
      } as IInstrument
    } as IExecutionReport
  }

the fixml is sent back to the client :-

<FIXML>
	<ExecRpt ID="Cli1" ExecID="exec1" ExecTyp="I" Stat="2" Side="1" Typ="2" Px="100.12" LastPx="100.12" LeavesQty="0" AvgPx="100.12" TxnTm="2018-10-07T12:16:12.584">
		<Hdr SID="accept-comp" TID="init-comp" TSub="fix"/>
		<Instrmt Sym="IBM" ID="459200101" Src="4"/>
		<OrdQty Qty="10000"/>
	</ExecRpt>
</FIXML>