PageRenderTime 70ms CodeModel.GetById 35ms RepoModel.GetById 0ms app.codeStats 0ms

/src/main/java/com/portfolio/management/util/alphavantage/AlphavantageParserUtil.java

https://bitbucket.org/Allen035/404-not-found
Java | 607 lines | 420 code | 113 blank | 74 comment | 56 complexity | eb93fbee878fdd10e74ed2ccee904f39 MD5 | raw file
  1. package com.portfolio.management.util.alphavantage;
  2. import com.alibaba.fastjson.JSON;
  3. import com.alibaba.fastjson.JSONArray;
  4. import com.alibaba.fastjson.JSONObject;
  5. import com.portfolio.management.dao.StockDao;
  6. import com.portfolio.management.model.RealTimeStock;
  7. import org.apache.commons.lang.StringUtils;
  8. import org.apache.log4j.Logger;
  9. import org.springframework.beans.factory.annotation.Autowired;
  10. import org.springframework.stereotype.Service;
  11. import java.time.LocalDate;
  12. import java.time.LocalDateTime;
  13. import java.time.format.DateTimeFormatter;
  14. import java.time.format.DateTimeParseException;
  15. import java.util.ArrayList;
  16. import java.util.Collections;
  17. import java.util.Comparator;
  18. import java.util.List;
  19. import java.util.concurrent.ExecutorService;
  20. import java.util.concurrent.Executors;
  21. import java.util.concurrent.TimeUnit;
  22. @Service
  23. public class AlphavantageParserUtil {
  24. @Autowired StockDao stockDao;
  25. private static final Logger LOGGER = Logger.getLogger(AlphavantageParserUtil.class);
  26. private static final String API_KEY = "X8RO597ZV071YDUA";
  27. // deprecated: replace this with multithreading method getRealTimeStock
  28. public static List<StockQuote> getAll(String symbols){
  29. String result = AlphavantageUtil.getAll(symbols);
  30. List<StockQuote> stocks = new ArrayList<StockQuote>();
  31. JSONObject jsonObject = JSON.parseObject(result);
  32. if (StringUtils.isEmpty(result)){
  33. for(String sym:symbols.split(",")){
  34. StockQuote stockq = new StockQuote();
  35. stockq.setSymbol(sym);
  36. stocks.add(stockq);
  37. }
  38. return stocks;
  39. }else {
  40. JSONArray josnArray = jsonObject.getJSONArray("Stock Quotes");
  41. for(int i=0;i<josnArray.size();i++){
  42. JSONObject jsonobj = josnArray.getJSONObject(i);
  43. StockQuote stockq = new StockQuote();
  44. stockq.setSymbol(jsonobj.getString("1. symbol"));
  45. stockq.setPrice(jsonobj.getString("2. price"));
  46. stockq.setVolume(jsonobj.getString("3. volume"));
  47. stockq.setTime(jsonobj.getString("4. timestamp"));
  48. stocks.add(stockq);
  49. }
  50. return stocks;
  51. }
  52. }
  53. // turn positive number to green or red in stock market style
  54. public static String getStyledChange(Float change){
  55. if(change >= 0.0)
  56. return "<span style='color:green'>" + String.valueOf(Math.round(change *100.0)/100.0) + "</span>";
  57. return "<span style='color:red'>" + String.valueOf(Math.round(change *100.0)/100.0) + "</span>";
  58. }
  59. // populate RealTimeStock model
  60. public List<RealTimeStock> getRealTimeStock(List<String> symbols){
  61. ExecutorService executorService = Executors.newCachedThreadPool();
  62. List<RealTimeStock> realTimeStocks = new ArrayList<>();
  63. for(String symbol: symbols){
  64. executorService.execute(new Runnable() {
  65. @Override
  66. public void run() {
  67. LOGGER.info(Thread.currentThread().getName());
  68. List<TimeSeriesDailyAdjustedStock> stocks = AlphavantageParserUtil.parseTimeSeriesDailyAdjusted(symbol,"","",API_KEY);
  69. stocks.sort(Comparator.comparing(TimeSeriesDailyAdjustedStock::getTime));
  70. Collections.reverse(stocks);
  71. RealTimeStock realTimeStock = new RealTimeStock();
  72. TimeSeriesDailyAdjustedStock todayStock = stocks.get(0);
  73. Float todayPrice = Float.parseFloat(todayStock.getAdjustedClose());
  74. Float yesterdayPrice = Float.parseFloat((stocks.get(1).getAdjustedClose()));
  75. String company = stockDao.queryCompanyBySymbol(symbol);
  76. realTimeStock.setSymbol(todayStock.getSymbol());
  77. realTimeStock.setVolume(todayStock.getVolume());
  78. realTimeStock.setPrice(todayPrice);
  79. realTimeStock.setChange(todayPrice - yesterdayPrice);
  80. realTimeStock.setStyledChange(getStyledChange(todayPrice - yesterdayPrice));
  81. realTimeStock.setPercentageChange((todayPrice-yesterdayPrice)/yesterdayPrice*100);
  82. realTimeStock.setStyledPercentageChange(getStyledChange((todayPrice-yesterdayPrice)/yesterdayPrice*100));
  83. if(company!=null)
  84. realTimeStock.setCompany(company);
  85. else
  86. LOGGER.info(symbol);
  87. realTimeStocks.add(realTimeStock);
  88. }
  89. });
  90. }
  91. executorService.shutdown();
  92. try{
  93. if(!executorService.awaitTermination(10, TimeUnit.SECONDS)){
  94. executorService.shutdownNow();
  95. }
  96. }catch (InterruptedException e){
  97. executorService.shutdownNow();
  98. return realTimeStocks;
  99. }
  100. return realTimeStocks;
  101. }
  102. // parse RSI indicator
  103. public static String parseRSI(String symbol){
  104. String result = AlphavantageUtil.getRSI(symbol);
  105. if(StringUtils.isEmpty(result))
  106. return "";
  107. JSONObject timeSeries = JSON.parseObject(result)
  108. .getJSONObject("Technical Analysis: RSI");
  109. DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
  110. String today = formatter.format(LocalDate.now().minusDays(1));
  111. JSONObject jsonObject = timeSeries.getJSONObject(today);
  112. if(jsonObject == null){
  113. for (int i = 2; i < 7; i++) {
  114. String altDay = formatter.format(LocalDate.now().minusDays(i));
  115. jsonObject = timeSeries.getJSONObject(altDay);
  116. if(jsonObject != null)
  117. return jsonObject.getString("RSI");
  118. }
  119. }
  120. else return jsonObject.getString("RSI");
  121. return "";
  122. }
  123. /**
  124. * AlphavantageTimeSeries-Intraday
  125. *
  126. * @param symbol
  127. * @param interval
  128. * @param outputsize
  129. * @param datatype
  130. * @param apikey
  131. * @return
  132. */
  133. public static List<TimeSeriesIntradayStock> parseTimeSeriesIntraday(String symbol, int interval, String outputsize, String datatype, String apikey){
  134. String intervalStr = interval + "min";
  135. String result = AlphavantageUtil.getTimeSeriesIntraday(symbol, intervalStr, outputsize, datatype, apikey);
  136. List<TimeSeriesIntradayStock> stocks = new ArrayList<TimeSeriesIntradayStock>();
  137. JSONObject jsonObject = JSON.parseObject(result);
  138. if (StringUtils.isEmpty(result)){
  139. return stocks;
  140. }else {
  141. JSONObject metaData = jsonObject.getJSONObject("Meta Data");
  142. DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
  143. LocalDateTime lastRefreshed = LocalDateTime.parse(metaData.getString("3. Last Refreshed"),formatter);
  144. String key = String.format("Time Series (%s)", intervalStr);
  145. JSONObject timeSeries = jsonObject.getJSONObject(key);
  146. int size = timeSeries.size();
  147. for (int i = 0;i < size;i++){
  148. TimeSeriesIntradayStock stock = new TimeSeriesIntradayStock();
  149. stock.setInterval(intervalStr);
  150. stock.setSymbol(symbol);
  151. LocalDateTime time = lastRefreshed.minusMinutes(i * interval);
  152. stock.setTime(time);
  153. JSONObject row = timeSeries.getJSONObject(time.format(formatter));
  154. stock.setOpen(row.getString("1. open"));
  155. stock.setHigh(row.getString("2. high"));
  156. stock.setLow(row.getString("3. low"));
  157. stock.setClose(row.getString("4. close"));
  158. stock.setVolume(row.getString("5. volume"));
  159. stocks.add(stock);
  160. }
  161. return stocks;
  162. }
  163. }
  164. /**
  165. * AlphavantageTimeSeries-Daily
  166. *
  167. * @param symbol
  168. * @param outputsize
  169. * @param datatype
  170. * @param apikey
  171. * @return
  172. */
  173. public static List<TimeSeriesDailyStock> parseTimeSeriesDaily(String symbol,String outputsize,String datatype,String apikey){
  174. String result = AlphavantageUtil.getTimeSeriesDaily(symbol, outputsize, datatype, apikey);
  175. List<TimeSeriesDailyStock> stocks = new ArrayList<TimeSeriesDailyStock>();
  176. JSONObject jsonObject = JSON.parseObject(result);
  177. if (StringUtils.isEmpty(result)){
  178. return stocks;
  179. }else {
  180. JSONObject metaData = jsonObject.getJSONObject("Meta Data");
  181. DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
  182. LocalDate lastRefreshed = LocalDate.parse(metaData.getString("3. Last Refreshed"),formatter);
  183. String key = String.format("Time Series (%s)", "Daily");
  184. JSONObject timeSeries = jsonObject.getJSONObject(key);
  185. int size = timeSeries.size();
  186. for (int i = 0;i < size;i++){
  187. TimeSeriesDailyStock stock = new TimeSeriesDailyStock();
  188. stock.setSymbol(symbol);
  189. LocalDate time = lastRefreshed.minusDays(i);
  190. stock.setTime(time);
  191. JSONObject row = timeSeries.getJSONObject(time.format(formatter));
  192. if (row != null){
  193. stock.setOpen(row.getString("1. open"));
  194. stock.setHigh(row.getString("2. high"));
  195. stock.setLow(row.getString("3. low"));
  196. stock.setClose(row.getString("4. close"));
  197. stock.setVolume(row.getString("5. volume"));
  198. stocks.add(stock);
  199. }else {
  200. size++;
  201. }
  202. }
  203. return stocks;
  204. }
  205. }
  206. /**
  207. * AlphavantageTimeSeries-DailyAdjusted
  208. *
  209. * @param symbol
  210. * @param outputsize
  211. * @param datatype
  212. * @param apikey
  213. * @return
  214. */
  215. public static List<TimeSeriesDailyAdjustedStock> parseTimeSeriesDailyAdjusted(String symbol,String outputsize,String datatype,String apikey){
  216. String result = AlphavantageUtil.getTimeSeriesDailyAdjusted(symbol, outputsize, datatype, apikey);
  217. List<TimeSeriesDailyAdjustedStock> stocks = new ArrayList<TimeSeriesDailyAdjustedStock>();
  218. JSONObject jsonObject = JSON.parseObject(result);
  219. if (StringUtils.isEmpty(result)){
  220. return stocks;
  221. }else {
  222. JSONObject metaData = jsonObject.getJSONObject("Meta Data");
  223. DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
  224. LocalDate lastRefreshed = LocalDate.parse(metaData.getString("3. Last Refreshed"),formatter);
  225. String key = String.format("Time Series (%s)", "Daily");
  226. JSONObject timeSeries = jsonObject.getJSONObject(key);
  227. int size = timeSeries.size();
  228. for (int i = 0;i < size;i++){
  229. TimeSeriesDailyAdjustedStock stock = new TimeSeriesDailyAdjustedStock();
  230. stock.setSymbol(symbol);
  231. LocalDate time = lastRefreshed.minusDays(i);
  232. stock.setTime(time);
  233. JSONObject row = timeSeries.getJSONObject(time.format(formatter));
  234. if (row != null){
  235. stock.setOpen(row.getString("1. open"));
  236. stock.setHigh(row.getString("2. high"));
  237. stock.setLow(row.getString("3. low"));
  238. stock.setClose(row.getString("4. close"));
  239. stock.setAdjustedClose(row.getString("5. adjusted close"));
  240. stock.setVolume(row.getString("6. volume"));
  241. stock.setDividendAmount(row.getString("7. dividend amount"));
  242. stock.setSplitCoefficient(row.getString("8. split coefficient"));
  243. stocks.add(stock);
  244. }else {
  245. size++;
  246. }
  247. }
  248. return stocks;
  249. }
  250. }
  251. /**
  252. * AlphavantageTimeSeries-Weekly
  253. *
  254. * @param symbol
  255. * @param datatype
  256. * @param apikey
  257. * @return
  258. */
  259. public static List<TimeSeriesWeeklyStock> parseTimeSeriesWeekly(String symbol,String datatype,String apikey){
  260. String result = AlphavantageUtil.getTimeSeriesWeekly(symbol, datatype, apikey);
  261. List<TimeSeriesWeeklyStock> stocks = new ArrayList<TimeSeriesWeeklyStock>();
  262. JSONObject jsonObject = JSON.parseObject(result);
  263. if (StringUtils.isEmpty(result)){
  264. return stocks;
  265. }else {
  266. JSONObject metaData = jsonObject.getJSONObject("Meta Data");
  267. DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
  268. LocalDate lastRefreshed = LocalDate.parse(metaData.getString("3. Last Refreshed"),formatter);
  269. String key = "Weekly Time Series";
  270. JSONObject timeSeries = jsonObject.getJSONObject(key);
  271. int size = timeSeries.size();
  272. for (int i = 0;i < size;i++){
  273. TimeSeriesWeeklyStock stock = new TimeSeriesWeeklyStock();
  274. stock.setSymbol(symbol);
  275. LocalDate time = lastRefreshed.minusDays(i * 7);
  276. stock.setTime(time);
  277. JSONObject row = timeSeries.getJSONObject(time.format(formatter));
  278. if (row == null){
  279. for (int j = 1;j < 7;j++){
  280. LocalDate tmp = time.minusDays(j);
  281. JSONObject rowTmp = timeSeries.getJSONObject(tmp.format(formatter));
  282. if (rowTmp != null){
  283. row = rowTmp;
  284. break;
  285. }
  286. }
  287. }
  288. stock.setOpen(row.getString("1. open"));
  289. stock.setHigh(row.getString("2. high"));
  290. stock.setLow(row.getString("3. low"));
  291. stock.setClose(row.getString("4. close"));
  292. stock.setVolume(row.getString("5. volume"));
  293. stocks.add(stock);
  294. }
  295. return stocks;
  296. }
  297. }
  298. /**
  299. * AlphavantageTimeSeries-WeeklyAdjusted
  300. *
  301. * @param symbol
  302. * @param datatype
  303. * @param apikey
  304. * @return
  305. */
  306. public static List<TimeSeriesWeeklyAdjustedStock> parseTimeSeriesWeeklyAdjusted(String symbol,String datatype,String apikey){
  307. String result = AlphavantageUtil.getTimeSeriesWeeklyAdjusted(symbol, datatype, apikey);
  308. List<TimeSeriesWeeklyAdjustedStock> stocks = new ArrayList<TimeSeriesWeeklyAdjustedStock>();
  309. JSONObject jsonObject = JSON.parseObject(result);
  310. if (StringUtils.isEmpty(result)){
  311. return stocks;
  312. }else {
  313. JSONObject metaData = jsonObject.getJSONObject("Meta Data");
  314. LocalDate lastRefreshed;
  315. DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
  316. try {
  317. lastRefreshed = LocalDate.parse(metaData.getString("3. Last Refreshed"), formatter);
  318. } catch (DateTimeParseException e) {
  319. DateTimeFormatter tempFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
  320. lastRefreshed = LocalDate.parse(metaData.getString("3. Last Refreshed"), tempFormatter);
  321. }
  322. String key = "Weekly Adjusted Time Series";
  323. JSONObject timeSeries = jsonObject.getJSONObject(key);
  324. int size = timeSeries.size();
  325. for (int i = 0;i < size;i++){
  326. TimeSeriesWeeklyAdjustedStock stock = new TimeSeriesWeeklyAdjustedStock();
  327. stock.setSymbol(symbol);
  328. LocalDate time = lastRefreshed.minusDays(i * 7);
  329. stock.setTime(time);
  330. JSONObject row = timeSeries.getJSONObject(time.format(formatter));
  331. if (row == null){
  332. for (int j = 1;j < 7;j++){
  333. LocalDate tmp = time.minusDays(j);
  334. JSONObject rowTmp = timeSeries.getJSONObject(tmp.format(formatter));
  335. if (rowTmp != null){
  336. row = rowTmp;
  337. break;
  338. }
  339. }
  340. }
  341. try {
  342. if (row != null) {
  343. stock.setOpen(row.getString("1. open"));
  344. stock.setHigh(row.getString("2. high"));
  345. stock.setLow(row.getString("3. low"));
  346. stock.setClose(row.getString("4. close"));
  347. stock.setAdjustedClose(row.getString("5. adjusted close"));
  348. stock.setVolume(row.getString("6. volume"));
  349. stock.setDividendAmount(row.getString("7. dividend amount"));
  350. stocks.add(stock);
  351. }
  352. } catch (NullPointerException e) {
  353. // LOGGER.info(e.getMessage());
  354. // LOGGER.info(stock.toString());
  355. }
  356. }
  357. return stocks;
  358. }
  359. }
  360. /**
  361. * AlphavantageTimeSeries-Monthly
  362. *
  363. * @param symbol
  364. * @param datatype
  365. * @param apikey
  366. * @return
  367. */
  368. public static List<TimeSeriesMonthlyStock> parseTimeSeriesMonthly(String symbol,String datatype,String apikey){
  369. String result = AlphavantageUtil.getTimeSeriesMonthly(symbol, datatype, apikey);
  370. List<TimeSeriesMonthlyStock> stocks = new ArrayList<TimeSeriesMonthlyStock>();
  371. JSONObject jsonObject = JSON.parseObject(result);
  372. LOGGER.info(jsonObject);
  373. if (StringUtils.isEmpty(result)){
  374. return stocks;
  375. }else {
  376. JSONObject metaData = jsonObject.getJSONObject("Meta Data");
  377. DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
  378. LocalDate lastRefreshed = LocalDate.parse(metaData.getString("3. Last Refreshed"),formatter);
  379. String key = "Monthly Time Series";
  380. JSONObject timeSeries = jsonObject.getJSONObject(key);
  381. LOGGER.info(timeSeries);
  382. int size = timeSeries.size();
  383. for (int i = 0;i < size;i++){
  384. TimeSeriesMonthlyStock stock = new TimeSeriesMonthlyStock();
  385. stock.setSymbol(symbol);
  386. LocalDate time = lastRefreshed.withDayOfMonth(1).minusMonths(i).minusDays(1);
  387. stock.setTime(time);
  388. JSONObject row = timeSeries.getJSONObject(time.format(formatter));
  389. if (row == null){
  390. int daysOfMonth = time.getDayOfMonth();
  391. for (int j = 1;j < daysOfMonth;j++){
  392. LocalDate tmp = time.minusDays(j);
  393. JSONObject rowTmp = timeSeries.getJSONObject(tmp.format(formatter));
  394. if (rowTmp != null){
  395. stock.setTime(tmp);
  396. row = rowTmp;
  397. break;
  398. }
  399. }
  400. }
  401. stock.setOpen(row.getString("1. open"));
  402. stock.setHigh(row.getString("2. high"));
  403. stock.setLow(row.getString("3. low"));
  404. stock.setClose(row.getString("4. close"));
  405. stock.setVolume(row.getString("5. volume"));
  406. stocks.add(stock);
  407. }
  408. return stocks;
  409. }
  410. }
  411. /**
  412. * AlphavantageTimeSeries-MonthlyAdjusted
  413. *
  414. * @param symbol
  415. * @param datatype
  416. * @param apikey
  417. * @return
  418. */
  419. public static List<TimeSeriesMonthlyAdjustedStock> parseTimeSeriesMonthlyAdjusted(String symbol,String datatype,String apikey){
  420. String result = AlphavantageUtil.getTimeSeriesMonthlyAdjusted(symbol, datatype, apikey);
  421. List<TimeSeriesMonthlyAdjustedStock> stocks = new ArrayList<TimeSeriesMonthlyAdjustedStock>();
  422. JSONObject jsonObject = JSON.parseObject(result);
  423. if (StringUtils.isEmpty(result)){
  424. return stocks;
  425. }else {
  426. JSONObject metaData = jsonObject.getJSONObject("Meta Data");
  427. DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
  428. LocalDate lastRefreshed = LocalDate.parse(metaData.getString("3. Last Refreshed"),formatter);
  429. String key = "Monthly Adjusted Time Series";
  430. JSONObject timeSeries = jsonObject.getJSONObject(key);
  431. int size = timeSeries.size();
  432. for (int i = 0;i < size - 1;i++){
  433. TimeSeriesMonthlyAdjustedStock stock = new TimeSeriesMonthlyAdjustedStock();
  434. stock.setSymbol(symbol);
  435. LocalDate time = lastRefreshed.withDayOfMonth(1).minusMonths(i).minusDays(1);
  436. stock.setTime(time);
  437. JSONObject row = timeSeries.getJSONObject(time.format(formatter));
  438. if (row == null){
  439. int daysOfMonth = time.getDayOfMonth();
  440. for (int j = 1;j < daysOfMonth;j++){
  441. LocalDate tmp = time.minusDays(j);
  442. JSONObject rowTmp = timeSeries.getJSONObject(tmp.format(formatter));
  443. if (rowTmp != null){
  444. stock.setTime(tmp);
  445. row = rowTmp;
  446. break;
  447. }
  448. }
  449. }
  450. stock.setOpen(row.getString("1. open"));
  451. stock.setHigh(row.getString("2. high"));
  452. stock.setLow(row.getString("3. low"));
  453. stock.setClose(row.getString("4. close"));
  454. stock.setAdjustedClose(row.getString("5. adjusted close"));
  455. stock.setVolume(row.getString("6. volume"));
  456. stock.setDividendAmount(row.getString("7. dividend amount"));
  457. stocks.add(stock);
  458. }
  459. return stocks;
  460. }
  461. }
  462. /**
  463. * AlphavantageTimeSeries-BatchStockQuotes
  464. *
  465. * @param symbols
  466. * @param datatype
  467. * @param apikey
  468. * @return
  469. */
  470. public static List<StockQuote> parseBatchStockQuotes(String symbols,String datatype,String apikey){
  471. String result = AlphavantageUtil.getBatchStockQuotes(symbols, datatype, apikey);
  472. List<StockQuote> stockQuotes = new ArrayList<StockQuote>();
  473. JSONObject jsonObject = JSON.parseObject(result);
  474. if (StringUtils.isEmpty(result)){
  475. return stockQuotes;
  476. }else{
  477. String key = "Stock Quotes";
  478. JSONArray stockQuoteJsonArray = jsonObject.getJSONArray(key);
  479. int size = stockQuoteJsonArray.size();
  480. for (int i = 0;i < size;i++){
  481. JSONObject stockQuoteJsonObject = stockQuoteJsonArray.getJSONObject(i);
  482. StockQuote stockQuote = new StockQuote();
  483. stockQuote.setSymbol(stockQuoteJsonObject.getString("1. symbol"));
  484. stockQuote.setPrice(stockQuoteJsonObject.getString("2. price"));
  485. stockQuote.setVolume(stockQuoteJsonObject.getString("3. volume"));
  486. DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
  487. LocalDateTime timestamp = LocalDateTime.parse(stockQuoteJsonObject.getString("4. timestamp"),formatter);
  488. stockQuote.setTimestamp(timestamp);
  489. stockQuotes.add(stockQuote);
  490. }
  491. return stockQuotes;
  492. }
  493. }
  494. }