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

io.fair_acc.sample.financial.service.order.PositionFinancialDataSet Maven / Gradle / Ivy

Go to download

Small sample applications to showcase the features of the chart-fx library.

The newest version!
package io.fair_acc.sample.financial.service.order;

import static io.fair_acc.sample.financial.service.StandardTradePlanAttributes.POSITIONS;

import java.util.*;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.fair_acc.chartfx.renderer.spi.financial.PositionFinancialRendererPaintAfterEP.PositionRendered;
import io.fair_acc.chartfx.renderer.spi.financial.PositionFinancialRendererPaintAfterEP.PositionRenderedAware;
import io.fair_acc.dataset.DataSet;
import io.fair_acc.dataset.events.ChartBits;
import io.fair_acc.dataset.spi.AbstractDataSet;
import io.fair_acc.dataset.spi.financial.OhlcvDataSet;
import io.fair_acc.dataset.spi.financial.api.attrs.AttributeModel;
import io.fair_acc.dataset.spi.financial.api.ohlcv.IOhlcvItem;
import io.fair_acc.sample.financial.dos.Order;
import io.fair_acc.sample.financial.dos.Position;
import io.fair_acc.sample.financial.dos.Position.PositionStatus;
import io.fair_acc.sample.financial.dos.PositionContainer;
import io.fair_acc.sample.financial.service.execution.ExecutionPlatformListener;
import io.fair_acc.sample.financial.service.execution.OrderEvent;

