/* * Copyright (c) 2012 Jeremy Goetsch * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.jgoetsch.eventtrader.order.price; import java.text.NumberFormat; import com.jgoetsch.eventtrader.TradeSignal; import com.jgoetsch.tradeframework.data.DataUnavailableException; import com.jgoetsch.tradeframework.marketdata.MarketData; /** * Abstract PriceCalculation whose resulting price can be offset by a predetermined amount. * * @author jgoetsch * */ public abstract class OffsetOrderPrice implements OrderPrice { private double offset = 0.0; private boolean isPercentage = false; private double tickSize = 0.01; public final double getValue(TradeSignal trade, MarketData marketData) throws DataUnavailableException { double base = getBaseValue(trade, marketData); if (base == 0) throw new DataUnavailableException("Market data for " + getClass().getSimpleName() + " not available"); else return base + getOffset(trade, marketData, base); } /** * Override to provide the base price to use from the MarketData before * the offset is applied. * * @param trade * @param marketData * @return base price extracted from the marketData */ protected abstract Double getBaseValue(TradeSignal trade, MarketData marketData) throws DataUnavailableException; /** * Returns the actual offset amount to be added to the base price. By * default the fixed offset is added to the price if buying, or subtracted * if selling. Can be overridden in order to dynamically modify the offset * based on trade or market data. * * @param trade * @param marketData * @return offset to add to base price */ protected double getOffset(TradeSignal trade, MarketData marketData, double basePrice) { return Math.rint(((trade.isSell() ? -getOffset() : getOffset()) * (isPercentage() ? basePrice : 1)) / tickSize) * tickSize; } @Override public String toString() { NumberFormat nf = isPercentage ? NumberFormat.getPercentInstance() : NumberFormat.getNumberInstance(); return getClass().getSimpleName() + (offset >= 0 ? " + " : " - ") + nf.format(Math.abs(offset)); } public final void setOffset(double offset) { this.offset = offset; } public final double getOffset() { return offset; } public final void setPercentage(boolean isPercentage) { this.isPercentage = isPercentage; } public final boolean isPercentage() { return isPercentage; } public final void setTickSize(double tickSize) { this.tickSize = tickSize; } public final double getTickSize() { return tickSize; } }