×

Warning

EU e-Privacy Directive

This website uses cookies to manage authentication, navigation, and other functions. By using our website, you agree that we can place these types of cookies on your device.

View Privacy Policy

View e-Privacy Directive Documents

View GDPR Documents

You have declined cookies. This decision can be reversed.
It has been a while since the last blog entry but today, we will eventually start to extend the features of our application and make it a useful tool for trading of stocks.We will ...
  • implement a pull mechanism of stocks data from a data source, ...
  • extend our data model to be more flexible, ...
  • implement a master-detail view for our stocks in order to show all the details that we have loaded.
 
Therefore, we need to adjust the following two process steps from our existing application:
activity diagram
 
The process step Load StockInfo needs to be adjusted in order to support a more flexible approach of loading stock information as well to load more data into the database.
The process step View StockInfo needs to be extended to show all the data that we have loaded. A simple listing of stocks won't do it anymore. Instead, we need a master detail view that allows us to show an overview of all stocks as well as detailed information about only one stock.

Datasource for Finance Data

I have struggled for a while to find a free and reliable datasource for stocks. After all, I have decided for the Yahoo Finance Data (at least as a starting point). Queries on the underlying YQL data tables are quite cumbersome to implement (believe me, I have carefully tried to do that - and failed). It seems as if the main issue was the availability of the underlying data tables. While it seems as if there are plenty of Online Services to get quotes, I haven't found any free and stable alternative.
Therefore, I have chosen the JAVA Finance Quotes API for Yahoo Finance as the basis of the application. As an implication, this means that my application can't be shared with others anymore due to the Yahoo API Terms of Use (Clause 1.7.4). I highly encourage you, to read the following article for further background information on this topic: http://meumobi.github.io/stocks%20apis/2016/03/13/get-realtime-stock-quotes-yahoo-finance-api.html
If possible, this API should be replaced in the future.
 
In terms of code changes, this is what needs to be done:
 
At first, we need to include the Finance Quotes API in our project. This is simply done by adding them to the pom.xml
 <!-- yahoo finance API to request financial info for stocks -->
 <dependency>
            <groupId>com.yahoofinance-api</groupId>
            <artifactId>YahooFinanceAPI</artifactId>
            <version>3.5.0</version>
 </dependency>
Afterwards, I have implemented the new class YahooFinanceDataCollectorImpl, which wraps the Finance Quotes API specific code:
package de.dlopes.stocks.facilitator.services.impl;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import yahoofinance.Stock;
import yahoofinance.YahooFinance;
import de.dlopes.stocks.facilitator.services.impl.util.SFApplicationException;
public class YahooFinanceDataCollectorImpl {
    public static Map<String,Stock> requestStocks(List<String> symbols) throws SFApplicationException {
 Map<String,Stock> result = new HashMap<String,Stock>();
     
 String[] yhooSymbols = symbols.toArray(new String[symbols.size()]);
 try {
            Map<String,Stock> quotes = YahooFinance.get(yhooSymbols);
            result = quotes;
        } catch (IOException ioe) {
            throw new SFApplicationException("Error during load of stock details for symbols from yahoo finance API", ioe);
        }
     
        return result;
    }
}

Data Model Changes

The data model for the stockinfo entity was extended as well in order to support a more flexible approach to load KPIs and further stock data:
data model
With this setup it should be possible to store any KPI and any further identified (e. g. Yahoo Symbol) for a stock. However, I kept the ISIN as the unique key for a stock because I didn't want to be entirely depending on Yahoo.
 
Just for completeness reasons, this is the diagram for our remaining entities:
data model1
 

Yahoo Symbols

Due to the Yahoo finance data, I have changed the approach to load the data in the application. The UI supports now a list of Yahoo Symbols as input and loads all associated current data via the Finance Quotes API. Obviously, the view for the load of stock information had to be adjusted for that:UI change
 
Additionaly, the managed bean AddStocksForm had to be introduced in order to temporarily store the list of Yahoo Symbols:
package de.dlopes.stocks.facilitator.ui.forms;
import java.io.Serializable;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import lombok.Data;
import de.dlopes.stocks.facilitator.config.ConfigurationSettings;
import de.dlopes.stocks.facilitator.services.FinanceDataExtractor;
@Data
public class AddStocksForm implements Serializable {
 private static final long serialVersionUID = 1764745848460626971L;
    
    @Autowired
    ConfigurationSettings config;
    
    private String url;
    private String listOfYahooSymbols;
 
    public void validateInput(FacesContext fc, UIComponent component, Object object) {
        FinanceDataExtractor finDataExtr = config.getFinanceDataExtractor();
     if (!StringUtils.isEmpty(url) &amp;& !finDataExtr.isApplicable(url)) {
        FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, "URL not applicable", "URL '" + url + "' is not applicable for automatic processing.");
           FacesContext.getCurrentInstance().addMessage("messages", msg);
     } else if (StringUtils.isEmpty(listOfYahooSymbols)) {
           FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, "No information provided", "Neither URL nor Yahoo Symbols where provided.");
           FacesContext.getCurrentInstance().addMessage("messages", msg);
     }
    }
 
}
 
This managed bean as well as the service "StockInfoService" (class StockInfoServiceImpl.java) are referenced in our Spring WebFlow flow stock-info-flow.xml:
<var name="addStocksForm" class="de.dlopes.stocks.facilitator.ui.forms.AddStocksForm"/>
  
