Skip to content

Commit

Permalink
src final commit
Browse files Browse the repository at this point in the history
  • Loading branch information
soorjya authored May 24, 2024
1 parent 529e577 commit fe7958d
Show file tree
Hide file tree
Showing 10 changed files with 275 additions and 0 deletions.
49 changes: 49 additions & 0 deletions TASK_3/src/App.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
.App {
text-align: center;
min-height: 100vh;
}

.App-logo {
animation: App-logo-spin infinite 20s linear;
height: 40vmin;
}

.App-header {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
margin-bottom: 12px;
}

.App-link {
color: #61dafb;
}

.App-content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin-bottom: 12px;
}

.Stream-button {
margin-bottom: 12px;
}

.Graph {
min-height: 50vh;
width: 700px;
margin-bottom: 12px;
}

@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
9 changes: 9 additions & 0 deletions TASK_3/src/App.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<App />, div);
ReactDOM.unmountComponentAtNode(div);
});
59 changes: 59 additions & 0 deletions TASK_3/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import React, { Component } from 'react';
import DataStreamer, { ServerRespond } from './DataStreamer';
import Graph from './Graph';
import './App.css';

interface IState {
data: ServerRespond[],
showGraph: boolean,
}

class App extends Component<{}, IState> {
constructor(props: {}) {
super(props);
this.state = {
data: [],
showGraph: false,
};
}

renderGraph() {
if (this.state.showGraph) {
return (<Graph data={this.state.data}/>)
}
}

getDataFromServer() {
let x = 0;
const interval = setInterval(() => {
DataStreamer.getData((serverResponds: ServerRespond[]) => {
this.setState({
data: serverResponds,
showGraph: true,
});
});
x++;
if (x > 1000) {
clearInterval(interval);
}
}, 100);
}

render() {
return (
<div className="App">
<header className="App-header">
Bank Merge & Co Task 3
</header>
<div className="App-content">
<button className="btn btn-primary Stream-button" onClick={() => {this.getDataFromServer()}}>Start Streaming Data</button>
<div className="Graph">
{this.renderGraph()}
</div>
</div>
</div>
)
}
}

export default App;
33 changes: 33 additions & 0 deletions TASK_3/src/DataManipulator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { ServerRespond } from './DataStreamer';

export interface Row {
price_abc: number,
price_def: number,
ratio: number,
timestamp: Date,
upper_bound: number,
lower_bound: number,
trigger_alert: number | undefined,

}

export class DataManipulator {
static generateRow(serverResponds: ServerRespond[]): Row {
const priceABC = (serverResponds[0].top_ask.price + serverResponds[0].top_bid.price)/2;
const priceDEF = (serverResponds[1].top_ask.price + serverResponds[1].top_bid.price)/2;
const ratio = priceABC / priceDEF;
const upper_bound = 1 + 0.01;
const lower_bound = 1 - 0.01;
return {
price_abc: priceABC,
price_def: priceDEF,
ratio,
timestamp: serverResponds[0].timestamp > serverResponds[1].timestamp ?
serverResponds[0].timestamp : serverResponds[1].timestamp,
upper_bound: upper_bound,
lower_bound: lower_bound,
trigger_alert: (ratio > upper_bound || ratio < lower_bound ) ? ratio : undefined,

};
}
}
31 changes: 31 additions & 0 deletions TASK_3/src/DataStreamer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
export interface Order {
price: number,
size: number,
}
export interface ServerRespond {
stock: string,
top_bid: Order,
top_ask: Order,
timestamp: Date,
}

class DataStreamer {
static API_URL: string = 'http://localhost:8080/query?id=1';

static getData(callback: (data: ServerRespond[]) => void): void {
const request = new XMLHttpRequest();
request.open('GET', DataStreamer.API_URL, false);

request.onload = () => {
if (request.status === 200) {
callback(JSON.parse(request.responseText));
} else {
alert ('Request failed');
}
}

request.send();
}
}

export default DataStreamer;
4 changes: 4 additions & 0 deletions TASK_3/src/Graph.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
perspective-viewer {
height: 50vh;
width: 700px;
}
64 changes: 64 additions & 0 deletions TASK_3/src/Graph.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import React, { Component } from 'react';
import { Table } from '@jpmorganchase/perspective';
import { ServerRespond } from './DataStreamer';
import { DataManipulator } from './DataManipulator';
import './Graph.css';

interface IProps {
data: ServerRespond[],
}

interface PerspectiveViewerElement extends HTMLElement {
load: (table: Table) => void,
}
class Graph extends Component<IProps, {}> {
table: Table | undefined;

render() {
return React.createElement('perspective-viewer');
}

componentDidMount() {
// Get element from the DOM.
const elem = document.getElementsByTagName('perspective-viewer')[0] as unknown as PerspectiveViewerElement;

const schema = {
price_abc: 'float',
price_def: 'float',
ratio: 'float',
timestamp: 'date',
upper_bound: 'float',
lower_bound: 'float',
trigger_alert: 'float',
};

if (window.perspective && window.perspective.worker()) {
this.table = window.perspective.worker().table(schema);
}
if (this.table) {
// Load the `table` in the `<perspective-viewer>` DOM reference.
elem.load(this.table);
elem.setAttribute('view', 'y_line');
elem.setAttribute('row-pivots', '["timestamp"]');
elem.setAttribute('columns', '["ratio","lower_bound","upper_bound","trigger_alert"]');
elem.setAttribute('aggregates', JSON.stringify({
price_abc: 'avg',
price_def: 'avg',
timestamp: 'distinct count',
upper_bound: 'avg',
lower_bound: 'avg',
trigger_alert: 'avg',
}));
}
}

componentDidUpdate() {
if (this.table) {
this.table.update([
DataManipulator.generateRow(this.props.data),
]);
}
}
}

export default Graph;
14 changes: 14 additions & 0 deletions TASK_3/src/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
body {
margin: 0;
padding: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

code {
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
monospace;
}
11 changes: 11 additions & 0 deletions TASK_3/src/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import './index.css';
import 'bootstrap/dist/css/bootstrap.css';

declare global {
interface Window { perspective: any; }
}

ReactDOM.render(<App />, document.getElementById('root'));
1 change: 1 addition & 0 deletions TASK_3/src/react-app-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/// <reference types="react-scripts" />

0 comments on commit fe7958d

Please sign in to comment.