Implemented assets/debts chart
This commit is contained in:
parent
437ca39b02
commit
37775e650d
6 changed files with 155 additions and 5 deletions
|
@ -17,5 +17,8 @@ def compare_balance_sheets(ticker_list: list):
|
|||
df_ret.loc[ticker, 'total_debt'] = selected_data.iloc[0]['CurrentAssets']
|
||||
df_ret.loc[ticker, 'current_debt'] = selected_data.iloc[0]['CurrentDebt']
|
||||
|
||||
df_ret.loc[:, 'old_assets'] = df_ret['total_assets'].copy() - df_ret['current_assets'].copy()
|
||||
df_ret.loc[:, 'old_debt'] = df_ret['total_debt'].copy() - df_ret['current_debt'].copy()
|
||||
|
||||
df_ret.index.name = 'ticker'
|
||||
return df_ret.reset_index(drop=False).replace({ np.nan: None }).to_dict('records')
|
|
@ -30,6 +30,14 @@ export interface PriceHistory {
|
|||
[ticker: string]: string | number; // really just number
|
||||
}
|
||||
|
||||
export interface BalanceSheet {
|
||||
ticker: string;
|
||||
current_assets: number;
|
||||
current_debt: number;
|
||||
total_assets: number;
|
||||
total_debt: number;
|
||||
}
|
||||
|
||||
export const getCompanies = (tickers?: string[]): Promise<Company[]> =>
|
||||
fetch(BACKEND_URL + '/companies' + (tickers ? ('/' + tickers.join('/')) : ''))
|
||||
.then(r => r.json())
|
||||
|
@ -43,3 +51,6 @@ export const getEmployees = (tickers: string[]): Promise<EmployeeCount[]> =>
|
|||
|
||||
export const getPriceHistory = (tickers: string[]): Promise<PriceHistory[]> =>
|
||||
fetch(BACKEND_URL + '/price_history/' + tickers.join('/').toUpperCase()).then(r => r.json())
|
||||
|
||||
export const getBalanceSheet = (tickers: string[]): Promise<BalanceSheet[]> =>
|
||||
fetch(BACKEND_URL + '/assets_debts/' + tickers.join('/')).then(r=>r.json())
|
||||
|
|
|
@ -12,6 +12,5 @@ export const defineLoader = <ApiResult>(apiCall: () => Promise<ApiResult>) => re
|
|||
alert('Error loading data'); // don't do this for the final product
|
||||
}
|
||||
this.loading = false;
|
||||
console.log(this.data, this.loading);
|
||||
}
|
||||
})
|
130
stockingly-frontend/src/components/BalanceSheet.vue
Normal file
130
stockingly-frontend/src/components/BalanceSheet.vue
Normal file
|
@ -0,0 +1,130 @@
|
|||
<template>
|
||||
<v-row>
|
||||
<v-col cols="12">
|
||||
<v-card>
|
||||
<v-card-item>
|
||||
<v-card-title>Balance sheet</v-card-title>
|
||||
</v-card-item>
|
||||
<v-card-text>
|
||||
<v-skeleton-loader class="chart-loader" v-if="balanceSheet.loading" />
|
||||
<ag-charts-vue class="chart" v-else :options="options" />
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { BalanceSheet, EmployeeCount, getBalanceSheet } from '@/api';
|
||||
import { defineLoader } from '@/api/loader';
|
||||
import { AgAxisLabelFormatterParams, time } from 'ag-charts-community';
|
||||
import { DateTime } from 'luxon';
|
||||
import { roundTo } from 'round-to';
|
||||
import { onMounted, computed } from 'vue';
|
||||
import { AgChartsVue } from 'ag-charts-vue3';
|
||||
|
||||
const renderer = (params: any) => ({
|
||||
title: params.title,
|
||||
content: DateTime.fromMillis(params.xValue).year + ': ' + roundTo(params.yValue, 0),
|
||||
});
|
||||
|
||||
const props = defineProps<{
|
||||
tickers: string[],
|
||||
colors: string[]
|
||||
}>();
|
||||
|
||||
const getTickerColor = (ticker: string) => props.colors[props.tickers.indexOf(ticker)];
|
||||
|
||||
const balanceSheet = defineLoader<BalanceSheet[]>(() => getBalanceSheet(props.tickers));
|
||||
|
||||
const options = computed(() => {
|
||||
if (balanceSheet.loading) return null;
|
||||
|
||||
const currencyFormat = (num: number) => {
|
||||
return '$' + num.toFixed(2).replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,')
|
||||
}
|
||||
|
||||
const renderer = (params: any) => {
|
||||
return {
|
||||
title: params.title,
|
||||
content: params.xValue + ': ' + currencyFormat(params.yKey.startsWith('old') ?
|
||||
(params.datum[params.yKey.replace('old', 'total')]) :
|
||||
(params.yValue)),
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
theme: 'ag-material',
|
||||
data: balanceSheet.data,
|
||||
series: [
|
||||
{
|
||||
type: 'column',
|
||||
xKey: 'ticker',
|
||||
yKey: 'current_assets',
|
||||
yName: 'Current Assets',
|
||||
stackGroup: 'Assets',
|
||||
fill: '#004D40',
|
||||
stroke: '#004D40'
|
||||
},
|
||||
{
|
||||
type: 'column',
|
||||
xKey: 'ticker',
|
||||
yKey: 'old_assets',
|
||||
yName: 'Total Assets',
|
||||
stackGroup: 'Assets',
|
||||
fill: '#4DB6AC',
|
||||
stroke: '#4DB6AC'
|
||||
},
|
||||
{
|
||||
type: 'column',
|
||||
xKey: 'ticker',
|
||||
yKey: 'current_debt',
|
||||
yName: 'Current Debt',
|
||||
stackGroup: 'Debt',
|
||||
fill: '#880E4F',
|
||||
stroke: '#880E4F'
|
||||
},
|
||||
{
|
||||
type: 'column',
|
||||
xKey: 'ticker',
|
||||
yKey: 'old_debt',
|
||||
yName: 'Total Debt',
|
||||
stackGroup: 'Debt',
|
||||
fill: '#F06292',
|
||||
stroke: '#F06292'
|
||||
}
|
||||
].map(e => ({
|
||||
...e,
|
||||
highlightStyle: {
|
||||
item: { fillOpacity: 0 },
|
||||
series: { enabled: false }
|
||||
},
|
||||
tooltip: { renderer: renderer },
|
||||
})),
|
||||
axes: [
|
||||
{
|
||||
type: 'category',
|
||||
position: 'bottom',
|
||||
},
|
||||
{
|
||||
type: 'number',
|
||||
position: 'left',
|
||||
label: {
|
||||
format: '$~s',
|
||||
formatter: (params: AgAxisLabelFormatterParams) =>
|
||||
params?.formatter?.(params.value)
|
||||
.replace('k', 'K')
|
||||
.replace('G', 'B') ?? ''
|
||||
},
|
||||
},
|
||||
],
|
||||
legend: {
|
||||
position: 'bottom',
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
balanceSheet.load();
|
||||
});
|
||||
</script>
|
|
@ -3,7 +3,7 @@
|
|||
<v-col cols="12">
|
||||
<v-card>
|
||||
<v-card-item>
|
||||
<v-card-title>Stock price over time</v-card-title>
|
||||
<v-card-title>Employees over time</v-card-title>
|
||||
</v-card-item>
|
||||
<v-card-text>
|
||||
<v-skeleton-loader class="chart-loader" v-if="employees.loading" />
|
||||
|
@ -85,7 +85,6 @@ const options = computed(() => {
|
|||
});
|
||||
|
||||
onMounted(() => {
|
||||
console.log(JSON.parse(JSON.stringify(props)));
|
||||
employees.load();
|
||||
});
|
||||
</script>
|
|
@ -46,7 +46,10 @@
|
|||
</v-row>
|
||||
<v-row>
|
||||
<v-col cols="12">
|
||||
<EmployeesChart :colors="colors" :tickers="tickers"></EmployeesChart>
|
||||
<employees-chart :colors="colors" :tickers="tickers" />
|
||||
</v-col>
|
||||
<v-col cols="12">
|
||||
<balance-sheet :colors="colors" :tickers="tickers" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-container>
|
||||
|
@ -62,6 +65,10 @@
|
|||
width: 100%;
|
||||
height: 30em !important;
|
||||
}
|
||||
|
||||
.v-row {
|
||||
width: 100% !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
@ -76,6 +83,7 @@ import { roundTo } from 'round-to';
|
|||
import { defineLoader } from '@/api/loader';
|
||||
import CompanyCard from '@/components/CompanyCard.vue';
|
||||
import EmployeesChart from '@/components/EmployeesChart.vue';
|
||||
import BalanceSheet from '@/components/BalanceSheet.vue';
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
@ -154,7 +162,7 @@ const options = computed(() => {
|
|||
formatter: (params: AgAxisLabelFormatterParams) =>
|
||||
params?.formatter?.(params.value)
|
||||
.replace('k', 'K')
|
||||
.replace('G', 'B') ?? ''
|
||||
.replace('G', 'B') ?? '' + '$'
|
||||
},
|
||||
},
|
||||
],
|
||||
|
|
Reference in a new issue