diff --git a/README.md b/README.md
index cb01019..96f4660 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
# Intrinio Java SDK for Real-Time Stock Prices
-SDK for working with Intrinio's realtime IEX, NASDAQ Basic, CBOE One, delayed SIP prices, and realtime/delayed [OPRA](https://www.opraplan.com/) options feeds.
+SDK for working with Intrinio's realtime IEX, NASDAQ Basic, CBOE One, delayed SIP prices, and realtime/delayed [OPRA](https://www.opraplan.com/) and Options Edge options feeds.
[Intrinio](https://intrinio.com/) provides real-time and delayed stock prices via a two-way WebSocket connection. To get started, [subscribe to a real-time data feed](https://docs.intrinio.com/tutorial/websocket) and follow the instructions below.
@@ -87,6 +87,7 @@ public record Trade(String symbol, SubProvider subProvider, char marketCenter, d
* **`NASDAQ_BASIC`** - NASDAQ Basic in the NASDAQ_BASIC provider.
* **`IEX`** - From the IEX exchange in the REALTIME provider.
* **`CBOE_ONE`** - From the CBOE One exchanges provider.
+ * **`EQUITIES_EDGE`** - From the Equities Edge provider.
* **marketCenter** - Provides the market center
* **price** - the price in USD
* **size** - the size of the last trade.
@@ -113,6 +114,7 @@ public record Quote(QuoteType type, String symbol, SubProvider subProvider, char
* **`NASDAQ_BASIC`** - NASDAQ Basic in the NASDAQ_BASIC provider.
* **`IEX`** - From the IEX exchange in the REALTIME provider.
* **`CBOE_ONE`** - From the CBOE One exchanges provider.
+ * **`EQUITIES_EDGE`** - From the Equities Edge provider.
* **marketCenter** - Provides the market center
* **symbol** - Ticker symbol.
* **price** - the price in USD
@@ -387,7 +389,7 @@ client.leave()
```json
{
"apiKey": "",
- "provider": "IEX", //or DELAYED_SIP or NASDAQ_BASIC or CBOE_ONE or MANUAL
+ "provider": "IEX", //or DELAYED_SIP or NASDAQ_BASIC or CBOE_ONE or EQUITIES_EDGE or MANUAL
"symbols": [ "AAPL", "MSFT", "GOOG" ], //This is a list of individual tickers to subscribe to, or "lobby" to subscribe to all at once (firehose).
"tradesOnly": true, //This indicates whether you only want trade events (true) or you want trade, ask, and bid events (false).
"numThreads": 4 //The number of threads to use for processing events.
@@ -447,7 +449,7 @@ If a subscription has already been created with one of the `join` methods, data
```json
{
"apiKey": "",
- "provider": "OPRA", //OPRA
+ "provider": "OPRA", //OPRA, OPTIONS_EDGE
"symbols": [ "GOOG__210917C01040000", "MSFT", "AAPL__210917C00130000", "SPY" ], //Individual contracts, or option chains to subscribe to all contracts under a symbol.
"numThreads": 4, //The number of threads to use for processing events.
"delayed": false //If you have realtime access but want to force 15minute delayed, set this to true.
diff --git a/pom.xml b/pom.xml
index 191acb0..c4d3833 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2,7 +2,7 @@
4.0.0
com.intrinio
IntrinioRealtimeJavaSDK
- 7.2.0
+ 8.0.0
jar
IntrinioRealtimeJavaSDK
diff --git a/src/SampleApp/CompositeSampleApp.java b/src/SampleApp/CompositeSampleApp.java
index 28d630a..ab70e71 100644
--- a/src/SampleApp/CompositeSampleApp.java
+++ b/src/SampleApp/CompositeSampleApp.java
@@ -28,7 +28,7 @@ public static void run(String[] args){
}
//store the most recent values in a simple non-transactional cache that gives contextual information with the event.
- intrinio.realtime.composite.DataCache currentDataCache = new CurrentDataCache();
+ intrinio.realtime.composite.DataCache currentDataCache = DataCacheFactory.create();
//Initialize Options Client and wire it to the cache
//intrinio.realtime.options.OnUnusualActivity optionsUnusualActivityHandler = null;
@@ -44,7 +44,7 @@ public static void run(String[] args){
intrinio.realtime.equities.Client equitiesClient = new intrinio.realtime.equities.Client(equitiesTradeHandler, equitiesQuoteHandler, equitiesConfig);
//Display trade events with context
- currentDataCache.setOnEquitiesTradeUpdated((SecurityData securityData, DataCache dataCache) -> {
+ currentDataCache.setEquitiesTradeUpdatedCallback((SecurityData securityData, DataCache dataCache, intrinio.realtime.equities.Trade trade) -> {
intrinio.realtime.equities.Client.Log(securityData.getTickerSymbol() + " had a trade and also has " + securityData.getAllOptionsContractData().size() + " active contracts");
});
diff --git a/src/intrinio/realtime/composite/BlackScholesGreekCalculator.java b/src/intrinio/realtime/composite/BlackScholesGreekCalculator.java
index c1d4ee6..726a8ca 100644
--- a/src/intrinio/realtime/composite/BlackScholesGreekCalculator.java
+++ b/src/intrinio/realtime/composite/BlackScholesGreekCalculator.java
@@ -1,193 +1,141 @@
-//package intrinio.realtime.composite;
-//
-//public class BlackScholesGreekCalculator implements GreekCalculator
-//{
-// private final double LOW_VOL = 0.0;
-// private final double HIGH_VOL = 5.0;
-// private final double VOL_TOLERANCE = 0.0001;
-// private final double MIN_Z_SCORE = -8.0;
-// private final double MAX_Z_SCORE = 8.0;
-// private final String DividendYieldKey = "DividendYield";
-//
-// @Override
-// public Greek calculate(String contract, SecurityData calcData, Double riskFreeInterestRate) {
-// intrinio.realtime.equities.Trade underlyingTrade = calcData.getEquitiesTrade();
-// OptionsContractData optionsContractData = calcData.getOptionsContractData(contract);
-// if (optionsContractData == null){
-// return null;
-// }
-// intrinio.realtime.options.Trade latestOptionTrade = optionsContractData.getTrade();
-// intrinio.realtime.options.Quote latestOptionQuote = optionsContractData.getQuote();
-// if (underlyingTrade == null || latestOptionTrade == null || latestOptionQuote == null)
-// return null;
-// if (latestOptionQuote.askPrice() <= 0.0 || latestOptionQuote.bidPrice() <= 0.0)
-// return null;
-// if (riskFreeInterestRate == null || riskFreeInterestRate <= 0.0)
-// return null;
-//
-// boolean isPut = latestOptionTrade.isPut();
-// double underlyingPrice = underlyingTrade.price();
-// double strike = latestOptionTrade.getStrikePrice();
-// double daysToExpiration = getDaysToExpiration(latestOptionTrade, latestOptionQuote);
-// double dividendYield = calcData.getSupplementaryDatum(DividendYieldKey);
-// double marketPrice = (latestOptionQuote.askPrice() + latestOptionQuote.bidPrice()) / 2.0;
-// double impliedVolatility = calcImpliedVolatility(isPut, underlyingPrice, strike, daysToExpiration, riskFreeInterestRate, dividendYield, marketPrice);
-// double sigma = impliedVolatility;
-// double delta = calcDelta(isPut, underlyingPrice, strike, daysToExpiration, riskFreeInterestRate, dividendYield, marketPrice, sigma);
-// double gamma = calcGamma(underlyingPrice, strike, daysToExpiration, riskFreeInterestRate, dividendYield, marketPrice, sigma);
-// double theta = calcTheta(isPut, underlyingPrice, strike, daysToExpiration, riskFreeInterestRate, dividendYield, marketPrice, sigma);
-// double vega = calcVega(underlyingPrice, strike, daysToExpiration, riskFreeInterestRate, dividendYield, marketPrice, sigma);
-//
-// return getGreek(calcData, riskFreeInterestRate, contract, daysToExpiration, marketPrice, impliedVolatility, delta, gamma, theta, vega);
-// }
-//
-// private double calcImpliedVolatilityCall(double underlyingPrice, double strike, double daysToExpiration, double riskFreeInterestRate, double dividendYield, double marketPrice) {
-// double low = LOW_VOL, high = HIGH_VOL;
-// while ((high - low) > VOL_TOLERANCE){
-// if (calcPriceCall(underlyingPrice, strike, daysToExpiration, riskFreeInterestRate, (high + low) / 2.0, dividendYield) > marketPrice)
-// high = (high + low) / 2.0;
-// else
-// low = (high + low) / 2.0;
-// }
-//
-// return (high + low) / 2.0;
-// }
-//
-// private double calcImpliedVolatilityPut(double underlyingPrice, double strike, double daysToExpiration, double riskFreeInterestRate, double dividendYield, double marketPrice) {
-// double low = LOW_VOL, high = HIGH_VOL;
-// while ((high - low) > VOL_TOLERANCE){
-// if (calcPricePut(underlyingPrice, strike, daysToExpiration, riskFreeInterestRate, (high + low) / 2.0, dividendYield) > marketPrice)
-// high = (high + low) / 2.0;
-// else
-// low = (high + low) / 2.0;
-// }
-//
-// return (high + low) / 2.0;
-// }
-//
-// private double calcImpliedVolatility(boolean isPut, double underlyingPrice, double strike, double daysToExpiration, double riskFreeInterestRate, double dividendYield, double marketPrice){
-// if (isPut)
-// return calcImpliedVolatilityPut(underlyingPrice, strike, daysToExpiration, riskFreeInterestRate, dividendYield, marketPrice);
-// return calcImpliedVolatilityCall(underlyingPrice, strike, daysToExpiration, riskFreeInterestRate, dividendYield, marketPrice);
-// }
-//
-// private double calcDeltaCall(double underlyingPrice, double strike, double daysToExpiration, double riskFreeInterestRate, double dividendYield, double marketPrice, double sigma){
-// return normalSDist( d1( underlyingPrice, strike, daysToExpiration, riskFreeInterestRate, sigma, dividendYield ) );
-// }
-//
-// private double calcDeltaPut(double underlyingPrice, double strike, double daysToExpiration, double riskFreeInterestRate, double dividendYield, double marketPrice, double sigma){
-// return calcDeltaCall( underlyingPrice, strike, daysToExpiration, riskFreeInterestRate, dividendYield, marketPrice, sigma) - 1;
-// }
-//
-// private double calcDelta(boolean isPut, double underlyingPrice, double strike, double daysToExpiration, double riskFreeInterestRate, double dividendYield, double marketPrice, double sigma){
-// if (isPut)
-// return calcDeltaPut(underlyingPrice, strike, daysToExpiration, riskFreeInterestRate, dividendYield, marketPrice, sigma);
-// else return calcDeltaCall(underlyingPrice, strike, daysToExpiration, riskFreeInterestRate, dividendYield, marketPrice, sigma);
-// }
-//
-// private double calcGamma(double underlyingPrice, double strike, double daysToExpiration, double riskFreeInterestRate, double dividendYield, double marketPrice, double sigma){
-// return phi( d1( underlyingPrice, strike, daysToExpiration, riskFreeInterestRate, sigma, dividendYield ) ) / ( underlyingPrice * sigma * Math.sqrt(daysToExpiration) );
-// }
-//
-// private double calcThetaCall(double underlyingPrice, double strike, double daysToExpiration, double riskFreeInterestRate, double dividendYield, double marketPrice, double sigma){
-// double term1 = underlyingPrice * phi( d1( underlyingPrice, strike, daysToExpiration, riskFreeInterestRate, sigma, dividendYield ) ) * sigma / ( 2 * Math.sqrt(daysToExpiration) );
-// double term2 = riskFreeInterestRate * strike * Math.exp(-1.0 * riskFreeInterestRate * daysToExpiration) * normalSDist( d2( underlyingPrice, strike, daysToExpiration, riskFreeInterestRate, sigma, dividendYield ) );
-// return ( - term1 - term2 ) / 365.25;
-// }
-//
-// private double calcThetaPut(double underlyingPrice, double strike, double daysToExpiration, double riskFreeInterestRate, double dividendYield, double marketPrice, double sigma){
-// double term1 = underlyingPrice * phi( d1( underlyingPrice, strike, daysToExpiration, riskFreeInterestRate, sigma, dividendYield ) ) * sigma / ( 2 * Math.sqrt(daysToExpiration) );
-// double term2 = riskFreeInterestRate * strike * Math.exp(-1.0 * riskFreeInterestRate * daysToExpiration) * normalSDist( - d2( underlyingPrice, strike, daysToExpiration, riskFreeInterestRate, sigma, dividendYield ) );
-// return ( - term1 + term2 ) / 365.25;
-// }
-//
-// private double calcTheta(boolean isPut, double underlyingPrice, double strike, double daysToExpiration, double riskFreeInterestRate, double dividendYield, double marketPrice, double sigma){
-// if (isPut)
-// return calcThetaPut(underlyingPrice, strike, daysToExpiration, riskFreeInterestRate, dividendYield, marketPrice, sigma);
-// else return calcThetaCall(underlyingPrice, strike, daysToExpiration, riskFreeInterestRate, dividendYield, marketPrice, sigma);
-// }
-//
-// private double calcVega(double underlyingPrice, double strike, double daysToExpiration, double riskFreeInterestRate, double dividendYield, double marketPrice, double sigma){
-// return 0.01 * underlyingPrice * Math.sqrt(daysToExpiration) * phi(d1(underlyingPrice, strike, daysToExpiration, riskFreeInterestRate, sigma, dividendYield));
-// }
-//
-// private double d1(double underylyingPrice, double strike, double daysToExpiration, double riskFreeInterestRate, double sigma, double dividendYield){
-// double numerator = ( Math.log(underylyingPrice / strike) + (riskFreeInterestRate - dividendYield + 0.5 * Math.pow(sigma, 2.0) ) * daysToExpiration);
-// double denominator = ( sigma * Math.sqrt(daysToExpiration));
-// return numerator / denominator;
-// }
-//
-// private double d2(double underylyingPrice, double strike, double daysToExpiration, double riskFreeInterestRate, double sigma, double dividendYield){
-// return d1( underylyingPrice, strike, daysToExpiration, riskFreeInterestRate, sigma, dividendYield ) - ( sigma * Math.sqrt(daysToExpiration) );
-// }
-//
-// private double normalSDist(double z){
-// if (z < MIN_Z_SCORE)
-// return 0.0;
-// if (z > MAX_Z_SCORE)
-// return 1.0;
-// double i = 3.0, sum = 0.0, term = z;
-// while ((sum + term) != sum){
-// sum = sum + term;
-// term = term * z * z / i;
-// i += 2.0;
-// }
-// return 0.5 + sum * phi(z);
-// }
-//
-// private double phi(double x){
-// double numerator = Math.exp(-1.0 * x*x / 2.0);
-// double denominator = Math.sqrt(2.0 * Math.PI);
-// return numerator / denominator;
-// }
-//
-// private double calcPriceCall(double underylyingPrice, double strike, double daysToExpiration, double riskFreeInterestRate, double sigma, double dividendYield){
-// double d1 = d1( underylyingPrice, strike, daysToExpiration, riskFreeInterestRate, sigma, dividendYield );
-// double discounted_underlying = Math.exp(-1.0 * dividendYield * daysToExpiration) * underylyingPrice;
-// double probability_weighted_value_of_being_exercised = discounted_underlying * normalSDist( d1 );
-//
-// double d2 = d1 - ( sigma * Math.sqrt(daysToExpiration) );
-// double discounted_strike = Math.exp(-1.0 * riskFreeInterestRate * daysToExpiration) * strike;
-// double probability_weighted_value_of_discounted_strike = discounted_strike * normalSDist( d2 );
-//
-// return probability_weighted_value_of_being_exercised - probability_weighted_value_of_discounted_strike;
-// }
-//
-// private double calcPricePut(double underylyingPrice, double strike, double daysToExpiration, double riskFreeInterestRate, double sigma, double dividendYield){
-// double d2 = d2( underylyingPrice, strike, daysToExpiration, riskFreeInterestRate, sigma, dividendYield );
-// double discounted_strike = strike * Math.exp(-1.0 * riskFreeInterestRate * daysToExpiration);
-// double probabiltity_weighted_value_of_discounted_strike = discounted_strike * normalSDist( -1.0 * d2 );
-//
-// double d1 = d2 + ( sigma * Math.sqrt(daysToExpiration) );
-// double discounted_underlying = underylyingPrice * Math.exp(-1.0 * dividendYield * daysToExpiration);
-// double probability_weighted_value_of_being_exercised = discounted_underlying * normalSDist( -1.0 * d1 );
-//
-// return probabiltity_weighted_value_of_discounted_strike - probability_weighted_value_of_being_exercised;
-// }
-//
-// private double getDaysToExpiration(intrinio.realtime.options.Trade latestOptionTrade, intrinio.realtime.options.Quote latestOptionQuote){
-// double latestActivity = Math.max(latestOptionTrade.timestamp(), latestOptionQuote.timestamp());
-// long expirationAsUnixWholeSeconds = latestOptionTrade.getExpirationDate().toEpochSecond();
-// double fractional = ((double)(latestOptionTrade.getExpirationDate().getNano())) / 1_000_000_000.0;
-// double expiration = (((double)expirationAsUnixWholeSeconds) + fractional);
-// return (expiration - latestActivity) / 86400.0; //86400 is seconds in a day
-// }
-//
-// private Greek getGreek(SecurityData calcData, Double riskFreeInterestRate, String contract, double daysToExpiration, double marketPrice, double impliedVolatility, double delta, double gamma, double theta, double vega){
-// return new Greek(calcData.getTickerSymbol(),
-// contract,
-// calcData.getEquitiesTrade(),
-// calcData.getAllOptionsContractData().get(contract).getTrade(),//latestOptionTrade,
-// calcData.getAllOptionsContractData().get(contract).getQuote(),//latestOptionQuote,
-// riskFreeInterestRate,
-// calcData.getSupplementaryDatum(DividendYieldKey),
-// daysToExpiration,
-// marketPrice,
-// impliedVolatility,
-// delta,
-// gamma,
-// theta,
-// vega,
-// GreekCalculationMethod.BLACK_SCHOLES);
-// }
-//}
+package intrinio.realtime.composite;
+
+import java.util.Date;
+
+public class BlackScholesGreekCalculator {
+ private static final double LOW_VOL = 0.0D;
+ private static final double HIGH_VOL = 5.0D;
+ private static final double VOL_TOLERANCE = 1e-12D;
+ private static final double MIN_Z_SCORE = -8.0D;
+ private static final double MAX_Z_SCORE = 8.0D;
+ private static final double root2Pi = Math.sqrt(2.0D * Math.PI);
+
+ public static Greek calculate(double riskFreeInterestRate, double dividendYield, double underlyingPrice, double latestEventUnixTimestamp, double marketPrice, boolean isPut, double strike, Date expirationDate) {
+ if (marketPrice <= 0.0D || riskFreeInterestRate <= 0.0D || underlyingPrice <= 0.0D)
+ return new Greek(0.0D, 0.0D, 0.0D, 0.0D, 0.0D, false);
+
+ double yearsToExpiration = getYearsToExpiration(latestEventUnixTimestamp, expirationDate);
+
+ if (yearsToExpiration <= 0.0D || strike <= 0.0D)
+ return new Greek(0.0D, 0.0D, 0.0D, 0.0D, 0.0D, false);
+
+ double impliedVolatility = calcImpliedVolatility(isPut, underlyingPrice, strike, yearsToExpiration, riskFreeInterestRate, dividendYield, marketPrice);
+ if (impliedVolatility == 0.0D)
+ return new Greek(0.0D, 0.0D, 0.0D, 0.0D, 0.0D, false);
+
+ // Compute common values once for all Greeks to avoid redundant calcs
+ double sqrtT = Math.sqrt(yearsToExpiration);
+ double d1 = d1(underlyingPrice, strike, yearsToExpiration, riskFreeInterestRate, impliedVolatility, dividendYield);
+ double d2 = d1 - impliedVolatility * sqrtT;
+ double expQt = Math.exp(-dividendYield * yearsToExpiration);
+ double expRt = Math.exp(-riskFreeInterestRate * yearsToExpiration);
+ double nD1 = cumulativeNormalDistribution(d1);
+ double nD2 = cumulativeNormalDistribution(d2);
+ double phiD1 = normalPdf(d1);
+
+ double delta = isPut ? expQt * (nD1 - 1.0D) : expQt * nD1;
+ double gamma = expQt * phiD1 / (underlyingPrice * impliedVolatility * sqrtT);
+ double vega = 0.01D * underlyingPrice * expQt * sqrtT * phiD1;
+
+ // Theta with correct dividend adjustments
+ double term1 = expQt * underlyingPrice * phiD1 * impliedVolatility / (2.0D * sqrtT);
+ double term2 = riskFreeInterestRate * strike * expRt * (isPut ? (1.0D - nD2) : nD2);
+ double term3 = dividendYield * underlyingPrice * expQt * (isPut ? (1.0D - nD1) : nD1);
+ double theta = isPut ? (-term1 + term2 - term3) / 365.25D : (-term1 - term2 + term3) / 365.25D;
+
+ return new Greek(impliedVolatility, delta, gamma, theta, vega, true);
+ }
+
+ private static double calcImpliedVolatility(boolean isPut, double underlyingPrice, double strike, double yearsToExpiration, double riskFreeInterestRate, double dividendYield, double marketPrice) {
+ double tol = 1e-10D;
+ double forward = underlyingPrice * Math.exp((riskFreeInterestRate - dividendYield) * yearsToExpiration);
+ double m = forward / strike;
+ double sigma = Math.sqrt(2.0D * Math.abs(Math.log(m)) / yearsToExpiration);
+ if (Double.isNaN(sigma) || sigma <= 0.0D) sigma = 0.3D;
+
+ int maxIter = 50;
+ for (int iter = 0; iter < maxIter; iter++) {
+ double price = isPut ? calcPricePut(underlyingPrice, strike, yearsToExpiration, riskFreeInterestRate, sigma, dividendYield) : calcPriceCall(underlyingPrice, strike, yearsToExpiration, riskFreeInterestRate, sigma, dividendYield);
+ double diff = price - marketPrice;
+ if (Math.abs(diff) < tol) break;
+
+ double d1 = d1(underlyingPrice, strike, yearsToExpiration, riskFreeInterestRate, sigma, dividendYield);
+ double vega = underlyingPrice * Math.exp(-dividendYield * yearsToExpiration) * Math.sqrt(yearsToExpiration) * normalPdf(d1);
+ if (Math.abs(vega) < 1e-10D) break; // avoid division by zero
+
+ sigma -= diff / vega;
+ if (sigma <= 0.0D) sigma = 0.0001D; // prevent negative or zero
+ }
+
+ return sigma;
+ }
+
+ private static double d1(double underlyingPrice, double strike, double yearsToExpiration, double riskFreeInterestRate, double sigma, double dividendYield) {
+ double numerator = Math.log(underlyingPrice / strike) + (riskFreeInterestRate - dividendYield + 0.5D * sigma * sigma) * yearsToExpiration;
+ double denominator = sigma * Math.sqrt(yearsToExpiration);
+ return numerator / denominator;
+ }
+
+ private static double d2(double underlyingPrice, double strike, double yearsToExpiration, double riskFreeInterestRate, double sigma, double dividendYield) {
+ return d1(underlyingPrice, strike, yearsToExpiration, riskFreeInterestRate, sigma, dividendYield) - sigma * Math.sqrt(yearsToExpiration);
+ }
+
+ private static double cumulativeNormalDistribution(double z) {
+ if (Math.abs(z) < 1.5D)
+ return cumulativeNormalDistributionSeries(z);
+
+ if (z > MAX_Z_SCORE) return 1.0D;
+ if (z < MIN_Z_SCORE) return 0.0D;
+
+ boolean isNegative = z < 0.0D;
+ if (isNegative) z = -z;
+
+ double t = 1.0D / (1.0D + 0.2316419D * z);
+ double poly = t * (0.319381530D + t * (-0.356563782D + t * (1.781477937D + t * (-1.821255978D + t * 1.330274429D))));
+
+ double pdf = Math.exp(-0.5D * z * z) / root2Pi;
+ double tail = pdf * poly;
+
+ return isNegative ? tail : 1.0D - tail;
+ }
+
+ private static double cumulativeNormalDistributionSeries(double z) {
+ double absZ = Math.abs(z);
+ double sum = 0.0D;
+ double term = absZ;
+ double i = 3.0D;
+ while (sum + term != sum) {
+ sum += term;
+ term = term * absZ * absZ / i;
+ i += 2.0D;
+ }
+ double pdf = Math.exp(-0.5D * absZ * absZ) / root2Pi;
+ double half = pdf * sum;
+ return z >= 0.0D ? 0.5D + half : 0.5D - half;
+ }
+
+ private static double normalPdf(double x) {
+ return Math.exp(-0.5D * x * x) / root2Pi;
+ }
+
+ private static double calcPriceCall(double underlyingPrice, double strike, double yearsToExpiration, double riskFreeInterestRate, double sigma, double dividendYield) {
+ double d1 = d1(underlyingPrice, strike, yearsToExpiration, riskFreeInterestRate, sigma, dividendYield);
+ double d2 = d1 - sigma * Math.sqrt(yearsToExpiration);
+ double discountedUnderlying = Math.exp(-dividendYield * yearsToExpiration) * underlyingPrice;
+ double discountedStrike = Math.exp(-riskFreeInterestRate * yearsToExpiration) * strike;
+ return discountedUnderlying * cumulativeNormalDistribution(d1) - discountedStrike * cumulativeNormalDistribution(d2);
+ }
+
+ private static double calcPricePut(double underlyingPrice, double strike, double yearsToExpiration, double riskFreeInterestRate, double sigma, double dividendYield) {
+ double d1 = d1(underlyingPrice, strike, yearsToExpiration, riskFreeInterestRate, sigma, dividendYield);
+ double d2 = d1 - sigma * Math.sqrt(yearsToExpiration);
+ double discountedUnderlying = Math.exp(-dividendYield * yearsToExpiration) * underlyingPrice;
+ double discountedStrike = Math.exp(-riskFreeInterestRate * yearsToExpiration) * strike;
+ return discountedStrike * cumulativeNormalDistribution(-d2) - discountedUnderlying * cumulativeNormalDistribution(-d1);
+ }
+
+ private static double getYearsToExpiration(double latestActivityUnixTime, Date expirationDate) {
+ double expiration = expirationDate.getTime() / 1000.0D;
+ return (expiration - latestActivityUnixTime) / 31557600.0D;
+ }
+}
\ No newline at end of file
diff --git a/src/intrinio/realtime/composite/CalculateNewGreek.java b/src/intrinio/realtime/composite/CalculateNewGreek.java
new file mode 100644
index 0000000..c45bd6b
--- /dev/null
+++ b/src/intrinio/realtime/composite/CalculateNewGreek.java
@@ -0,0 +1,6 @@
+package intrinio.realtime.composite;
+
+@FunctionalInterface
+public interface CalculateNewGreek {
+ void calculateNewGreek(OptionsContractData optionsContractData, SecurityData securityData, DataCache dataCache);
+}
diff --git a/src/intrinio/realtime/composite/CurrentDataCache.java b/src/intrinio/realtime/composite/CurrentDataCache.java
index 2db1a5c..d8163b2 100644
--- a/src/intrinio/realtime/composite/CurrentDataCache.java
+++ b/src/intrinio/realtime/composite/CurrentDataCache.java
@@ -1,256 +1,304 @@
package intrinio.realtime.composite;
-import java.util.*;
+import java.util.Collections;
+import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
-/**
- * This is a simple thread-safe non-transactional cache intended to store the most recent data for an event type.
- * The on-updated events do not clone data before returning, so will always represent the newest data, even if it's
- * changed before you process it.
- */
-public class CurrentDataCache implements DataCache
-{
- //region Data Members
- private final ConcurrentHashMap data;
- private final Map readonlyData;
- private OnSupplementalDatumUpdated onSupplementalDatumUpdated;
- private OnSecuritySupplementalDatumUpdated onSecuritySupplementalDatumUpdated;
- private OnOptionsContractSupplementalDatumUpdated onOptionsContractSupplementalDatumUpdated;
- private OnEquitiesQuoteUpdated onEquitiesQuoteUpdated;
- private OnEquitiesTradeUpdated onEquitiesTradeUpdated;
- private OnOptionsQuoteUpdated onOptionsQuoteUpdated;
- private OnOptionsTradeUpdated onOptionsTradeUpdated;
- private OnOptionsRefreshUpdated onOptionsRefreshUpdated;
- private final ConcurrentHashMap supplementaryData;
- private final Map readonlySupplementaryData;
- //endregion Data Members
-
- //region Constructors
- public CurrentDataCache(){
- this.data = new ConcurrentHashMap();
- this.readonlyData = java.util.Collections.unmodifiableMap(this.data);
- this.onSupplementalDatumUpdated = null;
- this.onSecuritySupplementalDatumUpdated = null;
- this.onOptionsContractSupplementalDatumUpdated = null;
- this.onEquitiesQuoteUpdated = null;
- this.onEquitiesTradeUpdated = null;
- this.onOptionsQuoteUpdated = null;
- this.onOptionsTradeUpdated = null;
- this.onOptionsRefreshUpdated = null;
- this.supplementaryData = new ConcurrentHashMap();
- this.readonlySupplementaryData = java.util.Collections.unmodifiableMap(supplementaryData);
- }
- //endregion Constructors
-
- //region Public Methods
- public Double getsupplementaryDatum(String key){
+class CurrentDataCache implements DataCache {
+ private final ConcurrentHashMap securities = new ConcurrentHashMap<>();
+ private final Map readonlySecurities = Collections.unmodifiableMap(securities);
+ private final ConcurrentHashMap supplementaryData = new ConcurrentHashMap<>();
+ private final Map readonlySupplementaryData = Collections.unmodifiableMap(supplementaryData);
+
+ private OnSupplementalDatumUpdated supplementalDatumUpdatedCallback;
+ private OnSecuritySupplementalDatumUpdated securitySupplementalDatumUpdatedCallback;
+ private OnOptionsContractSupplementalDatumUpdated optionsContractSupplementalDatumUpdatedCallback;
+
+ private OnOptionsContractGreekDataUpdated optionsContractGreekDataUpdatedCallback;
+
+ private OnEquitiesTradeUpdated equitiesTradeUpdatedCallback;
+ private OnEquitiesQuoteUpdated equitiesQuoteUpdatedCallback;
+
+ private OnOptionsTradeUpdated optionsTradeUpdatedCallback;
+ private OnOptionsQuoteUpdated optionsQuoteUpdatedCallback;
+ private OnOptionsRefreshUpdated optionsRefreshUpdatedCallback;
+ private OnOptionsUnusualActivityUpdated optionsUnusualActivityUpdatedCallback;
+
+ public CurrentDataCache() {
+ }
+
+ public Double getSupplementaryDatum(String key) {
return supplementaryData.getOrDefault(key, null);
}
- public boolean setsupplementaryDatum(String key, double datum){
- boolean isSet = datum == supplementaryData.compute(key, (k, oldValue) -> datum);
- if (this.onSupplementalDatumUpdated != null){
- try{
- this.onSupplementalDatumUpdated.onSupplementalDatumUpdated(key, datum, this);
- }catch (Exception e){
- Log("Error in setsupplementaryDatum Callback: " + e.getMessage());
+ public boolean setSupplementaryDatum(String key, Double datum, SupplementalDatumUpdate update) {
+ Double newValue = supplementaryData.compute(key, (k, oldValue) -> update.supplementalDatumUpdate(k, oldValue, datum));
+ boolean result = java.util.Objects.equals(datum, newValue);
+ if (result && supplementalDatumUpdatedCallback != null) {
+ try {
+ supplementalDatumUpdatedCallback.onSupplementalDatumUpdated(key, datum, this);
+ } catch (Exception e) {
+ Log("Error in OnSupplementalDatumUpdated Callback: " + e.getMessage());
}
}
- return isSet;
+ return result;
}
- public Map getAllSupplementaryData(){return readonlySupplementaryData;}
+ public Map getAllSupplementaryData() {
+ return readonlySupplementaryData;
+ }
- public SecurityData getSecurityData(String tickerSymbol){
- return data.getOrDefault(tickerSymbol, null);
+ public Double getSecuritySupplementalDatum(String tickerSymbol, String key) {
+ SecurityData securityData = securities.get(tickerSymbol);
+ return securityData != null ? securityData.getSupplementaryDatum(key) : null;
}
- public Map getAllSecurityData(){
- return readonlyData;
+ public boolean setSecuritySupplementalDatum(String tickerSymbol, String key, Double datum, SupplementalDatumUpdate update) {
+ if (tickerSymbol != null && !tickerSymbol.trim().isEmpty()) {
+ SecurityData securityData = securities.computeIfAbsent(tickerSymbol, k -> new CurrentSecurityData(tickerSymbol, null, null, null));
+ return securityData.setSupplementaryDatum(key, datum, securitySupplementalDatumUpdatedCallback, this, update);
+ }
+ return false;
}
- public intrinio.realtime.equities.Trade getEquityTrade(String tickerSymbol){
- if (data.containsKey(tickerSymbol))
- return data.get(tickerSymbol).getEquitiesTrade();
- else return null;
+ public Double getOptionsContractSupplementalDatum(String tickerSymbol, String contract, String key) {
+ SecurityData securityData = securities.get(tickerSymbol);
+ return securityData != null ? securityData.getOptionsContractSupplementalDatum(contract, key) : null;
}
- public boolean setEquityTrade(intrinio.realtime.equities.Trade trade){
- String symbol = trade.symbol();
- CurrentSecurityData securityData;
- if (data.containsKey(symbol)){
- securityData = data.get(symbol);
- }
- else {
- CurrentSecurityData newData = new CurrentSecurityData(symbol);
- CurrentSecurityData possiblyNewerData = data.putIfAbsent(symbol, newData);
- securityData = Objects.requireNonNullElse(possiblyNewerData, newData);
+ public boolean setOptionSupplementalDatum(String tickerSymbol, String contract, String key, Double datum, SupplementalDatumUpdate update) {
+ if (tickerSymbol != null && !tickerSymbol.trim().isEmpty()) {
+ SecurityData securityData = securities.computeIfAbsent(tickerSymbol, k -> new CurrentSecurityData(tickerSymbol, null, null, null));
+ return securityData.setOptionsContractSupplementalDatum(contract, key, datum, optionsContractSupplementalDatumUpdatedCallback, this, update);
}
- return securityData.setEquitiesTrade(trade, this.onEquitiesTradeUpdated, this);
+ return false;
}
- public intrinio.realtime.equities.Quote getEquityQuote(String tickerSymbol){
- if (data.containsKey(tickerSymbol))
- return data.get(tickerSymbol).getEquitiesQuote();
- else return null;
+ public Greek getOptionsContractGreekData(String tickerSymbol, String contract, String key) {
+ SecurityData securityData = securities.get(tickerSymbol);
+ return securityData != null ? securityData.getOptionsContractGreekData(contract, key) : null;
}
- public boolean setEquityQuote(intrinio.realtime.equities.Quote quote){
- String symbol = quote.symbol();
- CurrentSecurityData securityData;
- if (data.containsKey(symbol)){
- securityData = data.get(symbol);
+ public boolean setOptionGreekData(String tickerSymbol, String contract, String key, Greek data, GreekDataUpdate update) {
+ if (tickerSymbol != null && !tickerSymbol.trim().isEmpty()) {
+ SecurityData securityData = securities.computeIfAbsent(tickerSymbol, k -> new CurrentSecurityData(tickerSymbol, null, null, null));
+ return securityData.setOptionsContractGreekData(contract, key, data, optionsContractGreekDataUpdatedCallback, this, update);
}
- else {
- CurrentSecurityData newData = new CurrentSecurityData(symbol);
- CurrentSecurityData possiblyNewerData = data.putIfAbsent(symbol, newData);
- securityData = Objects.requireNonNullElse(possiblyNewerData, newData);
- }
- return securityData.setEquitiesQuote(quote, this.onEquitiesQuoteUpdated, this);
+ return false;
}
- public OptionsContractData getOptionsContractData(String tickerSymbol, String contract){
- if (data.containsKey(tickerSymbol))
- return data.get(tickerSymbol).getOptionsContractData(contract);
- else return null;
+ public SecurityData getSecurityData(String tickerSymbol) {
+ return securities.get(tickerSymbol);
}
- public intrinio.realtime.options.Trade getOptionsTrade(String tickerSymbol, String contract){
- if (data.containsKey(tickerSymbol))
- return data.get(tickerSymbol).getOptionsContractTrade(contract);
- else return null;
+ public Map getAllSecurityData() {
+ return readonlySecurities;
}
- public boolean setOptionsTrade(intrinio.realtime.options.Trade trade){
- String underlyingSymbol = trade.getUnderlyingSymbol();
- CurrentSecurityData securityData;
- if (data.containsKey(underlyingSymbol)){
- securityData = data.get(underlyingSymbol);
- }
- else {
- CurrentSecurityData newData = new CurrentSecurityData(underlyingSymbol);
- CurrentSecurityData possiblyNewerData = data.putIfAbsent(underlyingSymbol, newData);
- securityData = Objects.requireNonNullElse(possiblyNewerData, newData);
- }
- return securityData.setOptionsTrade(trade, this.onOptionsTradeUpdated, this);
+ public OptionsContractData getOptionsContractData(String tickerSymbol, String contract) {
+ SecurityData securityData = securities.get(tickerSymbol);
+ return securityData != null ? securityData.getOptionsContractData(contract) : null;
}
- public intrinio.realtime.options.Quote getOptionsQuote(String tickerSymbol, String contract){
- if (data.containsKey(tickerSymbol))
- return data.get(tickerSymbol).getOptionsContractQuote(contract);
- else return null;
+ public Map getAllOptionsContractData(String tickerSymbol) {
+ SecurityData securityData = securities.get(tickerSymbol);
+ return securityData != null ? securityData.getAllOptionsContractData() : Collections.emptyMap();
}
- public boolean setOptionsQuote(intrinio.realtime.options.Quote quote){
- String underlyingSymbol = quote.getUnderlyingSymbol();
- CurrentSecurityData securityData;
- if (data.containsKey(underlyingSymbol)){
- securityData = data.get(underlyingSymbol);
- }
- else {
- CurrentSecurityData newData = new CurrentSecurityData(underlyingSymbol);
- CurrentSecurityData possiblyNewerData = data.putIfAbsent(underlyingSymbol, newData);
- securityData = Objects.requireNonNullElse(possiblyNewerData, newData);
+ public intrinio.realtime.equities.Trade getLatestEquityTrade(String tickerSymbol) {
+ SecurityData securityData = securities.get(tickerSymbol);
+ return securityData != null ? securityData.getLatestEquitiesTrade() : null;
+ }
+
+ public boolean setEquityTrade(intrinio.realtime.equities.Trade trade) {
+ if (trade != null) {
+ String symbol = trade.symbol();
+ SecurityData securityData = securities.computeIfAbsent(symbol, k -> new CurrentSecurityData(symbol, trade, null, null));
+ return securityData.setEquitiesTrade(trade, equitiesTradeUpdatedCallback, this);
}
- return securityData.setOptionsQuote(quote, this.onOptionsQuoteUpdated, this);
+ return false;
}
- public intrinio.realtime.options.Refresh getOptionsRefresh(String tickerSymbol, String contract){
- if (data.containsKey(tickerSymbol))
- return data.get(tickerSymbol).getOptionsContractRefresh(contract);
- else return null;
+ public void onTrade(intrinio.realtime.equities.Trade trade) {
+ setEquityTrade(trade);
}
- public boolean setOptionsRefresh(intrinio.realtime.options.Refresh refresh){
- String underlyingSymbol = refresh.getUnderlyingSymbol();
- CurrentSecurityData securityData;
- if (data.containsKey(underlyingSymbol)){
- securityData = data.get(underlyingSymbol);
- }
- else {
- CurrentSecurityData newData = new CurrentSecurityData(underlyingSymbol);
- CurrentSecurityData possiblyNewerData = data.putIfAbsent(underlyingSymbol, newData);
- securityData = Objects.requireNonNullElse(possiblyNewerData, newData);
+ public intrinio.realtime.equities.Quote getLatestEquityAskQuote(String tickerSymbol) {
+ SecurityData securityData = securities.get(tickerSymbol);
+ return securityData != null ? securityData.getLatestEquitiesAskQuote() : null;
+ }
+
+ public intrinio.realtime.equities.Quote getLatestEquityBidQuote(String tickerSymbol) {
+ SecurityData securityData = securities.get(tickerSymbol);
+ return securityData != null ? securityData.getLatestEquitiesBidQuote() : null;
+ }
+
+ public boolean setEquityQuote(intrinio.realtime.equities.Quote quote) {
+ if (quote != null) {
+ String symbol = quote.symbol();
+ SecurityData securityData = securities.computeIfAbsent(symbol, k -> new CurrentSecurityData(symbol, null, quote.type() == intrinio.realtime.equities.QuoteType.ASK ? quote : null, quote.type() == intrinio.realtime.equities.QuoteType.BID ? quote : null));
+ return securityData.setEquitiesQuote(quote, equitiesQuoteUpdatedCallback, this);
}
- return securityData.setOptionsRefresh(refresh, this.onOptionsRefreshUpdated, this);
+ return false;
+ }
+
+ public void onQuote(intrinio.realtime.equities.Quote quote) {
+ setEquityQuote(quote);
}
- public Double getSecuritySupplementalDatum(String tickerSymbol, String key){
- if (data.containsKey(tickerSymbol))
- return data.get(tickerSymbol).getSupplementaryDatum(key);
- else return null;
+ public intrinio.realtime.options.Trade getLatestOptionsTrade(String tickerSymbol, String contract) {
+ SecurityData securityData = securities.get(tickerSymbol);
+ return securityData != null ? securityData.getOptionsContractTrade(contract) : null;
}
- public boolean setSecuritySupplementalDatum(String tickerSymbol, String key, double datum){
- boolean result = false;
- CurrentSecurityData currentSecurityData;
- if (data.containsKey(tickerSymbol)) {
- currentSecurityData = data.get(tickerSymbol);
+ public boolean setOptionsTrade(intrinio.realtime.options.Trade trade) {
+ if (trade != null) {
+ String underlyingSymbol = trade.getUnderlyingSymbol();
+ SecurityData securityData = securities.computeIfAbsent(underlyingSymbol, k -> new CurrentSecurityData(underlyingSymbol, null, null, null));
+ return securityData.setOptionsContractTrade(trade, optionsTradeUpdatedCallback, this);
}
- else {
- CurrentSecurityData newData = new CurrentSecurityData(tickerSymbol);
- CurrentSecurityData possiblyNewerData = data.putIfAbsent(tickerSymbol, newData);
- currentSecurityData = possiblyNewerData == null ? newData : possiblyNewerData;
+ return false;
+ }
+
+ public void onTrade(intrinio.realtime.options.Trade trade) {
+ setOptionsTrade(trade);
+ }
+
+ public intrinio.realtime.options.Quote getLatestOptionsQuote(String tickerSymbol, String contract) {
+ SecurityData securityData = securities.get(tickerSymbol);
+ return securityData != null ? securityData.getOptionsContractQuote(contract) : null;
+ }
+
+ public boolean setOptionsQuote(intrinio.realtime.options.Quote quote) {
+ if (quote != null) {
+ String underlyingSymbol = quote.getUnderlyingSymbol();
+ SecurityData securityData = securities.computeIfAbsent(underlyingSymbol, k -> new CurrentSecurityData(underlyingSymbol, null, null, null));
+ return securityData.setOptionsContractQuote(quote, optionsQuoteUpdatedCallback, this);
}
- return currentSecurityData.setSupplementaryDatum(key, datum, this.onSecuritySupplementalDatumUpdated, this);
+ return false;
+ }
+
+ public void onQuote(intrinio.realtime.options.Quote quote) {
+ setOptionsQuote(quote);
}
- public Double getOptionsContractSupplementalDatum(String tickerSymbol, String contract, String key){
- if (data.containsKey(tickerSymbol))
- return data.get(tickerSymbol).getOptionsContractSupplementalDatum(contract, key);
- else return null;
+ public intrinio.realtime.options.Refresh getLatestOptionsRefresh(String tickerSymbol, String contract) {
+ SecurityData securityData = securities.get(tickerSymbol);
+ return securityData != null ? securityData.getOptionsContractRefresh(contract) : null;
}
- public boolean setOptionSupplementalDatum(String tickerSymbol, String contract, String key, double datum){
- CurrentSecurityData currentSecurityData;
- if (data.containsKey(tickerSymbol)) {
- currentSecurityData = data.get(tickerSymbol);
+ public boolean setOptionsRefresh(intrinio.realtime.options.Refresh refresh) {
+ if (refresh != null) {
+ String underlyingSymbol = refresh.getUnderlyingSymbol();
+ SecurityData securityData = securities.computeIfAbsent(underlyingSymbol, k -> new CurrentSecurityData(underlyingSymbol, null, null, null));
+ return securityData.setOptionsContractRefresh(refresh, optionsRefreshUpdatedCallback, this);
}
- else {
- CurrentSecurityData newData = new CurrentSecurityData(tickerSymbol);
- CurrentSecurityData possiblyNewerData = data.putIfAbsent(tickerSymbol, newData);
- currentSecurityData = possiblyNewerData == null ? newData : possiblyNewerData;
+ return false;
+ }
+
+ public void onRefresh(intrinio.realtime.options.Refresh refresh) {
+ setOptionsRefresh(refresh);
+ }
+
+ public intrinio.realtime.options.UnusualActivity getLatestOptionsUnusualActivity(String tickerSymbol, String contract) {
+ SecurityData securityData = securities.get(tickerSymbol);
+ return securityData != null ? securityData.getOptionsContractUnusualActivity(contract) : null;
+ }
+
+ public boolean setOptionsUnusualActivity(intrinio.realtime.options.UnusualActivity unusualActivity) {
+ if (unusualActivity != null) {
+ String underlyingSymbol = unusualActivity.getUnderlyingSymbol();
+ SecurityData securityData = securities.computeIfAbsent(underlyingSymbol, k -> new CurrentSecurityData(underlyingSymbol, null, null, null));
+ return securityData.setOptionsContractUnusualActivity(unusualActivity, optionsUnusualActivityUpdatedCallback, this);
}
- return currentSecurityData.setOptionsContractSupplementalDatum(contract, key, datum, onOptionsContractSupplementalDatumUpdated, this);
+ return false;
+ }
+
+ public void onUnusualActivity(intrinio.realtime.options.UnusualActivity unusualActivity) {
+ setOptionsUnusualActivity(unusualActivity);
+ }
+
+ public OnSupplementalDatumUpdated getSupplementalDatumUpdatedCallback() {
+ return supplementalDatumUpdatedCallback;
+ }
+
+ public void setSupplementalDatumUpdatedCallback(OnSupplementalDatumUpdated supplementalDatumUpdatedCallback) {
+ this.supplementalDatumUpdatedCallback = supplementalDatumUpdatedCallback;
+ }
+
+ public OnSecuritySupplementalDatumUpdated getSecuritySupplementalDatumUpdatedCallback() {
+ return securitySupplementalDatumUpdatedCallback;
+ }
+
+ public void setSecuritySupplementalDatumUpdatedCallback(OnSecuritySupplementalDatumUpdated securitySupplementalDatumUpdatedCallback) {
+ this.securitySupplementalDatumUpdatedCallback = securitySupplementalDatumUpdatedCallback;
}
- public void setOnSupplementalDatumUpdated(OnSupplementalDatumUpdated onSupplementalDatumUpdated){
- this.onSupplementalDatumUpdated = onSupplementalDatumUpdated;
+ public OnOptionsContractSupplementalDatumUpdated getOptionsContractSupplementalDatumUpdatedCallback() {
+ return optionsContractSupplementalDatumUpdatedCallback;
}
- public void setOnSecuritySupplementalDatumUpdated(OnSecuritySupplementalDatumUpdated onSecuritySupplementalDatumUpdated){
- this.onSecuritySupplementalDatumUpdated = onSecuritySupplementalDatumUpdated;
+ public void setOptionsContractSupplementalDatumUpdatedCallback(OnOptionsContractSupplementalDatumUpdated optionsContractSupplementalDatumUpdatedCallback) {
+ this.optionsContractSupplementalDatumUpdatedCallback = optionsContractSupplementalDatumUpdatedCallback;
}
- public void setOnOptionSupplementalDatumUpdated(OnOptionsContractSupplementalDatumUpdated onOptionsContractSupplementalDatumUpdated){
- this.onOptionsContractSupplementalDatumUpdated = onOptionsContractSupplementalDatumUpdated;
+ public OnOptionsContractGreekDataUpdated getOptionsContractGreekDataUpdatedCallback() {
+ return optionsContractGreekDataUpdatedCallback;
}
- public void setOnEquitiesQuoteUpdated(OnEquitiesQuoteUpdated onEquitiesQuoteUpdated){
- this.onEquitiesQuoteUpdated = onEquitiesQuoteUpdated;
+ public void setOptionsContractGreekDataUpdatedCallback(OnOptionsContractGreekDataUpdated optionsContractGreekDataUpdatedCallback) {
+ this.optionsContractGreekDataUpdatedCallback = optionsContractGreekDataUpdatedCallback;
}
- public void setOnEquitiesTradeUpdated(OnEquitiesTradeUpdated onEquitiesTradeUpdated){
- this.onEquitiesTradeUpdated = onEquitiesTradeUpdated;
+ public OnEquitiesTradeUpdated getEquitiesTradeUpdatedCallback() {
+ return equitiesTradeUpdatedCallback;
}
- public void setOnOptionsQuoteUpdated(OnOptionsQuoteUpdated onOptionsQuoteUpdated){
- this.onOptionsQuoteUpdated = onOptionsQuoteUpdated;
+ public void setEquitiesTradeUpdatedCallback(OnEquitiesTradeUpdated equitiesTradeUpdatedCallback) {
+ this.equitiesTradeUpdatedCallback = equitiesTradeUpdatedCallback;
}
- public void setOnOptionsTradeUpdated(OnOptionsTradeUpdated onOptionsTradeUpdated){
- this.onOptionsTradeUpdated = onOptionsTradeUpdated;
+ public OnEquitiesQuoteUpdated getEquitiesQuoteUpdatedCallback() {
+ return equitiesQuoteUpdatedCallback;
}
- public void setOnOptionsRefreshUpdated(OnOptionsRefreshUpdated onOptionsRefreshUpdated){
- this.onOptionsRefreshUpdated = onOptionsRefreshUpdated;
+ public void setEquitiesQuoteUpdatedCallback(OnEquitiesQuoteUpdated equitiesQuoteUpdatedCallback) {
+ this.equitiesQuoteUpdatedCallback = equitiesQuoteUpdatedCallback;
}
- //endregion Public Methods
- //region Private Methods
+ public OnOptionsTradeUpdated getOptionsTradeUpdatedCallback() {
+ return optionsTradeUpdatedCallback;
+ }
+
+ public void setOptionsTradeUpdatedCallback(OnOptionsTradeUpdated optionsTradeUpdatedCallback) {
+ this.optionsTradeUpdatedCallback = optionsTradeUpdatedCallback;
+ }
+
+ public OnOptionsQuoteUpdated getOptionsQuoteUpdatedCallback() {
+ return optionsQuoteUpdatedCallback;
+ }
+
+ public void setOptionsQuoteUpdatedCallback(OnOptionsQuoteUpdated optionsQuoteUpdatedCallback) {
+ this.optionsQuoteUpdatedCallback = optionsQuoteUpdatedCallback;
+ }
+
+ public OnOptionsRefreshUpdated getOptionsRefreshUpdatedCallback() {
+ return optionsRefreshUpdatedCallback;
+ }
+
+ public void setOptionsRefreshUpdatedCallback(OnOptionsRefreshUpdated optionsRefreshUpdatedCallback) {
+ this.optionsRefreshUpdatedCallback = optionsRefreshUpdatedCallback;
+ }
+
+ public OnOptionsUnusualActivityUpdated getOptionsUnusualActivityUpdatedCallback() {
+ return optionsUnusualActivityUpdatedCallback;
+ }
+
+ public void setOptionsUnusualActivityUpdatedCallback(OnOptionsUnusualActivityUpdated optionsUnusualActivityUpdatedCallback) {
+ this.optionsUnusualActivityUpdatedCallback = optionsUnusualActivityUpdatedCallback;
+ }
+
private void Log(String message){
System.out.println(message);
}
-
- //endregion Private Methods
-}
+}
\ No newline at end of file
diff --git a/src/intrinio/realtime/composite/CurrentOptionsContractData.java b/src/intrinio/realtime/composite/CurrentOptionsContractData.java
index 23e051d..bb93d2b 100644
--- a/src/intrinio/realtime/composite/CurrentOptionsContractData.java
+++ b/src/intrinio/realtime/composite/CurrentOptionsContractData.java
@@ -1,126 +1,209 @@
package intrinio.realtime.composite;
-import java.util.Map;
+import intrinio.realtime.options.Trade;
+import intrinio.realtime.options.Quote;
+import intrinio.realtime.options.Refresh;
+import intrinio.realtime.options.UnusualActivity;
+import intrinio.realtime.options.QuoteType;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.Collections;
+import java.util.Map;
-public class CurrentOptionsContractData implements OptionsContractData {
+/**
+ * Not for Use yet. Subject to change.
+ */
+class CurrentOptionsContractData implements OptionsContractData {
private final String contract;
- private volatile intrinio.realtime.options.Trade latestTrade;
- private volatile intrinio.realtime.options.Quote latestQuote;
- private volatile intrinio.realtime.options.Refresh latestRefresh;
- private final ConcurrentHashMap supplementaryData;
- private final Map readonlySupplementaryData;
-
- public CurrentOptionsContractData(String contract, intrinio.realtime.options.Trade latestTrade, intrinio.realtime.options.Quote latestQuote, intrinio.realtime.options.Refresh latestRefresh){
+ private Trade latestTrade;
+ private Quote latestQuote;
+ private Refresh latestRefresh;
+ private UnusualActivity latestUnusualActivity;
+ private final ConcurrentHashMap supplementaryData = new ConcurrentHashMap<>();
+ private final Map readonlySupplementaryData = Collections.unmodifiableMap(supplementaryData);
+ private final ConcurrentHashMap greekData = new ConcurrentHashMap<>();
+ private final Map readonlyGreekData = Collections.unmodifiableMap(greekData);
+
+ public CurrentOptionsContractData(String contract,
+ Trade latestTrade,
+ Quote latestQuote,
+ Refresh latestRefresh,
+ UnusualActivity latestUnusualActivity) {
this.contract = contract;
this.latestTrade = latestTrade;
this.latestQuote = latestQuote;
this.latestRefresh = latestRefresh;
- this.supplementaryData = new ConcurrentHashMap();
- this.readonlySupplementaryData = java.util.Collections.unmodifiableMap(supplementaryData);
+ this.latestUnusualActivity = latestUnusualActivity;
}
- public String getContract(){
+ @Override
+ public String getContract() {
return this.contract;
}
- public intrinio.realtime.options.Trade getTrade(){
+ @Override
+ public Trade getLatestTrade() {
return this.latestTrade;
}
- public intrinio.realtime.options.Quote getQuote(){
+ @Override
+ public Quote getLatestQuote() {
return this.latestQuote;
}
- public intrinio.realtime.options.Refresh getRefresh(){
+ @Override
+ public Refresh getLatestRefresh() {
return this.latestRefresh;
}
- public boolean setTrade(intrinio.realtime.options.Trade trade){
+ @Override
+ public UnusualActivity getLatestUnusualActivity() {
+ return this.latestUnusualActivity;
+ }
+
+ @Override
+ public boolean setTrade(Trade trade) {
//dirty set
- if ((latestTrade == null) || (trade.timestamp() > latestTrade.timestamp())) {
- latestTrade = trade;
+ if (this.latestTrade == null || (trade != null && trade.timestamp() > this.latestTrade.timestamp())) {
+ this.latestTrade = trade;
return true;
}
return false;
}
- boolean setTrade(intrinio.realtime.options.Trade trade, OnOptionsTradeUpdated onOptionsTradeUpdated, SecurityData securityData, DataCache dataCache){
- boolean isSet = this.setTrade(trade);
- if (isSet && onOptionsTradeUpdated != null){
- try{
- onOptionsTradeUpdated.onOptionsTradeUpdated(this, dataCache, securityData);
- }catch (Exception e){
- Log("Error in onOptionsTradeUpdated Callback: " + e.getMessage());
+ @Override
+ public boolean setTrade(Trade trade, OnOptionsTradeUpdated onOptionsTradeUpdated, SecurityData securityData, DataCache dataCache) {
+ boolean isSet = setTrade(trade);
+ if (isSet && onOptionsTradeUpdated != null) {
+ try {
+ onOptionsTradeUpdated.onOptionsTradeUpdated(this, dataCache, securityData, trade);
+ } catch (Exception e) {
+ Log("Error in OnOptionsTradeUpdated Callback: " + e.getMessage());
}
}
return isSet;
}
- public boolean setQuote(intrinio.realtime.options.Quote quote){
+ @Override
+ public boolean setQuote(Quote quote) {
//dirty set
- if ((latestQuote == null) || (quote.timestamp() > latestQuote.timestamp())) {
- latestQuote = quote;
+ if (this.latestQuote == null || (quote != null && quote.timestamp() > this.latestQuote.timestamp())) {
+ this.latestQuote = quote;
return true;
}
return false;
}
- boolean setQuote(intrinio.realtime.options.Quote quote, OnOptionsQuoteUpdated onOptionsQuoteUpdated, SecurityData securityData, DataCache dataCache){
+ @Override
+ public boolean setQuote(Quote quote, OnOptionsQuoteUpdated onOptionsQuoteUpdated, SecurityData securityData, DataCache dataCache) {
boolean isSet = this.setQuote(quote);
- if (isSet && onOptionsQuoteUpdated != null){
- try{
- onOptionsQuoteUpdated.onOptionsQuoteUpdated(this, dataCache, securityData);
- }catch (Exception e){
+ if (isSet && onOptionsQuoteUpdated != null) {
+ try {
+ onOptionsQuoteUpdated.onOptionsQuoteUpdated(this, dataCache, securityData, quote);
+ } catch (Exception e) {
Log("Error in onOptionsQuoteUpdated Callback: " + e.getMessage());
}
}
return isSet;
}
- public boolean setRefresh(intrinio.realtime.options.Refresh refresh){
- latestRefresh = refresh;
+ @Override
+ public boolean setRefresh(Refresh refresh) {
+ this.latestRefresh = refresh;
return true;
}
- boolean setRefresh(intrinio.realtime.options.Refresh refresh, OnOptionsRefreshUpdated onOptionsRefreshUpdated, SecurityData securityData, DataCache dataCache){
+ @Override
+ public boolean setRefresh(Refresh refresh, OnOptionsRefreshUpdated onOptionsRefreshUpdated, SecurityData securityData, DataCache dataCache) {
boolean isSet = this.setRefresh(refresh);
- if (isSet && onOptionsRefreshUpdated != null){
- try{
- onOptionsRefreshUpdated.onOptionsRefreshUpdated(this, dataCache, securityData);
- }catch (Exception e){
+ if (isSet && onOptionsRefreshUpdated != null) {
+ try {
+ onOptionsRefreshUpdated.onOptionsRefreshUpdated(this, dataCache, securityData, refresh);
+ } catch (Exception e) {
Log("Error in onOptionsRefreshUpdated Callback: " + e.getMessage());
}
}
return isSet;
}
- public Double getSupplementaryDatum(String key){
+ @Override
+ public boolean setUnusualActivity(UnusualActivity unusualActivity) {
+ this.latestUnusualActivity = unusualActivity;
+ return true;
+ }
+
+ @Override
+ public boolean setUnusualActivity(UnusualActivity unusualActivity, OnOptionsUnusualActivityUpdated onOptionsUnusualActivityUpdated, SecurityData securityData, DataCache dataCache) {
+ boolean isSet = this.setUnusualActivity(unusualActivity);
+ if (isSet && onOptionsUnusualActivityUpdated != null) {
+ try {
+ onOptionsUnusualActivityUpdated.onOptionsUnusualActivityUpdated(this, dataCache, securityData, unusualActivity);
+ } catch (Exception e) {
+ Log("Error in onOptionsUnusualActivityUpdated Callback: " + e.getMessage());
+ }
+ }
+ return isSet;
+ }
+
+ @Override
+ public Double getSupplementaryDatum(String key) {
return supplementaryData.getOrDefault(key, null);
}
- public boolean setSupplementaryDatum(String key, double datum){
- return datum == supplementaryData.compute(key, (k, oldValue) -> datum);
+ @Override
+ public boolean setSupplementaryDatum(String key, Double datum, SupplementalDatumUpdate update) {
+ Double newValue = supplementaryData.compute(key, (k, oldValue) -> update.supplementalDatumUpdate(k, oldValue, datum));
+ return java.util.Objects.equals(datum, newValue);
}
- boolean setSupplementaryDatum(String key, double datum, OnOptionsContractSupplementalDatumUpdated onOptionsContractSupplementalDatumUpdated, SecurityData securityData, DataCache dataCache){
- boolean result = setSupplementaryDatum(key, datum);
- if (result && onOptionsContractSupplementalDatumUpdated != null){
- try{
+ @Override
+ public boolean setSupplementaryDatum(String key, Double datum, OnOptionsContractSupplementalDatumUpdated onOptionsContractSupplementalDatumUpdated, SecurityData securityData, DataCache dataCache, SupplementalDatumUpdate update) {
+ boolean result = setSupplementaryDatum(key, datum, update);
+ if (result && onOptionsContractSupplementalDatumUpdated != null) {
+ try {
onOptionsContractSupplementalDatumUpdated.onOptionsContractSupplementalDatumUpdated(key, datum, this, securityData, dataCache);
- }catch (Exception e){
+ } catch (Exception e) {
Log("Error in onOptionsContractSupplementalDatumUpdated Callback: " + e.getMessage());
}
}
return result;
}
- public Map getAllSupplementaryData(){return readonlySupplementaryData;}
+ @Override
+ public Map getAllSupplementaryData() {
+ return readonlySupplementaryData;
+ }
+
+ @Override
+ public Greek getGreekData(String key) {
+ return greekData.getOrDefault(key, null);
+ }
+
+ @Override
+ public boolean setGreekData(String key, Greek datum, GreekDataUpdate update) {
+ Greek newValue = greekData.compute(key, (k, oldValue) -> update.greekDataUpdate(k, oldValue, datum));
+ return (newValue != null && datum != null && newValue.equals(datum))
+ || (newValue == null && datum == null);
+ }
+
+ @Override
+ public boolean setGreekData(String key, Greek datum, OnOptionsContractGreekDataUpdated onOptionsContractGreekDataUpdated, SecurityData securityData, DataCache dataCache, GreekDataUpdate update) {
+ boolean result = setGreekData(key, datum, update);
+ if (result && onOptionsContractGreekDataUpdated != null) {
+ try {
+ onOptionsContractGreekDataUpdated.onOptionsContractGreekDataUpdated(key, datum, this, securityData, dataCache);
+ } catch (Exception e) {
+ Log("Error in onOptionsContractGreekDataUpdated Callback: " + e.getMessage());
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public Map getAllGreekData() {
+ return readonlyGreekData;
+ }
- //region Private Methods
private void Log(String message){
System.out.println(message);
}
-
- //endregion Private Methods
-}
+}
\ No newline at end of file
diff --git a/src/intrinio/realtime/composite/CurrentSecurityData.java b/src/intrinio/realtime/composite/CurrentSecurityData.java
index 6f6a939..687f141 100644
--- a/src/intrinio/realtime/composite/CurrentSecurityData.java
+++ b/src/intrinio/realtime/composite/CurrentSecurityData.java
@@ -1,254 +1,352 @@
package intrinio.realtime.composite;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
-public class CurrentSecurityData implements SecurityData{
+class CurrentSecurityData implements SecurityData {
private final String tickerSymbol;
- private volatile intrinio.realtime.equities.Trade equitiesTrade;
- private volatile intrinio.realtime.equities.Quote equitiesQuote;
- private final ConcurrentHashMap contracts;
- private final Map readonlyContracts;
- private final ConcurrentHashMap supplementaryData;
- private final Map readonlySupplementaryData;
-
- public CurrentSecurityData(String tickerSymbol){
+ private intrinio.realtime.equities.Trade latestTrade;
+ private intrinio.realtime.equities.Quote latestAskQuote;
+ private intrinio.realtime.equities.Quote latestBidQuote;
+ private final ConcurrentHashMap contracts = new ConcurrentHashMap<>();
+ private final Map readonlyContracts = Collections.unmodifiableMap(contracts);
+ private final ConcurrentHashMap supplementaryData = new ConcurrentHashMap<>();
+ private final Map readonlySupplementaryData = Collections.unmodifiableMap(supplementaryData);
+
+ public CurrentSecurityData(String tickerSymbol,
+ intrinio.realtime.equities.Trade latestTrade,
+ intrinio.realtime.equities.Quote latestAskQuote,
+ intrinio.realtime.equities.Quote latestBidQuote) {
this.tickerSymbol = tickerSymbol;
- this.contracts = new ConcurrentHashMap();
- this.readonlyContracts = java.util.Collections.unmodifiableMap(contracts);
- this.supplementaryData = new ConcurrentHashMap();
- this.readonlySupplementaryData = java.util.Collections.unmodifiableMap(supplementaryData);
+ this.latestTrade = latestTrade;
+ this.latestAskQuote = latestAskQuote;
+ this.latestBidQuote = latestBidQuote;
}
- public String getTickerSymbol(){
+ @Override
+ public String getTickerSymbol() {
return tickerSymbol;
}
- public Double getSupplementaryDatum(String key){
- return supplementaryData.getOrDefault(key, null);
+ @Override
+ public intrinio.realtime.equities.Trade getLatestEquitiesTrade() {
+ return latestTrade;
}
- public boolean setSupplementaryDatum(String key, double datum){
- return datum == supplementaryData.compute(key, (k, oldValue) -> datum);
+ @Override
+ public intrinio.realtime.equities.Quote getLatestEquitiesAskQuote() {
+ return latestAskQuote;
}
- boolean setSupplementaryDatum(String key, double datum, OnSecuritySupplementalDatumUpdated onSecuritySupplementalDatumUpdated, CurrentDataCache currentDataCache){
- boolean result = setSupplementaryDatum(key, datum);
- if (result && onSecuritySupplementalDatumUpdated != null){
- try{
- onSecuritySupplementalDatumUpdated.onSecuritySupplementalDatumUpdated(key, datum, this, currentDataCache);
- }catch (Exception e){
- Log("Error in onSecuritySupplementalDatumUpdated Callback: " + e.getMessage());
- }
- }
- return result;
- }
-
- public Map getAllSupplementaryData(){return readonlySupplementaryData;}
-
- public intrinio.realtime.equities.Trade getEquitiesTrade(){
- return equitiesTrade;
+ @Override
+ public intrinio.realtime.equities.Quote getLatestEquitiesBidQuote() {
+ return latestBidQuote;
}
- public intrinio.realtime.equities.Quote getEquitiesQuote(){
- return equitiesQuote;
+ @Override
+ public Double getSupplementaryDatum(String key) {
+ return supplementaryData.getOrDefault(key, null);
}
- public OptionsContractData getOptionsContractData(String contract){
- return contracts.getOrDefault(contract, null);
+ @Override
+ public boolean setSupplementaryDatum(String key, Double datum, SupplementalDatumUpdate update) {
+ Double newValue = supplementaryData.compute(key, (k, oldValue) -> update.supplementalDatumUpdate(k, oldValue, datum));
+ return java.util.Objects.equals(datum, newValue);
}
- public Map getAllOptionsContractData(){
- return readonlyContracts;
+ @Override
+ public boolean setSupplementaryDatum(String key, Double datum, OnSecuritySupplementalDatumUpdated onSecuritySupplementalDatumUpdated, DataCache dataCache, SupplementalDatumUpdate update) {
+ boolean result = setSupplementaryDatum(key, datum, update);
+ if (result && onSecuritySupplementalDatumUpdated != null) {
+ try {
+ onSecuritySupplementalDatumUpdated.onSecuritySupplementalDatumUpdated(key, datum, this, dataCache);
+ } catch (Exception e) {
+ Log("Error in onSecuritySupplementalDatumUpdated Callback: " + e.getMessage());
+ }
+ }
+ return result;
}
- public List getContractNames(String ticker){
- return contracts.values().stream().map(CurrentOptionsContractData::getContract).collect(Collectors.toList());
+ @Override
+ public Map getAllSupplementaryData() {
+ return readonlySupplementaryData;
}
- public boolean setEquitiesTrade(intrinio.realtime.equities.Trade trade){
+ @Override
+ public boolean setEquitiesTrade(intrinio.realtime.equities.Trade trade) {
//dirty set
- if ((equitiesTrade == null) || (trade.timestamp() > equitiesTrade.timestamp())) {
- equitiesTrade = trade;
+ if (this.latestTrade == null || (trade != null && trade.timestamp() > this.latestTrade.timestamp())) {
+ this.latestTrade = trade;
return true;
}
return false;
}
- boolean setEquitiesTrade(intrinio.realtime.equities.Trade trade, OnEquitiesTradeUpdated onEquitiesTradeUpdated, DataCache dataCache){
- boolean isSet = this.setEquitiesTrade(trade);
- if (isSet && onEquitiesTradeUpdated != null){
- try{
- onEquitiesTradeUpdated.onEquitiesTradeUpdated(this, dataCache);
- }catch (Exception e){
+ @Override
+ public boolean setEquitiesTrade(intrinio.realtime.equities.Trade trade, OnEquitiesTradeUpdated onEquitiesTradeUpdated, DataCache dataCache) {
+ boolean isSet = setEquitiesTrade(trade);
+ if (isSet && onEquitiesTradeUpdated != null) {
+ try {
+ onEquitiesTradeUpdated.onEquitiesTradeUpdated(this, dataCache, trade);
+ } catch (Exception e) {
Log("Error in onEquitiesTradeUpdated Callback: " + e.getMessage());
}
}
return isSet;
}
- public boolean setEquitiesQuote(intrinio.realtime.equities.Quote quote){
- //dirty set
- if ((equitiesQuote == null) || (quote.timestamp() > equitiesQuote.timestamp())) {
- equitiesQuote = quote;
- return true;
+ @Override
+ public boolean setEquitiesQuote(intrinio.realtime.equities.Quote quote) {
+ if (quote != null) {
+ if (quote.type() == intrinio.realtime.equities.QuoteType.ASK) {
+ if (this.latestAskQuote == null || (quote.timestamp() > this.latestAskQuote.timestamp())) {
+ this.latestAskQuote = quote;
+ return true;
+ }
+ return false;
+ } else { // Bid
+ if (this.latestBidQuote == null || (quote.timestamp() > this.latestBidQuote.timestamp())) {
+ this.latestBidQuote = quote;
+ return true;
+ }
+ return false;
+ }
}
return false;
}
- boolean setEquitiesQuote(intrinio.realtime.equities.Quote quote, OnEquitiesQuoteUpdated onEquitiesQuoteUpdated, DataCache dataCache){
+ @Override
+ public boolean setEquitiesQuote(intrinio.realtime.equities.Quote quote, OnEquitiesQuoteUpdated onEquitiesQuoteUpdated, DataCache dataCache) {
boolean isSet = this.setEquitiesQuote(quote);
- if (isSet && onEquitiesQuoteUpdated != null){
- try{
- onEquitiesQuoteUpdated.onEquitiesQuoteUpdated(this, dataCache);
- }catch (Exception e){
+ if (isSet && onEquitiesQuoteUpdated != null) {
+ try {
+ onEquitiesQuoteUpdated.onEquitiesQuoteUpdated(this, dataCache, quote);
+ } catch (Exception e) {
Log("Error in onEquitiesQuoteUpdated Callback: " + e.getMessage());
}
}
return isSet;
}
- public intrinio.realtime.options.Trade getOptionsContractTrade(String contract){
- if (contracts.containsKey(contract))
- return contracts.get(contract).getTrade();
- else return null;
+ @Override
+ public OptionsContractData getOptionsContractData(String contract) {
+ return contracts.get(contract);
}
- public boolean setOptionsContractTrade(intrinio.realtime.options.Trade trade){
- //dirty set
- if (contracts.containsKey(trade.contract())){
- return contracts.get(trade.contract()).setTrade(trade);
- }
- else{
- CurrentOptionsContractData data = new CurrentOptionsContractData(trade.contract(), trade, null, null);
- CurrentOptionsContractData possiblyNewerData = contracts.putIfAbsent(trade.contract(), data);
- if (possiblyNewerData != null)
- return possiblyNewerData.setTrade(trade);
- return true;
- }
+ @Override
+ public Map getAllOptionsContractData() {
+ return readonlyContracts;
}
- public boolean setOptionsTrade(intrinio.realtime.options.Trade trade, OnOptionsTradeUpdated onOptionsTradeUpdated, DataCache dataCache){
- CurrentOptionsContractData currentOptionsContractData;
- String contract = trade.contract();
- if (contracts.containsKey(contract)) {
- currentOptionsContractData = contracts.get(contract);
+ public List getContractNames() {
+ return contracts.values().stream().map(OptionsContractData::getContract).collect(Collectors.toList());
+ }
+
+ @Override
+ public intrinio.realtime.options.Trade getOptionsContractTrade(String contract) {
+ OptionsContractData optionsContractData = contracts.get(contract);
+ return optionsContractData != null ? optionsContractData.getLatestTrade() : null;
+ }
+
+ @Override
+ public boolean setOptionsContractTrade(intrinio.realtime.options.Trade trade) {
+ if (trade != null) {
+ String contract = trade.contract();
+ OptionsContractData currentOptionsContractData = contracts.get(contract);
+ if (currentOptionsContractData == null) {
+ CurrentOptionsContractData newDatum = new CurrentOptionsContractData(contract, trade, null, null, null);
+ currentOptionsContractData = contracts.computeIfAbsent(contract, k -> newDatum);
+ }
+ return currentOptionsContractData.setTrade(trade);
}
- else {
- CurrentOptionsContractData newData = new CurrentOptionsContractData(contract, trade, null, null);
- CurrentOptionsContractData possiblyNewerData = contracts.putIfAbsent(contract, newData);
- currentOptionsContractData = possiblyNewerData == null ? newData : possiblyNewerData;
+ return false;
+ }
+
+ @Override
+ public boolean setOptionsContractTrade(intrinio.realtime.options.Trade trade, OnOptionsTradeUpdated onOptionsTradeUpdated, DataCache dataCache) {
+ if (trade != null) {
+ String contract = trade.contract();
+ OptionsContractData currentOptionsContractData = contracts.get(contract);
+ if (currentOptionsContractData == null) {
+ OptionsContractData newDatum = new CurrentOptionsContractData(contract, trade, null, null, null);
+ currentOptionsContractData = contracts.computeIfAbsent(contract, k -> newDatum);
+ }
+ return currentOptionsContractData.setTrade(trade, onOptionsTradeUpdated, this, dataCache);
}
- return currentOptionsContractData.setTrade(trade, onOptionsTradeUpdated, this, dataCache);
+ return false;
}
- public intrinio.realtime.options.Quote getOptionsContractQuote(String contract){
- if (contracts.containsKey(contract))
- return contracts.get(contract).getQuote();
- else return null;
+ @Override
+ public intrinio.realtime.options.Quote getOptionsContractQuote(String contract) {
+ OptionsContractData optionsContractData = contracts.get(contract);
+ return optionsContractData != null ? optionsContractData.getLatestQuote() : null;
}
- public boolean setOptionsContractQuote(intrinio.realtime.options.Quote quote){
- //dirty set
- if (contracts.containsKey(quote.contract())){
- return contracts.get(quote.contract()).setQuote(quote);
- }
- else{
- CurrentOptionsContractData data = new CurrentOptionsContractData(quote.contract(), null, quote, null);
- CurrentOptionsContractData possiblyNewerData = contracts.putIfAbsent(quote.contract(), data);
- if (possiblyNewerData != null)
- return possiblyNewerData.setQuote(quote);
- return true;
+ @Override
+ public boolean setOptionsContractQuote(intrinio.realtime.options.Quote quote) {
+ if (quote != null) {
+ String contract = quote.contract();
+ OptionsContractData currentOptionsContractData = contracts.get(contract);
+ if (currentOptionsContractData == null) {
+ OptionsContractData newDatum = new CurrentOptionsContractData(contract, null, quote, null, null);
+ currentOptionsContractData = contracts.computeIfAbsent(contract, k -> newDatum);
+ }
+ return currentOptionsContractData.setQuote(quote);
}
+ return false;
}
- public boolean setOptionsQuote(intrinio.realtime.options.Quote quote, OnOptionsQuoteUpdated onOptionsQuoteUpdated, DataCache dataCache){
- CurrentOptionsContractData currentOptionsContractData;
- String contract = quote.contract();
- if (contracts.containsKey(contract)) {
- currentOptionsContractData = contracts.get(contract);
- }
- else {
- CurrentOptionsContractData newData = new CurrentOptionsContractData(contract, null, quote, null);
- CurrentOptionsContractData possiblyNewerData = contracts.putIfAbsent(contract, newData);
- currentOptionsContractData = possiblyNewerData == null ? newData : possiblyNewerData;
+ @Override
+ public boolean setOptionsContractQuote(intrinio.realtime.options.Quote quote, OnOptionsQuoteUpdated onOptionsQuoteUpdated, DataCache dataCache) {
+ if (quote != null) {
+ String contract = quote.contract();
+ OptionsContractData currentOptionsContractData = contracts.get(contract);
+ if (currentOptionsContractData == null) {
+ OptionsContractData newDatum = new CurrentOptionsContractData(contract, null, quote, null, null);
+ currentOptionsContractData = contracts.computeIfAbsent(contract, k -> newDatum);
+ }
+ return currentOptionsContractData.setQuote(quote, onOptionsQuoteUpdated, this, dataCache);
}
- return currentOptionsContractData.setQuote(quote, onOptionsQuoteUpdated, this, dataCache);
+ return false;
}
- public intrinio.realtime.options.Refresh getOptionsContractRefresh(String contract){
- if (contracts.containsKey(contract))
- return contracts.get(contract).getRefresh();
- else return null;
+ @Override
+ public intrinio.realtime.options.Refresh getOptionsContractRefresh(String contract) {
+ OptionsContractData optionsContractData = contracts.get(contract);
+ return optionsContractData != null ? optionsContractData.getLatestRefresh() : null;
}
- public boolean setOptionsContractRefresh(intrinio.realtime.options.Refresh refresh){
- //dirty set
- String contract = refresh.contract();
- if (contracts.containsKey(contract)){
- return contracts.get(contract).setRefresh(refresh);
- }
- else{
- CurrentOptionsContractData data = new CurrentOptionsContractData(contract, null, null, refresh);
- CurrentOptionsContractData possiblyNewerData = contracts.putIfAbsent(contract, data);
- if (possiblyNewerData != null)
- return possiblyNewerData.setRefresh(refresh);
- return true;
+ @Override
+ public boolean setOptionsContractRefresh(intrinio.realtime.options.Refresh refresh) {
+ if (refresh != null) {
+ String contract = refresh.contract();
+ OptionsContractData currentOptionsContractData = contracts.get(contract);
+ if (currentOptionsContractData == null) {
+ OptionsContractData newDatum = new CurrentOptionsContractData(contract, null, null, refresh, null);
+ currentOptionsContractData = contracts.computeIfAbsent(contract, k -> newDatum);
+ }
+ return currentOptionsContractData.setRefresh(refresh);
}
+ return false;
}
- public boolean setOptionsRefresh(intrinio.realtime.options.Refresh refresh, OnOptionsRefreshUpdated onOptionsRefreshUpdated, DataCache dataCache){
- CurrentOptionsContractData currentOptionsContractData;
- String contract = refresh.contract();
- if (contracts.containsKey(contract)) {
- currentOptionsContractData = contracts.get(contract);
+ @Override
+ public boolean setOptionsContractRefresh(intrinio.realtime.options.Refresh refresh, OnOptionsRefreshUpdated onOptionsRefreshUpdated, DataCache dataCache) {
+ if (refresh != null) {
+ String contract = refresh.contract();
+ OptionsContractData currentOptionsContractData = contracts.get(contract);
+ if (currentOptionsContractData == null) {
+ OptionsContractData newDatum = new CurrentOptionsContractData(contract, null, null, refresh, null);
+ currentOptionsContractData = contracts.computeIfAbsent(contract, k -> newDatum);
+ }
+ return currentOptionsContractData.setRefresh(refresh, onOptionsRefreshUpdated, this, dataCache);
}
- else {
- CurrentOptionsContractData newData = new CurrentOptionsContractData(contract, null, null, refresh);
- CurrentOptionsContractData possiblyNewerData = contracts.putIfAbsent(contract, newData);
- currentOptionsContractData = possiblyNewerData == null ? newData : possiblyNewerData;
+ return false;
+ }
+
+ @Override
+ public intrinio.realtime.options.UnusualActivity getOptionsContractUnusualActivity(String contract) {
+ OptionsContractData optionsContractData = contracts.get(contract);
+ return optionsContractData != null ? optionsContractData.getLatestUnusualActivity() : null;
+ }
+
+ @Override
+ public boolean setOptionsContractUnusualActivity(intrinio.realtime.options.UnusualActivity unusualActivity) {
+ if (unusualActivity != null) {
+ String contract = unusualActivity.contract();
+ OptionsContractData currentOptionsContractData = contracts.get(contract);
+ if (currentOptionsContractData == null) {
+ OptionsContractData newDatum = new CurrentOptionsContractData(contract, null, null, null, unusualActivity);
+ currentOptionsContractData = contracts.computeIfAbsent(contract, k -> newDatum);
+ }
+ return currentOptionsContractData.setUnusualActivity(unusualActivity);
}
- return currentOptionsContractData.setRefresh(refresh, onOptionsRefreshUpdated, this, dataCache);
+ return false;
}
- public Double getOptionsContractSupplementalDatum(String contract, String key){
- if (contracts.containsKey(contract))
- return contracts.get(contract).getSupplementaryDatum(key);
- else return null;
+ @Override
+ public boolean setOptionsContractUnusualActivity(intrinio.realtime.options.UnusualActivity unusualActivity, OnOptionsUnusualActivityUpdated onOptionsUnusualActivityUpdated, DataCache dataCache) {
+ if (unusualActivity != null) {
+ String contract = unusualActivity.contract();
+ OptionsContractData currentOptionsContractData = contracts.get(contract);
+ if (currentOptionsContractData == null) {
+ OptionsContractData newDatum = new CurrentOptionsContractData(contract, null, null, null, unusualActivity);
+ currentOptionsContractData = contracts.computeIfAbsent(contract, k -> newDatum);
+ }
+ return currentOptionsContractData.setUnusualActivity(unusualActivity, onOptionsUnusualActivityUpdated, this, dataCache);
+ }
+ return false;
}
- public boolean setOptionsContractSupplementalDatum(String contract, String key, double datum){
- CurrentOptionsContractData currentOptionsContractData;
- if (contracts.containsKey(contract)) {
- currentOptionsContractData = contracts.get(contract);
+ @Override
+ public Double getOptionsContractSupplementalDatum(String contract, String key) {
+ OptionsContractData optionsContractData = contracts.get(contract);
+ return optionsContractData != null ? optionsContractData.getSupplementaryDatum(key) : null;
+ }
+
+ @Override
+ public boolean setOptionsContractSupplementalDatum(String contract, String key, Double datum, SupplementalDatumUpdate update) {
+ if (contract != null && !contract.trim().isEmpty()) {
+ OptionsContractData currentOptionsContractData = contracts.get(contract);
+ if (currentOptionsContractData == null) {
+ OptionsContractData newDatum = new CurrentOptionsContractData(contract, null, null, null, null);
+ currentOptionsContractData = contracts.computeIfAbsent(contract, k -> newDatum);
+ }
+ return currentOptionsContractData.setSupplementaryDatum(key, datum, update);
}
- else {
- CurrentOptionsContractData newData = new CurrentOptionsContractData(contract, null, null, null);
- CurrentOptionsContractData possiblyNewerData = contracts.putIfAbsent(contract, newData);
- currentOptionsContractData = possiblyNewerData == null ? newData : possiblyNewerData;
+ return false;
+ }
+
+ @Override
+ public boolean setOptionsContractSupplementalDatum(String contract, String key, Double datum, OnOptionsContractSupplementalDatumUpdated onOptionsContractSupplementalDatumUpdated, DataCache dataCache, SupplementalDatumUpdate update) {
+ if (contract != null && !contract.trim().isEmpty()) {
+ OptionsContractData currentOptionsContractData = contracts.get(contract);
+ if (currentOptionsContractData == null) {
+ OptionsContractData newDatum = new CurrentOptionsContractData(contract, null, null, null, null);
+ currentOptionsContractData = contracts.computeIfAbsent(contract, k -> newDatum);
+ }
+ return currentOptionsContractData.setSupplementaryDatum(key, datum, onOptionsContractSupplementalDatumUpdated, this, dataCache, update);
}
- return currentOptionsContractData.setSupplementaryDatum(key, datum);
+ return false;
}
- boolean setOptionsContractSupplementalDatum(String contract, String key, double datum, OnOptionsContractSupplementalDatumUpdated onOptionsContractSupplementalDatumUpdated, DataCache dataCache){
- CurrentOptionsContractData currentOptionsContractData;
- if (contracts.containsKey(contract)) {
- currentOptionsContractData = contracts.get(contract);
+ @Override
+ public Greek getOptionsContractGreekData(String contract, String key) {
+ OptionsContractData optionsContractData = contracts.get(contract);
+ return optionsContractData != null ? optionsContractData.getGreekData(key) : null;
+ }
+
+ @Override
+ public boolean setOptionsContractGreekData(String contract, String key, Greek data, GreekDataUpdate update) {
+ if (contract != null && !contract.trim().isEmpty()) {
+ OptionsContractData currentOptionsContractData = contracts.get(contract);
+ if (currentOptionsContractData == null) {
+ OptionsContractData newDatum = new CurrentOptionsContractData(contract, null, null, null, null);
+ currentOptionsContractData = contracts.computeIfAbsent(contract, k -> newDatum);
+ }
+ return currentOptionsContractData.setGreekData(key, data, update);
}
- else {
- CurrentOptionsContractData newData = new CurrentOptionsContractData(contract, null, null, null);
- CurrentOptionsContractData possiblyNewerData = contracts.putIfAbsent(contract, newData);
- currentOptionsContractData = possiblyNewerData == null ? newData : possiblyNewerData;
+ return false;
+ }
+
+ @Override
+ public boolean setOptionsContractGreekData(String contract, String key, Greek data, OnOptionsContractGreekDataUpdated onOptionsContractGreekDataUpdated, DataCache dataCache, GreekDataUpdate update) {
+ if (contract != null && !contract.trim().isEmpty()) {
+ OptionsContractData currentOptionsContractData = contracts.get(contract);
+ if (currentOptionsContractData == null) {
+ OptionsContractData newDatum = new CurrentOptionsContractData(contract, null, null, null, null);
+ currentOptionsContractData = contracts.computeIfAbsent(contract, k -> newDatum);
+ }
+ return currentOptionsContractData.setGreekData(key, data, onOptionsContractGreekDataUpdated, this, dataCache, update);
}
- return currentOptionsContractData.setSupplementaryDatum(key, datum, onOptionsContractSupplementalDatumUpdated, this, dataCache);
+ return false;
}
- //region Private Methods
private void Log(String message){
System.out.println(message);
}
-
- //endregion Private Methods
-}
+}
\ No newline at end of file
diff --git a/src/intrinio/realtime/composite/DataCache.java b/src/intrinio/realtime/composite/DataCache.java
index 8bfd1e4..37fccaf 100644
--- a/src/intrinio/realtime/composite/DataCache.java
+++ b/src/intrinio/realtime/composite/DataCache.java
@@ -1,62 +1,196 @@
package intrinio.realtime.composite;
-import java.util.*;
-
-public interface DataCache
-{
- Double getsupplementaryDatum(String key);
-
- boolean setsupplementaryDatum(String key, double datum);
-
+import java.util.Map;
+
+/**
+ * A non-transactional, thread-safe, volatile local cache for storing the latest data from a websocket.
+ */
+public interface DataCache {
+
+ /**
+ * Get a supplementary data point from the general cache.
+ */
+ Double getSupplementaryDatum(String key);
+
+ /**
+ * Set a supplementary data point in the general cache.
+ */
+ boolean setSupplementaryDatum(String key, Double datum, SupplementalDatumUpdate update);
+
+ /**
+ * Get all supplementary data stored at the top level general cache.
+ */
Map getAllSupplementaryData();
- SecurityData getSecurityData(String tickerSymbol);
-
- Map getAllSecurityData();
-
- intrinio.realtime.equities.Trade getEquityTrade(String tickerSymbol);
-
- boolean setEquityTrade(intrinio.realtime.equities.Trade trade);
+ /**
+ * Get a supplemental data point stored in a specific security's cache.
+ */
+ Double getSecuritySupplementalDatum(String tickerSymbol, String key);
- intrinio.realtime.equities.Quote getEquityQuote(String tickerSymbol);
+ /**
+ * Set a supplemental data point stored in a specific security's cache.
+ */
+ boolean setSecuritySupplementalDatum(String tickerSymbol, String key, Double datum, SupplementalDatumUpdate update);
- boolean setEquityQuote(intrinio.realtime.equities.Quote quote);
+ /**
+ * Get a supplemental data point stored in a specific option contract's cache.
+ */
+ Double getOptionsContractSupplementalDatum(String tickerSymbol, String contract, String key);
- OptionsContractData getOptionsContractData(String tickerSymbol, String contract);
+ /**
+ * Set a supplemental data point stored in a specific option contract's cache.
+ */
+ boolean setOptionSupplementalDatum(String tickerSymbol, String contract, String key, Double datum, SupplementalDatumUpdate update);
- intrinio.realtime.options.Trade getOptionsTrade(String tickerSymbol, String contract);
+ /**
+ * Get a supplemental data point stored in a specific option contract's cache.
+ */
+ Greek getOptionsContractGreekData(String tickerSymbol, String contract, String key);
- boolean setOptionsTrade(intrinio.realtime.options.Trade trade);
+ /**
+ * Set a supplemental data point stored in a specific option contract's cache.
+ */
+ boolean setOptionGreekData(String tickerSymbol, String contract, String key, Greek data, GreekDataUpdate update);
- intrinio.realtime.options.Quote getOptionsQuote(String tickerSymbol, String contract);
+ /**
+ * Get the cache for a specific security
+ */
+ SecurityData getSecurityData(String tickerSymbol);
- boolean setOptionsQuote(intrinio.realtime.options.Quote quote);
+ /**
+ * Get all security caches.
+ */
+ Map getAllSecurityData();
- intrinio.realtime.options.Refresh getOptionsRefresh(String tickerSymbol, String contract);
+ /**
+ * Get a specific option contract's cache.
+ */
+ OptionsContractData getOptionsContractData(String tickerSymbol, String contract);
- boolean setOptionsRefresh(intrinio.realtime.options.Refresh refresh);
+ /**
+ * Get all option contract caches for a security.
+ */
+ Map getAllOptionsContractData(String tickerSymbol);
- Double getSecuritySupplementalDatum(String tickerSymbol, String key);
+ /**
+ * Get the latest trade for a security.
+ */
+ intrinio.realtime.equities.Trade getLatestEquityTrade(String tickerSymbol);
- boolean setSecuritySupplementalDatum(String tickerSymbol, String key, double datum);
+ /**
+ * Set the latest trade for a security.
+ */
+ boolean setEquityTrade(intrinio.realtime.equities.Trade trade);
- Double getOptionsContractSupplementalDatum(String tickerSymbol, String contract, String key);
+ /**
+ * Get the latest ask quote for a security.
+ */
+ intrinio.realtime.equities.Quote getLatestEquityAskQuote(String tickerSymbol);
- boolean setOptionSupplementalDatum(String tickerSymbol, String contract, String key, double datum);
+ /**
+ * Set the latest bid quote for a security.
+ */
+ intrinio.realtime.equities.Quote getLatestEquityBidQuote(String tickerSymbol);
- void setOnSupplementalDatumUpdated(OnSupplementalDatumUpdated onSupplementalDatumUpdated);
+ /**
+ * Set the latest quote for a security.
+ */
+ boolean setEquityQuote(intrinio.realtime.equities.Quote quote);
- void setOnSecuritySupplementalDatumUpdated(OnSecuritySupplementalDatumUpdated onSecuritySupplementalDatumUpdated);
+ /**
+ * Get the latest option contract trade.
+ */
+ intrinio.realtime.options.Trade getLatestOptionsTrade(String tickerSymbol, String contract);
- void setOnOptionSupplementalDatumUpdated(OnOptionsContractSupplementalDatumUpdated onOptionsContractSupplementalDatumUpdated);
+ /**
+ * Set the latest option contract trade.
+ */
+ boolean setOptionsTrade(intrinio.realtime.options.Trade trade);
- void setOnEquitiesQuoteUpdated(OnEquitiesQuoteUpdated onEquitiesQuoteUpdated);
+ /**
+ * Get the latest option contract quote.
+ */
+ intrinio.realtime.options.Quote getLatestOptionsQuote(String tickerSymbol, String contract);
- void setOnEquitiesTradeUpdated(OnEquitiesTradeUpdated onEquitiesTradeUpdated);
+ /**
+ * Set the latest option contract quote.
+ */
+ boolean setOptionsQuote(intrinio.realtime.options.Quote quote);
- void setOnOptionsQuoteUpdated(OnOptionsQuoteUpdated onOptionsQuoteUpdated);
+ /**
+ * Get the latest option contract refresh.
+ */
+ intrinio.realtime.options.Refresh getLatestOptionsRefresh(String tickerSymbol, String contract);
- void setOnOptionsTradeUpdated(OnOptionsTradeUpdated onOptionsTradeUpdated);
+ /**
+ * Set the latest option contract refresh.
+ */
+ boolean setOptionsRefresh(intrinio.realtime.options.Refresh refresh);
- void setOnOptionsRefreshUpdated(OnOptionsRefreshUpdated onOptionsRefreshUpdated);
-}
+ /**
+ * Get the latest option contract unusual activity.
+ */
+ intrinio.realtime.options.UnusualActivity getLatestOptionsUnusualActivity(String tickerSymbol, String contract);
+
+ /**
+ * Set the latest option contract unusual activity.
+ */
+ boolean setOptionsUnusualActivity(intrinio.realtime.options.UnusualActivity unusualActivity);
+
+ /**
+ * Set the callback when the top level supplemental data is updated.
+ */
+ OnSupplementalDatumUpdated getSupplementalDatumUpdatedCallback();
+ void setSupplementalDatumUpdatedCallback(OnSupplementalDatumUpdated callback);
+
+ /**
+ * Set the callback when a security's supplemental data is updated.
+ */
+ OnSecuritySupplementalDatumUpdated getSecuritySupplementalDatumUpdatedCallback();
+ void setSecuritySupplementalDatumUpdatedCallback(OnSecuritySupplementalDatumUpdated callback);
+
+ /**
+ * Set the callback when an option contract's supplemental data is updated.
+ */
+ OnOptionsContractSupplementalDatumUpdated getOptionsContractSupplementalDatumUpdatedCallback();
+ void setOptionsContractSupplementalDatumUpdatedCallback(OnOptionsContractSupplementalDatumUpdated callback);
+
+ /**
+ * Set the callback for when the latest equity trade is updated.
+ */
+ OnEquitiesTradeUpdated getEquitiesTradeUpdatedCallback();
+ void setEquitiesTradeUpdatedCallback(OnEquitiesTradeUpdated callback);
+
+ /**
+ * Set the callback for when the latest equity quote is updated.
+ */
+ OnEquitiesQuoteUpdated getEquitiesQuoteUpdatedCallback();
+ void setEquitiesQuoteUpdatedCallback(OnEquitiesQuoteUpdated callback);
+
+ /**
+ * Set the callback for when the latest option trade is updated.
+ */
+ OnOptionsTradeUpdated getOptionsTradeUpdatedCallback();
+ void setOptionsTradeUpdatedCallback(OnOptionsTradeUpdated callback);
+
+ /**
+ * Set the callback for when the latest option quote is updated.
+ */
+ OnOptionsQuoteUpdated getOptionsQuoteUpdatedCallback();
+ void setOptionsQuoteUpdatedCallback(OnOptionsQuoteUpdated callback);
+
+ /**
+ * Set the callback for when the latest option refresh is updated.
+ */
+ OnOptionsRefreshUpdated getOptionsRefreshUpdatedCallback();
+ void setOptionsRefreshUpdatedCallback(OnOptionsRefreshUpdated callback);
+
+ /**
+ * Set the callback for when the latest option unusual activity is updated.
+ */
+ OnOptionsUnusualActivityUpdated getOptionsUnusualActivityUpdatedCallback();
+ void setOptionsUnusualActivityUpdatedCallback(OnOptionsUnusualActivityUpdated callback);
+
+ OnOptionsContractGreekDataUpdated getOptionsContractGreekDataUpdatedCallback();
+ void setOptionsContractGreekDataUpdatedCallback(OnOptionsContractGreekDataUpdated callback);
+}
\ No newline at end of file
diff --git a/src/intrinio/realtime/composite/DataCacheFactory.java b/src/intrinio/realtime/composite/DataCacheFactory.java
new file mode 100644
index 0000000..39b9d51
--- /dev/null
+++ b/src/intrinio/realtime/composite/DataCacheFactory.java
@@ -0,0 +1,7 @@
+package intrinio.realtime.composite;
+
+public class DataCacheFactory {
+ public static DataCache create() {
+ return new CurrentDataCache();
+ }
+}
\ No newline at end of file
diff --git a/src/intrinio/realtime/composite/Greek.java b/src/intrinio/realtime/composite/Greek.java
new file mode 100644
index 0000000..a7f3dc0
--- /dev/null
+++ b/src/intrinio/realtime/composite/Greek.java
@@ -0,0 +1,3 @@
+package intrinio.realtime.composite;
+
+public record Greek (double ImpliedVolatility, double Delta, double Gamma, double Theta, double Vega, boolean IsValid){}
\ No newline at end of file
diff --git a/src/intrinio/realtime/composite/GreekDataUpdate.java b/src/intrinio/realtime/composite/GreekDataUpdate.java
new file mode 100644
index 0000000..14c8b77
--- /dev/null
+++ b/src/intrinio/realtime/composite/GreekDataUpdate.java
@@ -0,0 +1,9 @@
+package intrinio.realtime.composite;
+
+/**
+ * The function used to update the Greek value in the cache.
+ */
+@FunctionalInterface
+public interface GreekDataUpdate {
+ Greek greekDataUpdate(String key, Greek oldValue, Greek newValue);
+}
diff --git a/src/intrinio/realtime/composite/GreekUpdateFrequency.java b/src/intrinio/realtime/composite/GreekUpdateFrequency.java
new file mode 100644
index 0000000..fd55075
--- /dev/null
+++ b/src/intrinio/realtime/composite/GreekUpdateFrequency.java
@@ -0,0 +1,40 @@
+package intrinio.realtime.composite;
+
+import java.util.EnumSet;
+
+public enum GreekUpdateFrequency {
+ EVERY_OPTIONS_TRADE_UPDATE(1),
+ EVERY_OPTIONS_QUOTE_UPDATE(2),
+ EVERY_RISK_FREE_INTEREST_RATE_UPDATE(4),
+ EVERY_DIVIDEND_YIELD_UPDATE(8),
+ EVERY_EQUITY_TRADE_UPDATE(16),
+ EVERY_EQUITY_QUOTE_UPDATE(32);
+
+ private final int value;
+
+ GreekUpdateFrequency(int value) {
+ this.value = value;
+ }
+
+ public int getValue() {
+ return value;
+ }
+
+ public static int combine(EnumSet set) {
+ int combined = 0;
+ for (GreekUpdateFrequency freq : set) {
+ combined |= freq.getValue();
+ }
+ return combined;
+ }
+
+ public static EnumSet fromValue(int value) {
+ EnumSet set = EnumSet.noneOf(GreekUpdateFrequency.class);
+ for (GreekUpdateFrequency freq : values()) {
+ if ((value & freq.getValue()) != 0) {
+ set.add(freq);
+ }
+ }
+ return set;
+ }
+}
\ No newline at end of file
diff --git a/src/intrinio/realtime/composite/OnEquitiesQuoteUpdated.java b/src/intrinio/realtime/composite/OnEquitiesQuoteUpdated.java
index be1676f..8f3e83c 100644
--- a/src/intrinio/realtime/composite/OnEquitiesQuoteUpdated.java
+++ b/src/intrinio/realtime/composite/OnEquitiesQuoteUpdated.java
@@ -1,5 +1,6 @@
package intrinio.realtime.composite;
+@FunctionalInterface
public interface OnEquitiesQuoteUpdated {
- void onEquitiesQuoteUpdated(SecurityData SecurityData, DataCache DataCache);
+ void onEquitiesQuoteUpdated(SecurityData securityData, DataCache dataCache, intrinio.realtime.equities.Quote quote);
}
diff --git a/src/intrinio/realtime/composite/OnEquitiesTradeUpdated.java b/src/intrinio/realtime/composite/OnEquitiesTradeUpdated.java
index d595bfe..8b3ac13 100644
--- a/src/intrinio/realtime/composite/OnEquitiesTradeUpdated.java
+++ b/src/intrinio/realtime/composite/OnEquitiesTradeUpdated.java
@@ -1,5 +1,6 @@
package intrinio.realtime.composite;
+@FunctionalInterface
public interface OnEquitiesTradeUpdated {
- void onEquitiesTradeUpdated(SecurityData securityData, DataCache dataCache);
+ void onEquitiesTradeUpdated(SecurityData securityData, DataCache dataCache, intrinio.realtime.equities.Trade trade);
}
diff --git a/src/intrinio/realtime/composite/OnOptionsContractGreekDataUpdated.java b/src/intrinio/realtime/composite/OnOptionsContractGreekDataUpdated.java
new file mode 100644
index 0000000..1090bb1
--- /dev/null
+++ b/src/intrinio/realtime/composite/OnOptionsContractGreekDataUpdated.java
@@ -0,0 +1,6 @@
+package intrinio.realtime.composite;
+
+@FunctionalInterface
+public interface OnOptionsContractGreekDataUpdated {
+ void onOptionsContractGreekDataUpdated(String key, Greek datum, OptionsContractData optionsContractData, SecurityData securityData, DataCache dataCache);
+}
diff --git a/src/intrinio/realtime/composite/OnOptionsContractSupplementalDatumUpdated.java b/src/intrinio/realtime/composite/OnOptionsContractSupplementalDatumUpdated.java
index f750f5d..706c890 100644
--- a/src/intrinio/realtime/composite/OnOptionsContractSupplementalDatumUpdated.java
+++ b/src/intrinio/realtime/composite/OnOptionsContractSupplementalDatumUpdated.java
@@ -1,5 +1,6 @@
package intrinio.realtime.composite;
+@FunctionalInterface
public interface OnOptionsContractSupplementalDatumUpdated {
- void onOptionsContractSupplementalDatumUpdated(String key, double datum, OptionsContractData optionsContractData, SecurityData securityData, DataCache dataCache);
+ void onOptionsContractSupplementalDatumUpdated(String key, Double datum, OptionsContractData optionsContractData, SecurityData securityData, DataCache dataCache);
}
diff --git a/src/intrinio/realtime/composite/OnOptionsQuoteUpdated.java b/src/intrinio/realtime/composite/OnOptionsQuoteUpdated.java
index 3e9f192..9879778 100644
--- a/src/intrinio/realtime/composite/OnOptionsQuoteUpdated.java
+++ b/src/intrinio/realtime/composite/OnOptionsQuoteUpdated.java
@@ -1,5 +1,6 @@
package intrinio.realtime.composite;
+@FunctionalInterface
public interface OnOptionsQuoteUpdated {
- void onOptionsQuoteUpdated(OptionsContractData optionsContractData, DataCache dataCache, SecurityData securityData);
+ void onOptionsQuoteUpdated(OptionsContractData optionsContractData, DataCache dataCache, SecurityData securityData, intrinio.realtime.options.Quote quote);
}
diff --git a/src/intrinio/realtime/composite/OnOptionsRefreshUpdated.java b/src/intrinio/realtime/composite/OnOptionsRefreshUpdated.java
index f51a36c..59ea966 100644
--- a/src/intrinio/realtime/composite/OnOptionsRefreshUpdated.java
+++ b/src/intrinio/realtime/composite/OnOptionsRefreshUpdated.java
@@ -1,5 +1,6 @@
package intrinio.realtime.composite;
+@FunctionalInterface
public interface OnOptionsRefreshUpdated {
- void onOptionsRefreshUpdated(OptionsContractData optionsContractData, DataCache dataCache, SecurityData securityData);
+ void onOptionsRefreshUpdated(OptionsContractData optionsContractData, DataCache dataCache, SecurityData securityData, intrinio.realtime.options.Refresh refresh);
}
diff --git a/src/intrinio/realtime/composite/OnOptionsTradeUpdated.java b/src/intrinio/realtime/composite/OnOptionsTradeUpdated.java
index ebca6f4..1d80a89 100644
--- a/src/intrinio/realtime/composite/OnOptionsTradeUpdated.java
+++ b/src/intrinio/realtime/composite/OnOptionsTradeUpdated.java
@@ -1,5 +1,6 @@
package intrinio.realtime.composite;
+@FunctionalInterface
public interface OnOptionsTradeUpdated {
- void onOptionsTradeUpdated(OptionsContractData optionsContractData, DataCache dataCache, SecurityData securityData);
+ void onOptionsTradeUpdated(OptionsContractData optionsContractData, DataCache dataCache, SecurityData securityData, intrinio.realtime.options.Trade trade);
}
diff --git a/src/intrinio/realtime/composite/OnOptionsUnusualActivityUpdated.java b/src/intrinio/realtime/composite/OnOptionsUnusualActivityUpdated.java
new file mode 100644
index 0000000..1ee3f60
--- /dev/null
+++ b/src/intrinio/realtime/composite/OnOptionsUnusualActivityUpdated.java
@@ -0,0 +1,6 @@
+package intrinio.realtime.composite;
+
+@FunctionalInterface
+public interface OnOptionsUnusualActivityUpdated {
+ void onOptionsUnusualActivityUpdated(OptionsContractData optionsContractData, DataCache dataCache, SecurityData securityData, intrinio.realtime.options.UnusualActivity unusualActivity);
+}
diff --git a/src/intrinio/realtime/composite/OnSecuritySupplementalDatumUpdated.java b/src/intrinio/realtime/composite/OnSecuritySupplementalDatumUpdated.java
index 1101811..b7b569b 100644
--- a/src/intrinio/realtime/composite/OnSecuritySupplementalDatumUpdated.java
+++ b/src/intrinio/realtime/composite/OnSecuritySupplementalDatumUpdated.java
@@ -1,5 +1,6 @@
package intrinio.realtime.composite;
+@FunctionalInterface
public interface OnSecuritySupplementalDatumUpdated {
- void onSecuritySupplementalDatumUpdated(String key, double datum, SecurityData securityData, DataCache dataCache);
+ void onSecuritySupplementalDatumUpdated(String key, Double datum, SecurityData securityData, DataCache dataCache);
}
diff --git a/src/intrinio/realtime/composite/OnSupplementalDatumUpdated.java b/src/intrinio/realtime/composite/OnSupplementalDatumUpdated.java
index d0c0bc0..e956371 100644
--- a/src/intrinio/realtime/composite/OnSupplementalDatumUpdated.java
+++ b/src/intrinio/realtime/composite/OnSupplementalDatumUpdated.java
@@ -1,5 +1,6 @@
package intrinio.realtime.composite;
+@FunctionalInterface
public interface OnSupplementalDatumUpdated {
- void onSupplementalDatumUpdated(String key, double datum, DataCache dataCache);
+ void onSupplementalDatumUpdated(String key, Double datum, DataCache dataCache);
}
diff --git a/src/intrinio/realtime/composite/OptionsContractData.java b/src/intrinio/realtime/composite/OptionsContractData.java
index 10009f5..628260e 100644
--- a/src/intrinio/realtime/composite/OptionsContractData.java
+++ b/src/intrinio/realtime/composite/OptionsContractData.java
@@ -1,26 +1,39 @@
package intrinio.realtime.composite;
+import intrinio.realtime.options.Trade;
+import intrinio.realtime.options.Quote;
+import intrinio.realtime.options.Refresh;
+import intrinio.realtime.options.UnusualActivity;
+import intrinio.realtime.options.QuoteType;
import java.util.Map;
+/**
+ * Not for Use yet. Subject to change.
+ */
public interface OptionsContractData {
-
String getContract();
- intrinio.realtime.options.Trade getTrade();
-
- intrinio.realtime.options.Quote getQuote();
-
- intrinio.realtime.options.Refresh getRefresh();
-
- boolean setTrade(intrinio.realtime.options.Trade trade);
+ Trade getLatestTrade();
+ Quote getLatestQuote();
+ Refresh getLatestRefresh();
+ UnusualActivity getLatestUnusualActivity();
- boolean setQuote(intrinio.realtime.options.Quote quote);
-
- boolean setRefresh(intrinio.realtime.options.Refresh refresh);
+ boolean setTrade(Trade trade);
+ boolean setTrade(Trade trade, OnOptionsTradeUpdated onOptionsTradeUpdated, SecurityData securityData, DataCache dataCache);
+ boolean setQuote(Quote quote);
+ boolean setQuote(Quote quote, OnOptionsQuoteUpdated onOptionsQuoteUpdated, SecurityData securityData, DataCache dataCache);
+ boolean setRefresh(Refresh refresh);
+ boolean setRefresh(Refresh refresh, OnOptionsRefreshUpdated onOptionsRefreshUpdated, SecurityData securityData, DataCache dataCache);
+ boolean setUnusualActivity(UnusualActivity unusualActivity);
+ boolean setUnusualActivity(UnusualActivity unusualActivity, OnOptionsUnusualActivityUpdated onOptionsUnusualActivityUpdated, SecurityData securityData, DataCache dataCache);
Double getSupplementaryDatum(String key);
-
- boolean setSupplementaryDatum(String key, double datum);
-
+ boolean setSupplementaryDatum(String key, Double datum, SupplementalDatumUpdate update);
+ boolean setSupplementaryDatum(String key, Double datum, OnOptionsContractSupplementalDatumUpdated onOptionsContractSupplementalDatumUpdated, SecurityData securityData, DataCache dataCache, SupplementalDatumUpdate update);
Map getAllSupplementaryData();
-}
+
+ Greek getGreekData(String key);
+ boolean setGreekData(String key, Greek datum, GreekDataUpdate update);
+ boolean setGreekData(String key, Greek datum, OnOptionsContractGreekDataUpdated onOptionsContractGreekDataUpdated, SecurityData securityData, DataCache dataCache, GreekDataUpdate update);
+ Map getAllGreekData();
+}
\ No newline at end of file
diff --git a/src/intrinio/realtime/composite/SecurityData.java b/src/intrinio/realtime/composite/SecurityData.java
index 3490f44..a25e83b 100644
--- a/src/intrinio/realtime/composite/SecurityData.java
+++ b/src/intrinio/realtime/composite/SecurityData.java
@@ -1,45 +1,64 @@
package intrinio.realtime.composite;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
public interface SecurityData {
-
String getTickerSymbol();
+ intrinio.realtime.equities.Trade getLatestEquitiesTrade();
+ intrinio.realtime.equities.Quote getLatestEquitiesAskQuote();
+ intrinio.realtime.equities.Quote getLatestEquitiesBidQuote();
+
Double getSupplementaryDatum(String key);
- boolean setSupplementaryDatum(String key, double datum);
+ boolean setSupplementaryDatum(String key, Double datum, SupplementalDatumUpdate update);
+ boolean setSupplementaryDatum(String key, Double datum, OnSecuritySupplementalDatumUpdated onSecuritySupplementalDatumUpdated, DataCache dataCache, SupplementalDatumUpdate update);
Map getAllSupplementaryData();
- intrinio.realtime.equities.Trade getEquitiesTrade();
+ boolean setEquitiesTrade(intrinio.realtime.equities.Trade trade);
+ boolean setEquitiesTrade(intrinio.realtime.equities.Trade trade, OnEquitiesTradeUpdated onEquitiesTradeUpdated, DataCache dataCache);
- intrinio.realtime.equities.Quote getEquitiesQuote();
+ boolean setEquitiesQuote(intrinio.realtime.equities.Quote quote);
+ boolean setEquitiesQuote(intrinio.realtime.equities.Quote quote, OnEquitiesQuoteUpdated onEquitiesQuoteUpdated, DataCache dataCache);
OptionsContractData getOptionsContractData(String contract);
Map getAllOptionsContractData();
- List getContractNames(String ticker);
-
- boolean setEquitiesTrade(intrinio.realtime.equities.Trade trade);
-
- boolean setEquitiesQuote(intrinio.realtime.equities.Quote quote);
+ List getContractNames();
intrinio.realtime.options.Trade getOptionsContractTrade(String contract);
boolean setOptionsContractTrade(intrinio.realtime.options.Trade trade);
+ boolean setOptionsContractTrade(intrinio.realtime.options.Trade trade, OnOptionsTradeUpdated onOptionsTradeUpdated, DataCache dataCache);
intrinio.realtime.options.Quote getOptionsContractQuote(String contract);
boolean setOptionsContractQuote(intrinio.realtime.options.Quote quote);
+ boolean setOptionsContractQuote(intrinio.realtime.options.Quote quote, OnOptionsQuoteUpdated onOptionsQuoteUpdated, DataCache dataCache);
intrinio.realtime.options.Refresh getOptionsContractRefresh(String contract);
boolean setOptionsContractRefresh(intrinio.realtime.options.Refresh refresh);
+ boolean setOptionsContractRefresh(intrinio.realtime.options.Refresh refresh, OnOptionsRefreshUpdated onOptionsRefreshUpdated, DataCache dataCache);
+
+ intrinio.realtime.options.UnusualActivity getOptionsContractUnusualActivity(String contract);
+
+ boolean setOptionsContractUnusualActivity(intrinio.realtime.options.UnusualActivity unusualActivity);
+ boolean setOptionsContractUnusualActivity(intrinio.realtime.options.UnusualActivity unusualActivity, OnOptionsUnusualActivityUpdated onOptionsUnusualActivityUpdated, DataCache dataCache);
Double getOptionsContractSupplementalDatum(String contract, String key);
- boolean setOptionsContractSupplementalDatum(String contract, String key, double datum);
-}
+ boolean setOptionsContractSupplementalDatum(String contract, String key, Double datum, SupplementalDatumUpdate update);
+ boolean setOptionsContractSupplementalDatum(String contract, String key, Double datum, OnOptionsContractSupplementalDatumUpdated onOptionsContractSupplementalDatumUpdated, DataCache dataCache, SupplementalDatumUpdate update);
+
+ Greek getOptionsContractGreekData(String contract, String key);
+
+ boolean setOptionsContractGreekData(String contract, String key, Greek data, GreekDataUpdate update);
+ boolean setOptionsContractGreekData(String contract, String key, Greek data, OnOptionsContractGreekDataUpdated onOptionsContractGreekDataUpdated, DataCache dataCache, GreekDataUpdate update);
+}
\ No newline at end of file
diff --git a/src/intrinio/realtime/composite/SupplementalDatumUpdate.java b/src/intrinio/realtime/composite/SupplementalDatumUpdate.java
new file mode 100644
index 0000000..e17647a
--- /dev/null
+++ b/src/intrinio/realtime/composite/SupplementalDatumUpdate.java
@@ -0,0 +1,9 @@
+package intrinio.realtime.composite;
+
+/**
+ * The function used to update the Supplemental value in the cache.
+ */
+@FunctionalInterface
+public interface SupplementalDatumUpdate {
+ Double supplementalDatumUpdate(String key, Double oldValue, Double newValue);
+}
diff --git a/src/intrinio/realtime/equities/Client.java b/src/intrinio/realtime/equities/Client.java
index 4f76276..127152b 100644
--- a/src/intrinio/realtime/equities/Client.java
+++ b/src/intrinio/realtime/equities/Client.java
@@ -52,7 +52,7 @@ public class Client implements WebSocket.Listener {
private Thread[] processDataThreads;
private boolean isCancellationRequested = false;
private String HeaderClientInformationKey = "Client-Information";
- private String HeaderClientInformationValue = "IntrinioRealtimeJavaSDKv7.2";
+ private String HeaderClientInformationValue = "IntrinioRealtimeJavaSDKv8.0";
private String HeaderMessageVersionKey = "UseNewEquitiesFormat";
private String HeaderMessageVersionValue = "v2";
//endregion Data Members
@@ -127,6 +127,8 @@ private String getAuthUrl() throws Exception {
break;
case CBOE_ONE: authUrl = "https://cboe-one.intrinio.com/auth?api_key=" + config.getEquitiesApiKey();
break;
+ case EQUITIES_EDGE: authUrl = "https://equities-edge.intrinio.com/auth?api_key=" + config.getEquitiesApiKey();
+ break;
case MANUAL: authUrl = "http://" + config.getEquitiesIpAddress() + "/auth?api_key=" + config.getEquitiesApiKey();
break;
default: throw new Exception("Provider not specified!");
@@ -148,6 +150,8 @@ private String getWebSocketUrl (String token) throws Exception {
break;
case CBOE_ONE: wsUrl = "wss://cboe-one.intrinio.com/socket/websocket?vsn=1.0.0&token=" + token + delayedPart;
break;
+ case EQUITIES_EDGE: wsUrl = "wss://equities-edge.intrinio.com/socket/websocket?vsn=1.0.0&token=" + token + delayedPart;
+ break;
case MANUAL: wsUrl = "ws://" + config.getEquitiesIpAddress() + "/socket/websocket?vsn=1.0.0&token=" + token + delayedPart;
break;
default: throw new Exception("Provider not specified!");
diff --git a/src/intrinio/realtime/equities/Provider.java b/src/intrinio/realtime/equities/Provider.java
index a9a14d7..8905b20 100644
--- a/src/intrinio/realtime/equities/Provider.java
+++ b/src/intrinio/realtime/equities/Provider.java
@@ -7,5 +7,6 @@ public enum Provider {
DELAYED_SIP,
NASDAQ_BASIC,
CBOE_ONE,
- IEX
+ IEX,
+ EQUITIES_EDGE
}
diff --git a/src/intrinio/realtime/equities/SubProvider.java b/src/intrinio/realtime/equities/SubProvider.java
index 8f5253e..34235b8 100644
--- a/src/intrinio/realtime/equities/SubProvider.java
+++ b/src/intrinio/realtime/equities/SubProvider.java
@@ -8,5 +8,6 @@ public enum SubProvider {
OTC,
NASDAQ_BASIC,
IEX,
- CBOE_ONE
+ CBOE_ONE,
+ EQUITIES_EDGE
}
diff --git a/src/intrinio/realtime/options/Client.java b/src/intrinio/realtime/options/Client.java
index 1db7980..027b208 100644
--- a/src/intrinio/realtime/options/Client.java
+++ b/src/intrinio/realtime/options/Client.java
@@ -35,7 +35,7 @@ public class Client implements WebSocket.Listener {
private final Lock dataBucketLock = new ReentrantLock();
private final LinkedBlockingDeque> dataBucket = new LinkedBlockingDeque>();
private final WebSocketState wsState = new WebSocketState();
- private final String Version = "IntrinioRealtimeOptionsJavaSDKv7.2";
+ private final String Version = "IntrinioRealtimeOptionsJavaSDKv8.0";
//endregion Final data members
//region Data Members
@@ -124,6 +124,8 @@ private String getAuthUrl() throws Exception {
switch (config.getOptionsProvider()) {
case OPRA: authUrl = "https://realtime-options.intrinio.com/auth?api_key=" + config.getOptionsApiKey();
break;
+ case OPTIONS_EDGE: authUrl = "https://options-edge.intrinio.com/auth?api_key=" + config.getOptionsApiKey();
+ break;
case MANUAL: authUrl = "http://" + config.getOptionsIpAddress() + "/auth?api_key=" + config.getOptionsApiKey();
break;
default: throw new Exception("Provider not specified!");
@@ -136,6 +138,8 @@ private String getWebSocketUrl (String token) throws Exception {
switch (config.getOptionsProvider()) {
case OPRA: wsUrl = "wss://realtime-options.intrinio.com/socket/websocket?vsn=1.0.0&token=" + token + (this.config.isDelayed() ? "&delayed=true" : "");
break;
+ case OPTIONS_EDGE: wsUrl = "wss://options-edge.intrinio.com/socket/websocket?vsn=1.0.0&token=" + token + (this.config.isDelayed() ? "&delayed=true" : "");
+ break;
case MANUAL: wsUrl = "ws://" + config.getOptionsIpAddress() + "/socket/websocket?vsn=1.0.0&token=" + token + (this.config.isDelayed() ? "&delayed=true" : "");
break;
default: throw new Exception("Provider not specified!");
diff --git a/src/intrinio/realtime/options/Provider.java b/src/intrinio/realtime/options/Provider.java
index 72b255f..beb8343 100644
--- a/src/intrinio/realtime/options/Provider.java
+++ b/src/intrinio/realtime/options/Provider.java
@@ -3,5 +3,6 @@
public enum Provider {
NONE,
OPRA,
+ OPTIONS_EDGE,
MANUAL
}
diff --git a/src/intrinio/realtime/options/QuoteType.java b/src/intrinio/realtime/options/QuoteType.java
new file mode 100644
index 0000000..1d38645
--- /dev/null
+++ b/src/intrinio/realtime/options/QuoteType.java
@@ -0,0 +1,7 @@
+package intrinio.realtime.options;
+
+public enum QuoteType
+{
+ Ask,
+ Bid
+}