diff --git a/src-trader-dashboard/components/LiveUpdatesGrid.jsx b/src-trader-dashboard/components/LiveUpdatesGrid.jsx
index 298fd98..2ccd835 100644
--- a/src-trader-dashboard/components/LiveUpdatesGrid.jsx
+++ b/src-trader-dashboard/components/LiveUpdatesGrid.jsx
@@ -48,6 +48,7 @@ export default class extends Component {
// grid events
this.onGridReady = this.onGridReady.bind(this);
+ this.onRowClicked = this.onRowClicked.bind(this);
// component events
this.updateQuote = this.updateQuote.bind(this);
@@ -70,6 +71,10 @@ export default class extends Component {
this.gridApi.sizeColumnsToFit();
}
+ onRowClicked(params) {
+ this.props.onRowClicked(params.data.symbol);
+ }
+
componentWillMount() {
this.props.selectedExchange.supportedStocks.forEach(symbol => {
this.exchangeService.addSubscriber(this.updateQuote, symbol);
@@ -151,7 +156,8 @@ export default class extends Component {
enableSorting="true"
// events
- onGridReady={this.onGridReady}>
+ onGridReady={this.onGridReady}
+ onRowClicked={this.onRowClicked}>
);
diff --git a/src-trader-dashboard/components/StockDetailPanel.jsx b/src-trader-dashboard/components/StockDetailPanel.jsx
index 1013d0c..49e53a2 100644
--- a/src-trader-dashboard/components/StockDetailPanel.jsx
+++ b/src-trader-dashboard/components/StockDetailPanel.jsx
@@ -1,5 +1,7 @@
import React, {Component} from "react";
+import ExchangeService from "../services/ExchangeService.jsx";
+
import StockPriceDeltaPanel from "./StockPriceDeltaPanel.jsx";
import StockTimestampPanel from "./StockTimestampPanel.jsx";
import StockSummaryPanel from "./StockSummaryPanel.jsx";
@@ -8,15 +10,42 @@ import StockHistoricalChartPanel from "./StockHistoricalChartPanel.jsx";
export default class extends Component {
constructor(props) {
super(props);
+
+ this.exchangeService = new ExchangeService();
+
+ this.state = {
+ priceDelta: null,
+ timestamp: null,
+ tickerSummary: null,
+ historicalData: null
+ }
+ }
+
+ shouldComponentUpdate(nextProps, nextState) {
+ return nextProps.selectedSymbol !== this.props.selectedSymbol;
+ }
+
+ componentWillReceiveProps(nextProps, nextState) {
+ if (nextProps.selectedSymbol !== this.props.selectedSymbol) {
+ let stockDetail = this.exchangeService.getTickerDetail(nextProps.selectedSymbol);
+
+ this.setState({
+ pricingDelta: stockDetail.pricingDelta,
+ timestamp: stockDetail.timestamp,
+ tickerSummary: stockDetail.tickerSummary,
+ historicalData: stockDetail.historicalData
+ })
+ }
}
render() {
return (
-
- 155.47
-
-
-
- -0.23
- (-0.15%)
+ let swingStyle = this.state.delta >= 0 ? positiveSwingStyle : negativeSwingStyle;
+
+ if(!this.props.pricingDelta) {
+ return null;
+ } else {
+ return (
+
+
+ {this.numberFormatter(this.state.currentPrice)}
+
+
+ {this.numberFormatter(this.state.delta)}
+ ({this.numberFormatter(this.state.deltaPercentage)}%)
+
+
-
- );
+ );
+ }
}
}
\ No newline at end of file
diff --git a/src-trader-dashboard/components/StockSummaryPanel.jsx b/src-trader-dashboard/components/StockSummaryPanel.jsx
index 114cf92..f59391f 100644
--- a/src-trader-dashboard/components/StockSummaryPanel.jsx
+++ b/src-trader-dashboard/components/StockSummaryPanel.jsx
@@ -13,9 +13,9 @@ export default class extends Component {
let tableStyle = {
display: "inline-block",
verticalAlign: "top",
- borderCollapse:"collapse"
+ borderCollapse: "collapse"
- };
+ };
let keyStyle = {
color: "#666"
@@ -25,70 +25,54 @@ export default class extends Component {
textAlign: "right"
};
- return (
-
-
-
-
- | Range
- |
- 154.72 - 156.06
- |
-
-
- | 52 week
- |
- 91.50 - 156.65
- |
-
-
- | Open
- |
- 155.94
- |
-
-
- |
- Vol / Avg.
- |
- 15,931.00/24.94M
- |
-
-
-
-
-
-
- |
- Div/yield
- |
- 0.63/1.62
- |
-
-
- |
- EPS
- |
- 8.55
- |
-
-
- |
- Shares
- |
- 5,213.84M
- |
-
-
- |
- Mkt cap
- |
- 808,518.60M
- |
-
-
-
-
- );
+ if (!this.props.tickerSummary) {
+ return null;
+ } else {
+ return (
+
+
+
+
+ | Range |
+ {this.props.tickerSummary.range} |
+
+
+ | 52 week |
+ {this.props.tickerSummary.fiftyTwoWeek} |
+
+
+ | Open |
+ {this.props.tickerSummary.open} |
+
+
+ | Vol / Avg. |
+ {this.props.tickerSummary.vol}/{this.props.tickerSummary.avg}
+ |
+
+
+
+
+
+
+ | Div/yield |
+ {this.props.tickerSummary.dividend}/{this.props.tickerSummary.yld} |
+
+
+ | EPS |
+ {this.props.tickerSummary.eps} |
+
+
+ | Shares |
+ {this.props.tickerSummary.shares} |
+
+
+ | Market Cap |
+ {this.props.tickerSummary.marketCap} |
+
+
+
+
+ );
+ }
}
}
\ No newline at end of file
diff --git a/src-trader-dashboard/components/StockTimestampPanel.jsx b/src-trader-dashboard/components/StockTimestampPanel.jsx
index 16c4c03..a9fda62 100644
--- a/src-trader-dashboard/components/StockTimestampPanel.jsx
+++ b/src-trader-dashboard/components/StockTimestampPanel.jsx
@@ -6,41 +6,25 @@ export default class extends Component {
}
render() {
- let containerStyle = {
- display: "inline-block"
- };
-
- let priceStyle = {
- fontSize: "2.6em",
- fontWeight: "bold",
- marginRight: 10
- };
-
let minorStyle = {
fontSize: 11,
color: "#6F6F6F"
};
- let negativeSwingStyle = {
- color: "#d14836",
- marginRight: 5
- };
-
- let positiveSwingStyle = {
- color: "#093",
- marginRight: 5
- };
-
- return (
-
-
- May 17, 6:17am GMT-4
-
-
NASDAQ
-
Currency in USD
+ if (!this.props.timestamp) {
+ return null;
+ } else {
+ return (
+
+
+ {this.props.timestamp}
+
+
{this.props.exchangeName}
+
Currency in USD
+
-
- );
+ );
+ }
}
}
\ No newline at end of file
diff --git a/src-trader-dashboard/components/TraderDashboard.jsx b/src-trader-dashboard/components/TraderDashboard.jsx
index fecd133..fe27196 100644
--- a/src-trader-dashboard/components/TraderDashboard.jsx
+++ b/src-trader-dashboard/components/TraderDashboard.jsx
@@ -36,7 +36,7 @@ export default class TraderDashboard extends Component {
onExchangeChanged={this.onExchangeChanged}>
-
+
);
}
diff --git a/src-trader-dashboard/services/ExchangeService.jsx b/src-trader-dashboard/services/ExchangeService.jsx
index 6188444..de2589c 100644
--- a/src-trader-dashboard/services/ExchangeService.jsx
+++ b/src-trader-dashboard/services/ExchangeService.jsx
@@ -17,6 +17,8 @@ export default class {
];
this.initialiseTickerData();
+
+ this.timestamp = new Date();
}
initialiseTickerData() {
@@ -95,6 +97,102 @@ export default class {
return exchange.symbol === exchangeName;
})
}
+
+ formatNumber(input) {
+ return input.toFixed(2);
+ }
+
+ formatWithDecimalPlaces(x) {
+ return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
+ }
+
+ getTickerDetail(symbol) {
+ let ticker = this.getTicker(symbol);
+ let currentPrice = ticker.price;
+ let tenthOfCurrentPrice = currentPrice / 10;
+ let previousPrice = +currentPrice + this.random(-tenthOfCurrentPrice, tenthOfCurrentPrice);
+
+ let twentiethOfCurrentPrice = currentPrice / 20;
+ let yearAgoPrice = this.random(-twentiethOfCurrentPrice, twentiethOfCurrentPrice);
+
+ let range = `${this.formatNumber(previousPrice)} - ${this.formatNumber(currentPrice)}`;
+ let fiftyTwoWeek = `${this.formatNumber(yearAgoPrice)} - ${this.formatNumber(currentPrice)}`;
+
+ let open = this.formatNumber(ticker.bid); // not the same, but will do for demo purposes
+
+ let vol = this.formatWithDecimalPlaces(this.random(5000, 20000).toFixed(2));
+ let avg = `${this.formatNumber(this.random(10, 30))}M`;
+
+ let dividend = this.random(0, 1).toFixed(2);
+ let yld = this.random(1, 2).toFixed(2);
+
+ let eps = this.random(5, 10).toFixed(2);
+
+ let shares = `${this.random(3000, 10000).toFixed(2)}M`;
+
+ let marketCap = `${this.random(100000, 900000).toFixed(2)}M`;
+
+ let historicalData = this.generateHistoricalData(100, this.timestamp, currentPrice);
+
+ return {
+ pricingDelta: {
+ currentPrice,
+ previousPrice
+ },
+ timestamp: this.timestamp.toDateString(),
+ tickerSummary: {
+ range,
+ fiftyTwoWeek,
+ open,
+ vol,
+ avg,
+ dividend,
+ yld,
+ eps,
+ shares,
+ marketCap
+ },
+ historicalData
+ }
+ }
+
+ formatDate(date) {
+ // todo remove substring(2,4) and change parseTime instead
+ let year = ("" + date.getFullYear()).substring(2, 4);
+ return `${date.getDate()}-${date.getMonth()+1}-${year}`
+ // return `${date.getDate()}-${date.getMonth()+1}-${date.getFullYear()
+ }
+
+ generateHistoricalData(numberOfPoints, endDate, endPrice) {
+ let historicalData = [{
+ "date": this.formatDate(endDate),
+ "price": endPrice
+ }
+ ];
+
+ let numberOfTransitions = 15;
+ let pointsPerTransition = numberOfPoints / numberOfTransitions;
+
+ let lastDate = endDate;
+ let lastPrice = endPrice;
+ for (let transition = 0; transition < numberOfTransitions; transition++) {
+ let swing = (Math.random() >= 0.5) ? 1 : -1;
+
+ for (let i = 0; i <= pointsPerTransition; i++) {
+ lastDate.setDate(lastDate.getDate() - 1);
+ lastPrice = lastPrice + (swing * this.random(-1, 10));
+
+ historicalData.push({
+ "date": this.formatDate(lastDate),
+ "price": lastPrice
+ })
+ }
+ }
+
+ historicalData = historicalData.reverse();
+
+ return historicalData;
+ }
}
const NASDAQ_SYMBOLS = [