/**
 *

* Example of Trading Position DataSet. Depended on the Trading Platform Position / Order Domain Objects. *

* The example includes: *

    *
  • merging positions for same entry or exit time, and *
  • mapping position domain object to renderer required domain object PositionRendered, and *
  • full example of the position listener mechanism. *
* * @author afischer */ public class PositionFinancialDataSet extends AbstractDataSet implements ExecutionPlatformListener, PositionRenderedAware { private static final Logger LOGGER = LoggerFactory.getLogger(PositionFinancialDataSet.class); private Map renderedPositionsBased; private List renderedPositionsList; private String instrument; private OhlcvDataSet ohlcvDataSet; public PositionFinancialDataSet(String instrument, OhlcvDataSet ohlcvDataSet, AttributeModel context) { super(instrument + "-positions", 2); this.instrument = instrument; this.ohlcvDataSet = ohlcvDataSet; fillDataSet(context.getRequiredAttribute(POSITIONS)); if (LOGGER.isDebugEnabled()) { LOGGER.atDebug().addArgument(PositionFinancialDataSet.class.getSimpleName()).log("started '{}'"); } } private void fillDataSet(PositionContainer positions) { renderedPositionsBased = new TreeMap<>(); renderedPositionsList = new ArrayList<>(); Set positionSet = positions.getPositionByMarketSymbol(instrument); for (Position position : positionSet) { includePosition(position, true); } renderedPositionsList.addAll(renderedPositionsBased.values()); } private void includePosition(Position position, boolean updateRequired) { if (position != null) { includeRenderedPosition(createPositionRendered(position, 1), updateRequired); if (position.getPositionStatus() == PositionStatus.CLOSED) { includeRenderedPosition(createPositionRendered(position, 2), updateRequired); } } } private void includeRenderedPosition(PositionRendered positionRendered, boolean updateRequired) { PositionRendered positionRenderedMain = renderedPositionsBased.get(positionRendered.index); if (positionRenderedMain != null) { // there exists some position for this index, merge it if (positionRenderedMain.positionId == positionRendered.positionId || !updateRequired) { return; // already included or update forbidden } if (positionRendered.entryExit == positionRenderedMain.entryExit) { positionRenderedMain.quantity += positionRendered.quantity; } else { positionRenderedMain.quantity -= positionRendered.quantity; } positionRenderedMain.price = (positionRenderedMain.price + positionRendered.price) / 2.0; positionRenderedMain.joinedEntries.addAll(positionRendered.joinedEntries); } else { // new rendered position, add them renderedPositionsBased.put(positionRendered.index, positionRendered); if (!updateRequired) { // add new order with new positions entry and exit parts renderedPositionsList.add(positionRendered); } } } private PositionRendered createPositionRendered(Position position, int entryExit) { PositionRendered positionRendered = new PositionRendered(); positionRendered.positionId = position.getPositionId(); positionRendered.entryExit = entryExit; positionRendered.posType = position.getPositionType(); positionRendered.quantity = position.getPositionQuantity(); positionRendered.price = entryExit == 1 ? position.getEntryPrice() : position.getExitPrice(); positionRendered.closed = position.getPositionStatus() == PositionStatus.CLOSED; if (entryExit != 1) { // estimate entry index appendEntryLinkage(position, positionRendered); } // find correct OHLC item and attach position index to painted OHLC item timestamp long orderTime = entryExit == 1 ? position.getPositionEntryIndex() : position.getPositionExitIndex(); positionRendered.index = estimateOhlcBasedTimestamp(orderTime); return positionRendered; } // necessary for linkage lines between exit and entry orders which are binding to same trade position private void appendEntryLinkage(Position position, PositionRendered positionRendered) { List entryRow = new ArrayList<>(); entryRow.add((double) estimateOhlcBasedTimestamp(position.getPositionEntryIndex())); // x entryRow.add(position.getEntryPrice()); // y entryRow.add((position.getPositionType() == -1 && position.getEntryPrice() < position.getExitPrice()) || (position.getPositionType() == 1 && position.getEntryPrice() > position.getExitPrice()) ? -1.0 : 1.0); // loss/profit positionRendered.joinedEntries.add(entryRow); } // estimate OHLC which shows the trades, find the timestamp of the bar for trade. private long estimateOhlcBasedTimestamp(long orderTime) { if (ohlcvDataSet != null) { int idx = ohlcvDataSet.getIndex(DIM_X, orderTime / 1000.0); IOhlcvItem ohlcvItem = ohlcvDataSet.getItem(idx); long ohlcItemTime = ohlcvItem.getTimeStamp().getTime(); long ohlcItemTimeNext = -1; if (idx < ohlcvDataSet.getDataCount() - 1) { ohlcItemTimeNext = ohlcvDataSet.getItem(idx + 1).getTimeStamp().getTime(); } if (orderTime <= ohlcItemTime) { orderTime = Math.round(ohlcItemTime / 1000.0); } else if (orderTime > ohlcItemTimeNext) { orderTime = Math.round(ohlcItemTimeNext / 1000.0); } } return orderTime; } public PositionRendered getPositionByTime(long corr) { return renderedPositionsBased.get(corr); } @Override public double get(int dimIndex, int index) { PositionRendered positionRendered = renderedPositionsList.get(index); if (dimIndex == DIM_X) { // return coordination by index return positionRendered == null ? -1.0 : positionRendered.index; } return positionRendered == null ? -1.0 : positionRendered.price; } @Override public int getDataCount() { return renderedPositionsList.size(); } @Override public DataSet set(DataSet other, boolean copy) { this.renderedPositionsBased = new TreeMap<>(((PositionFinancialDataSet) other).renderedPositionsBased); this.renderedPositionsList = new ArrayList<>(((PositionFinancialDataSet) other).renderedPositionsList); this.instrument = ((PositionFinancialDataSet) other).instrument; this.ohlcvDataSet = ((PositionFinancialDataSet) other).ohlcvDataSet; return this; } @Override public void orderFilled(OrderEvent event) { // update internal memories Order order = event.getOrder(); includePosition(order.isExitOrder() ? order.getExitOfPosition() : order.getEntryOfPosition(), false); fireInvalidated(ChartBits.DataSetDataAdded); } @Override public void orderCancelled(OrderEvent event) { // nothing to do } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy