com.ddfplus.service.definition.DefinitionServiceImpl Maven / Gradle / Ivy
package com.ddfplus.service.definition;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
public class DefinitionServiceImpl implements DefinitionService {
// Every 12 hours
private static final int DEFAULT_DEFINITION_REFRESH_INTERVAL_SEC = 60 * 60 * 12;
private static final int NEAREST_MONTH = 0;
private static final String BASE_URL = "http://extras.ddfplus.com/json/";
private static final String FUTURES_URL = BASE_URL + "/futures/?root=";
private static final String OPTIONS_URL = BASE_URL + "/options/?root=";
private static final Logger logger = LoggerFactory.getLogger("DefinitionService");
private final Map futureRoots = new ConcurrentHashMap();
private final Map optionsRoots = new ConcurrentHashMap();
private final Gson gson;
private OkHttpClient httpClient;
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
private long refreshIntervalSec = DEFAULT_DEFINITION_REFRESH_INTERVAL_SEC;
public DefinitionServiceImpl() {
httpClient = new OkHttpClient();
httpClient.setConnectTimeout(3, TimeUnit.SECONDS);
httpClient.setReadTimeout(20, TimeUnit.SECONDS);
gson = new GsonBuilder().create();
}
@Override
public void init(Long intervalSec) {
if (intervalSec != null) {
this.refreshIntervalSec = intervalSec;
}
/*
* Start a refresh thread
*/
logger.info("Scheduling a symbol refresh every " + refreshIntervalSec + " seconds.");
RefreshThread refreshThread = new RefreshThread();
scheduler.scheduleAtFixedRate(refreshThread, refreshIntervalSec, refreshIntervalSec, TimeUnit.SECONDS);
}
@Override
public String[] getAllFutureSymbols(String root) {
String[] futures = new String[0];
// Look up in cache first
FuturesRoot futureRoot = futureRoots.get(root);
if (futureRoot == null) {
futureRoot = buildFutureContractCache(root);
}
if (futureRoot != null) {
futures = futureRoot.getContractSymbols();
}
return futures;
}
@Override
public String getFuturesMonthSymbol(String root, int month) {
String ret = null;
// Look up in cache first
FuturesRoot futureRoot = futureRoots.get(root);
if (futureRoot == null) {
futureRoot = buildFutureContractCache(root);
}
if (futureRoot != null) {
if (month == NEAREST_MONTH) {
// nearest month
return futureRoot.getNearestContract().getSymbol();
}
return futureRoot.getSymbolByMonth(month);
}
return ret;
}
@Override
public String[] getAllOptionsSymbols(String root) {
String[] options = new String[0];
OptionsRoot optionsRoot = optionsRoots.get(root);
if (optionsRoot == null) {
optionsRoot = buildOptionsContractCache(root);
}
if (optionsRoot != null) {
options = optionsRoot.getAllStrikeSymbols();
}
return options;
}
@Override
public String[] getAllOptionsMonthYearSymbols(String root, String monthYear) {
String[] options = new String[0];
OptionsRoot optionsRoot = optionsRoots.get(root);
if (optionsRoot == null) {
optionsRoot = buildOptionsContractCache(root);
}
if (optionsRoot != null) {
options = optionsRoot.getMonthYearStrikeSymbols(monthYear);
}
return options;
}
private FuturesRoot buildFutureContractCache(String root) {
FuturesRoot futureRoot = null;
// Look up from web service
Request request = new Request.Builder().url(FUTURES_URL + root).build();
Response response;
try {
response = httpClient.newCall(request).execute();
if (response.isSuccessful()) {
String json = response.body().string();
if (logger.isDebugEnabled()) {
logger.debug("< " + json);
}
futureRoot = processFutureRoot(json, root);
}
} catch (Exception e) {
logger.error("Could not obtain futures definitions for: " + root + " error: " + e.getMessage());
}
return futureRoot;
}
FuturesRoot processFutureRoot(String json, String root) {
FuturesRoot futureRoot = null;
// A map is returned, so need collection type
Type collectionType = new TypeToken