All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.fluxtion.server.lib.pnl.calculator.FluxtionPnlCalculatorBuilder Maven / Gradle / Ivy

/*
 *
 *  * SPDX-FileCopyrightText: © 2024 Gregory Higgins 
 *  * SPDX-License-Identifier: AGPL-3.0-only
 *
 */

package com.fluxtion.server.lib.pnl.calculator;

import com.fluxtion.compiler.EventProcessorConfig;
import com.fluxtion.compiler.FluxtionCompilerConfig;
import com.fluxtion.compiler.FluxtionGraphBuilder;
import com.fluxtion.compiler.builder.dataflow.DataFlow;
import com.fluxtion.compiler.builder.dataflow.FlowBuilder;
import com.fluxtion.compiler.builder.dataflow.GroupByFlowBuilder;
import com.fluxtion.compiler.builder.dataflow.JoinFlowBuilder;
import com.fluxtion.runtime.dataflow.groupby.GroupBy;
import com.fluxtion.runtime.event.Signal;
import com.fluxtion.server.lib.pnl.*;
import com.fluxtion.server.lib.pnl.dto.DtoHelper;
import com.fluxtion.server.lib.pnl.refdata.Instrument;
import lombok.Getter;

import static com.fluxtion.server.lib.pnl.PnlCalculator.GLOBAL_NET_MTM_SINK;
import static com.fluxtion.server.lib.pnl.PnlCalculator.INSTRUMENT_NET_MTM_SINK;

/**
 * Builds the {@link FluxtionPnlCalculator} AOT using the Fluxtion maven plugin.
 * 

* This build can be extended with a subclass or used as a utility to build a graph with the streaming nodes available * through accessors */ @Getter public class FluxtionPnlCalculatorBuilder implements FluxtionGraphBuilder { private EventProcessorConfig eventProcessorConfig; private FlowBuilder positionUpdateEob; private FlowBuilder positionSnapshotReset; private FlowBuilder tradeStream; private FlowBuilder tradeBatchStream; private GroupByFlowBuilder instrumentFeeMap; private GroupByFlowBuilder dealtAndContraInstPosition; private GroupByFlowBuilder contraAndDealtInstPosition; private GroupByFlowBuilder dealtOnlyInstPosition; private GroupByFlowBuilder contraOnlyInstPosition; private DerivedRateNode derivedRateNode; private EventFeedConnector eventFeedConnector; public static FluxtionPnlCalculatorBuilder buildPnlCalculator(EventProcessorConfig config) { FluxtionPnlCalculatorBuilder calculatorBuilder = new FluxtionPnlCalculatorBuilder(); calculatorBuilder.buildGraph(config); return calculatorBuilder; } @Override public void configureGeneration(FluxtionCompilerConfig compilerConfig) { compilerConfig.setClassName("FluxtionPnlCalculator"); compilerConfig.setPackageName("com.fluxtion.server.lib.pnl.calculator"); } @Override public void buildGraph(EventProcessorConfig eventProcessorConfig) { this.eventProcessorConfig = eventProcessorConfig; buildSharedNodes(); buildTradeStream(); buildPositionMap(); buildInstrumentFeeMap(); buildGlobalMtm(); buildInstrumentMtm(); //no buffer/trigger support required on this processor // eventProcessorConfig.addEventAudit(); eventProcessorConfig.setSupportBufferAndTrigger(false); } private void buildSharedNodes() { positionUpdateEob = DataFlow.subscribeToSignal("positionUpdate"); positionSnapshotReset = DataFlow.subscribeToSignal("positionSnapshotReset"); derivedRateNode = eventProcessorConfig.addNode(new DerivedRateNode(), "derivedRateNode"); eventFeedConnector = eventProcessorConfig.addNode(new EventFeedConnector(), "eventFeedBatcher"); } private void buildTradeStream() { tradeBatchStream = DataFlow.subscribe(TradeBatch.class).flatMap(TradeBatch::getTrades); tradeStream = DataFlow.subscribe(Trade.class).merge(tradeBatchStream); } private void buildPositionMap() { //position by instrument aggregates dealt and contra quantities dealtAndContraInstPosition = tradeStream .groupBy(Trade::getDealtInstrument, SingleInstrumentPosMtmAggregate::dealt) .resetTrigger(positionSnapshotReset); contraAndDealtInstPosition = tradeStream .groupBy(Trade::getContraInstrument, SingleInstrumentPosMtmAggregate::contra) .resetTrigger(positionSnapshotReset); //position by instrument aggregates single side, either dealt and contra quantity dealtOnlyInstPosition = tradeStream .groupBy(Trade::getDealtInstrument, InstrumentPosMtmAggregate::dealt) .resetTrigger(positionSnapshotReset) .publishTrigger(positionSnapshotReset); contraOnlyInstPosition = tradeStream .groupBy(Trade::getContraInstrument, InstrumentPosMtmAggregate::contra) .resetTrigger(positionSnapshotReset) .publishTrigger(positionSnapshotReset); } private void buildInstrumentFeeMap() { instrumentFeeMap = DataFlow.subscribe(Trade.class) .merge(tradeBatchStream) .groupBy(Trade::getDealtInstrument, FeeInstrumentPosMtmAggregate::new) .resetTrigger(positionSnapshotReset) .defaultValue(GroupBy.emptyCollection()) .mapValues(derivedRateNode::calculateFeeMtm) .publishTriggerOverride(positionUpdateEob) .updateTrigger(positionUpdateEob); } private void buildGlobalMtm() { //Asset position map created by PositionSnapshot var snapshotPositionMap = DataFlow.subscribe(PositionSnapshot.class) .flatMap(PositionSnapshot::getPositions).id("flatMapSnapshotPositions") .groupBy(InstrumentPosition::instrument).id("groupBySnapshotPositions") .resetTrigger(positionSnapshotReset) .publishTriggerOverride(positionUpdateEob); //global mtm for trading + snapshot positions var globalNetMtm = JoinFlowBuilder.outerJoin(dealtAndContraInstPosition, contraAndDealtInstPosition, InstrumentPosMtm::merge) .outerJoin(snapshotPositionMap, InstrumentPosMtm::overwriteInstrumentPositionWithSnapshot) .mapValues(derivedRateNode::calculateInstrumentPosMtm) .updateTrigger(positionUpdateEob) .defaultValue(GroupBy.emptyCollection()) .publishTriggerOverride(positionUpdateEob); //global mtm net of fees JoinFlowBuilder.leftJoin(globalNetMtm, instrumentFeeMap, NetMarkToMarket::combine) .updateTrigger(positionUpdateEob) .map(GroupBy::toMap) .map(NetMarkToMarket::markToMarketSum) .id("globalNetMtm") .sink(GLOBAL_NET_MTM_SINK) .map(DtoHelper::formatPosition) .sink(PnlCalculator.POSITION_SNAPSHOT_SINK); } private void buildInstrumentMtm() { //instrument mtm for trading var instNetMtm = JoinFlowBuilder.outerJoin(dealtOnlyInstPosition, contraOnlyInstPosition, InstrumentPosMtm::merge) .mapValues(derivedRateNode::calculateInstrumentPosMtm) .updateTrigger(positionUpdateEob) .defaultValue(GroupBy.emptyCollection()) .publishTriggerOverride(positionUpdateEob); //instrument mtm net of fees JoinFlowBuilder.leftJoin(instNetMtm, instrumentFeeMap, NetMarkToMarket::combine) .updateTrigger(positionUpdateEob) .map(GroupBy::toMap) .id("instrumentNetMtm") .sink(INSTRUMENT_NET_MTM_SINK); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy