Skip to content

Commit

Permalink
Merge pull request #15 from r0fls/rd/insights-page
Browse files Browse the repository at this point in the history
add wip insights page
  • Loading branch information
r0fls authored Jun 7, 2024
2 parents 88a86c9 + 5ac05a5 commit 3710e1b
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 0 deletions.
2 changes: 2 additions & 0 deletions trading-dashboard/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Dashboard from './Dashboard';
import AccountView from './AccountView';
import Positions from './Positions';
import Trades from './Trades';
import Insights from './Insights';
import Sidebar from './Sidebar';

const App = () => {
Expand All @@ -18,6 +19,7 @@ const App = () => {
<Route path="/accounts" element={<AccountView />} />
<Route path="/positions" element={<Positions />} />
<Route path="/trades" element={<Trades />} />
<Route path="/insights" element={<Insights />} />
</Routes>
</div>
</Router>
Expand Down
82 changes: 82 additions & 0 deletions trading-dashboard/src/Insights.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import React, { useEffect, useState, useCallback } from 'react';
import axiosInstance from './axiosInstance';
import { Spinner, Card, Row, Col } from 'react-bootstrap';

const Insights = () => {
const [metrics, setMetrics] = useState({
var: 0,
max_drawdown: 0,
sharpe_ratio: 0,
});
const [loading, setLoading] = useState(true);

const fetchMetrics = useCallback(async () => {
setLoading(true);
try {
const [varResponse, drawdownResponse, sharpeResponse] = await Promise.all([
axiosInstance.get('/var'),
axiosInstance.get('/max_drawdown'),
axiosInstance.get('/sharpe_ratio'),
]);

setMetrics({
var: varResponse.data.var !== undefined ? varResponse.data.var : 0,
max_drawdown: drawdownResponse.data.max_drawdown !== undefined ? drawdownResponse.data.max_drawdown : 0,
sharpe_ratio: sharpeResponse.data.sharpe_ratio !== undefined ? sharpeResponse.data.sharpe_ratio : 0,
});
} catch (error) {
console.error('Eror fetching metrics:', error);
} finally {
setLoading(false);
}
}, []);

useEffect(() => {
fetchMetrics();
}, [fetchMetrics]);

return (
<div className="container-fluid">
<h1 className="mt-5">Insights</h1>
{loading ? (
<div className="text-center my-5">
<Spinner animation="border" role="status">
<span className="visually-hidden">Loading...</span>
</Spinner>
</div>
) : (
<>
<Row className="mb-3">
<Col md={4}>
<Card>
<Card.Body>
<Card.Title>Value At Risk (VaR)</Card.Title>
<Card.Text>{metrics.var.toFixed(2)}</Card.Text>
</Card.Body>
</Card>
</Col>
<Col md={4}>
<Card>
<Card.Body>
<Card.Title>Max Drawdown</Card.Title>
<Card.Text>{metrics.max_drawdown.toFixed(2)}</Card.Text>
</Card.Body>
</Card>
</Col>
<Col md={4}>
<Card>
<Card.Body>
<Card.Title>Sharpe Ratio</Card.Title>
<Card.Text>{metrics.sharpe_ratio.toFixed(2)}</Card.Text>
</Card.Body>
</Card>
</Col>
</Row>
{/* Add more metrics and charts as needed */}
</>
)}
</div>
);
};

export default Insights;
5 changes: 5 additions & 0 deletions trading-dashboard/src/Sidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ const Sidebar = () => {
<span>Trades</span>
</Link>
</li>
<li className="nav-text">
<Link to="/insights">
<span>Insights</span>
</Link>
</li>
</ul>
</nav>
</>
Expand Down
75 changes: 75 additions & 0 deletions ui/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
from sqlalchemy import create_engine, func
from database.models import Trade, AccountInfo, Balance, Position
from flask_cors import CORS
import numpy as np
from scipy.stats import norm
import os

app = Flask("TradingAPI")
Expand Down Expand Up @@ -162,6 +164,79 @@ def get_trade_stats():
'trades_per_day': trades_per_day
})

@app.route('/var', methods=['GET'])
def get_var():
brokers = request.args.getlist('brokers[]')
strategies = request.args.getlist('strategies[]')

query = app.session.query(Trade)

if brokers:
query = query.filter(Trade.broker.in_(brokers))
if strategies:
query = query.filter(Trade.strategy.in_(strategies))

trades = query.all()

if not trades:
return jsonify({'var': 0})

returns = [trade.profit_loss for trade in trades]
mean_return = np.mean(returns)
std_dev_return = np.std(returns)
var_95 = norm.ppf(0.05, mean_return, std_dev_return)

return jsonify({'var': var_95})

@app.route('/max_drawdown', methods=['GET'])
def get_max_drawdown():
brokers = request.args.getlist('brokers[]')
strategies = request.args.getlist('strategies[]')

query = app.session.query(Trade)

if brokers:
query = query.filter(Trade.broker.in_(brokers))
if strategies:
query = query.filter(Trade.strategy.in_(strategies))

trades = query.all()

if not trades:
return jsonify({'max_drawdown': 0})

cum_returns = np.cumsum([trade.profit_loss for trade in trades])
running_max = np.maximum.accumulate(cum_returns)
drawdowns = (running_max - cum_returns) / running_max
max_drawdown = np.max(drawdowns)

return jsonify({'max_drawdown': max_drawdown})

@app.route('/sharpe_ratio', methods=['GET'])
def get_sharpe_ratio():
brokers = request.args.getlist('brokers[]')
strategies = request.args.getlist('strategies[]')

query = app.session.query(Trade)

if brokers:
query = query.filter(Trade.broker.in_(brokers))
if strategies:
query = query.filter(Trade.strategy.in_(strategies))

trades = query.all()

if not trades:
return jsonify({'sharpe_ratio': 0})

returns = [trade.profit_loss for trade in trades]
mean_return = np.mean(returns)
std_dev_return = np.std(returns)
sharpe_ratio = mean_return / std_dev_return if std_dev_return != 0 else 0

return jsonify({'sharpe_ratio': sharpe_ratio})


def create_app(engine):
Session = sessionmaker(bind=engine)
app.session = Session()
Expand Down

0 comments on commit 3710e1b

Please sign in to comment.