<view-state id="loadStockInfo"> 
   <transition on="load" to="viewStockInfo">
     <evaluate expression="stockInfoService.addStocks(addStocksForm)" />
   </transition>
</view-state>

Master Detail View for Stocks

A couple of lines below in this Spring WebFlow flow, the master detail navigation is described:
   <view-state id="viewStockInfo">
       <var name="stocks" class="de.dlopes.stocks.facilitator.ui.forms.LazyStockDataModel"/>
       <transition on="select" to="showStockInfoDetails">
            <set name="flowScope.stock" value="stocks.selected" />
       </transition>
       <transition on="end" to="finish" />
   </view-state>
   <view-state id="showStockInfoDetails">
       <transition on="back" to="viewStockInfo" />
   </view-state>
The implementation relies on a LazyStockDataModel which stores the selected stock and manages the data table in the UI:
package de.dlopes.stocks.facilitator.ui.forms;
import java.util.List;
import java.util.Map;
import javax.persistence.Transient;
import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import de.dlopes.stocks.facilitator.data.StockInfo;
import de.dlopes.stocks.facilitator.data.StockInfoRepository;
import de.dlopes.stocks.facilitator.services.StockInfoService;
import de.dlopes.stocks.facilitator.services.impl.StockInfoServiceImpl;
public class LazyStockDataModel extends LazyDataModel<StockInfo> {
 private static final long serialVersionUID = -8832831134966938627L;
    // service needs to be declared as 'transient' in order to avoid Serialization Issue 
    // with org.springframework.dao.support.PersistenceExceptionTranslationInterceptor
    private transient StockInfoService stockInfoService;
 private List<StockInfo> stocks;
 private StockInfo selected;
     @Autowired
 public void setStockInfoService(StockInfoService stockInfoService) {
  this.stockInfoService = stockInfoService;
 }
 @Override
 public List<StockInfo> load(int first, int pageSize, String sortField, SortOrder order, Map<String, Object> filters) {
  // let's keep it easy for now: we neglect any pagination, sorting or filters
  this.stocks = stockInfoService.findAll();
  return stocks;
 }
 @Override
 public StockInfo getRowData(String rowKey) {
  for (StockInfo stock : this.stocks){
   if (stock.getIsin().equals(rowKey)) {
    return stock;
   }
   }
  return null;
 }
 @Override
 public Object getRowKey(StockInfo stock) {
  return stock.getIsin();
 }
 @Override
 public int getRowCount() {
  return stockInfoService.count();
 }
 public StockInfo getSelected() {
  return selected;
 }
 public void setSelected(StockInfo selected) {
  this.selected = selected;
 }
 public int getCurrentPage() {
  // let's keep it easy for now: there is only one page
  return 1;
 }
 public int getPageSize() {
     // let's keep it easy for now: page size = row count
  return getRowCount();
 }
}
The lazy data model "stocks" is utilized in the listing of loaded stock data: 
   <p:dataTable id="stocks" var="si" value="#{stocks}" paginator="true" dynamic="true" rows="#{stocks.pageSize}" page="#{stocks.currentPage}" lazy="true">
               <f:facet name="header">Stocks</f:facet>
               <p:column>
                   <f:facet name="header">Action</f:facet>
                   <p:commandButton id="viewStockDetails" value="View" action="select" icon="ui-icon-search">
                    <f:setPropertyActionListener value="#{si}" target="#{stocks.selected}" />
                   </p:commandButton>
                  </p:column>
   </p:dataTable>
The navigation to the detail view is invoked by means of a command button that has a property action listner which stores the selection from the lazy data model (right before the navigation happens):
 UI change2

On click on the "View" button, all (currently only the ISIN and the last changed date are listed, but you get the idea):

UI change3

This listing is rendered by the view showStockInfoDetails.xhtml:

<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!--/* 
 Copyright (c) 2016 Dominique Lopes.
 All rights reserved. 

 This Source Code Form is subject to the terms of the Mozilla Public 
 License, v. 2.0. If a copy of the MPL was not distributed with this
 file, You can obtain one at http://mozilla.org/MPL/2.0/.

 Contributors:
     Dominique Lopes - initial API and implementation
*/-->

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:p="http://primefaces.org/ui"
	template="/WEB-INF/layouts/standard.xhtml">

	<ui:define name="title">Detail</ui:define>

	<ui:define name="content">
        <h:form>
            <p:panel header="Stock: #{stock.name}">
                <h:panelGrid columns="1">
                    <h:outputText value="ISIN: #{stock.isin}" />
                    <h:outputText value="Last Changed: #{stock.lastChanged}" />            
                    <p:commandButton value="back" action="back" />
                </h:panelGrid>
            </p:panel>
        </h:form>
    </ui:define>

</ui:composition>

Recap

Today, we started to extend our application with some actual coding to dynamically load finance data and to show it in the UI. This setup allows us now to add more data in the next sessions until we are finally able to build a more complex analysis on top of that data.

As always, this blog post was inspired by some existing webpages - here they are:

About me

Profile picture
 

Dominique Lopes is a Senior SAP Consultant at MHP with more than 10 years experience in Software Development in various programming languages. In his leisure time he enjoys to try out new IT trends in his private software projects.

 

Popular Tags

JSN Mini template designed by JoomlaShine.com