Skip to content

Commit

Permalink
Trial implementation of a CrossInstrument class.
Browse files Browse the repository at this point in the history
  • Loading branch information
reiss authored and reiss committed Nov 8, 2017
1 parent 988fe9d commit c43b8f3
Show file tree
Hide file tree
Showing 3 changed files with 196 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package com.jforex.programming.instrument;

import static java.util.stream.Collectors.toSet;

import java.math.BigDecimal;
import java.math.RoundingMode;

import com.dukascopy.api.ICurrency;
import com.dukascopy.api.Instrument;
import com.google.common.collect.Sets;
import com.jforex.programming.currency.CurrencyFactory;
import com.jforex.programming.currency.CurrencyUtil;

import io.reactivex.Maybe;

public class CrossInstrument {

private final Instrument firstInstrument;
private final Instrument secondInstrument;
private final Instrument instrument;
private final ICurrency crossCurrency;
private final boolean isEmpty;
private final boolean shouldDivide;
private final int pipScale;

public CrossInstrument(final Instrument firstInstrument,
final Instrument secondInstrument) {
this.firstInstrument = firstInstrument;
this.secondInstrument = secondInstrument;

final Maybe<Instrument> maybeCross = InstrumentFactory.maybeCross(firstInstrument, secondInstrument);

instrument = maybeCross.blockingGet();
isEmpty = maybeCross
.isEmpty()
.blockingGet();
crossCurrency = calcCrossCurrency();
shouldDivide = shouldDivide();
pipScale = instrument.getPipScale() + 1;
}

public boolean isValid() {
return !isEmpty;
}

public Instrument get() {
return instrument;
}

public ICurrency crossCurrency() {
return crossCurrency;
}

public FxRate rate(final FxRate rateA,
final FxRate rateB) {
final BigDecimal bdcFirst = rateA.instrument().equals(firstInstrument)
? BigDecimal.valueOf(rateA.value())
: BigDecimal.valueOf(rateB.value());
final BigDecimal bdcSecond = rateB.instrument().equals(secondInstrument)
? BigDecimal.valueOf(rateB.value())
: BigDecimal.valueOf(rateA.value());

final double crossValue = shouldDivide
? bdcFirst.divide(bdcSecond,
pipScale,
RoundingMode.HALF_UP)
.doubleValue()
: bdcFirst
.multiply(bdcSecond)
.setScale(pipScale, RoundingMode.HALF_UP)
.doubleValue();

return new FxRate(crossValue, instrument);
}

private ICurrency calcCrossCurrency() {
return CurrencyFactory
.fromInstruments(firstInstrument, secondInstrument)
.stream()
.filter(currency -> CurrencyUtil.isInAllInstruments(currency,
Sets.newHashSet(firstInstrument, secondInstrument)))
.collect(toSet())
.iterator()
.next();
}

private boolean shouldDivide() {
final ICurrency baseFirstCurrency = firstInstrument.getPrimaryJFCurrency();
final ICurrency baseSecondCurrency = secondInstrument.getPrimaryJFCurrency();
final ICurrency quoteFirstCurrency = firstInstrument.getSecondaryJFCurrency();
final ICurrency quoteSecondCurrency = secondInstrument.getSecondaryJFCurrency();

return baseFirstCurrency.equals(crossCurrency) && baseSecondCurrency.equals(crossCurrency)
|| quoteFirstCurrency.equals(crossCurrency) && quoteSecondCurrency.equals(crossCurrency);
}
}
23 changes: 23 additions & 0 deletions src/main/java/com/jforex/programming/instrument/FxRate.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.jforex.programming.instrument;

import com.dukascopy.api.Instrument;

public class FxRate {

private final double value;
private final Instrument instrument;

public FxRate(final double value,
final Instrument instrument) {
this.value = value;
this.instrument = instrument;
}

public double value() {
return value;
}

public Instrument instrument() {
return instrument;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package com.jforex.programming.instrument.test;

import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

import org.junit.Before;
import org.junit.Test;

import com.jforex.programming.instrument.CrossInstrument;
import com.jforex.programming.instrument.FxRate;
import com.jforex.programming.test.common.CurrencyUtilForTest;

public class CrossInstrumentTest extends CurrencyUtilForTest {

private CrossInstrument crossInstrumentA;
private CrossInstrument crossInstrumentB;
private CrossInstrument crossInstrumentC;
private CrossInstrument crossInstrumentD;

@Before
public void setUp() {
crossInstrumentA = new CrossInstrument(instrumentEURUSD, instrumentGBPUSD);
crossInstrumentB = new CrossInstrument(instrumentEURGBP, instrumentGBPUSD);
crossInstrumentC = new CrossInstrument(instrumentEURJPY, instrumentGBPJPY);
crossInstrumentD = new CrossInstrument(instrumentEURGBP, instrumentGBPJPY);
}

@Test
public void instanceIsValid() {
assertTrue(crossInstrumentA.isValid());
assertTrue(crossInstrumentB.isValid());
assertTrue(crossInstrumentC.isValid());
assertTrue(crossInstrumentD.isValid());
}

@Test
public void instrumentIsCorrect() {
assertThat(crossInstrumentA.get(), equalTo(instrumentEURGBP));
assertThat(crossInstrumentB.get(), equalTo(instrumentEURUSD));
assertThat(crossInstrumentC.get(), equalTo(instrumentEURGBP));
assertThat(crossInstrumentD.get(), equalTo(instrumentEURJPY));
}

@Test
public void crossCurrencyIsCorrect() {
assertThat(crossInstrumentA.crossCurrency(), equalTo(currencyUSD));
assertThat(crossInstrumentB.crossCurrency(), equalTo(currencyGBP));
assertThat(crossInstrumentC.crossCurrency(), equalTo(currencyJPY));
assertThat(crossInstrumentD.crossCurrency(), equalTo(currencyGBP));
}

@Test
public void crossRateIsCorrect() {
FxRate rateA = new FxRate(1.15863, instrumentEURUSD);
FxRate rateB = new FxRate(1.31044, instrumentGBPUSD);
assertThat(crossInstrumentA.rate(rateA, rateB).value(),
equalTo(0.88415));
assertThat(crossInstrumentA.rate(rateA, rateB).instrument(),
equalTo(instrumentEURGBP));

rateA = new FxRate(0.88415, instrumentEURGBP);
rateB = new FxRate(1.31044, instrumentGBPUSD);
assertThat(crossInstrumentB.rate(rateA, rateB).value(),
equalTo(1.15863));

rateA = new FxRate(131.452, instrumentEURJPY);
rateB = new FxRate(148.653, instrumentGBPJPY);
assertThat(crossInstrumentC.rate(rateA, rateB).value(),
equalTo(0.88429));

rateA = new FxRate(0.88429, instrumentEURGBP);
rateB = new FxRate(148.653, instrumentGBPJPY);
assertThat(crossInstrumentD.rate(rateA, rateB).value(),
equalTo(131.452));
}
}

0 comments on commit c43b8f3

Please sign in to comment.