things occurred
This commit is contained in:
parent
c197d08d67
commit
e68a6eeb36
2 changed files with 105 additions and 0 deletions
17
backend/api/eps.py
Normal file
17
backend/api/eps.py
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import os
|
||||||
|
import pandas as pd
|
||||||
|
import numpy as np
|
||||||
|
from scraper.top100_extractor import programming_crime_list
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
DF_EPS_PATH: str = os.path.join(os.path.dirname(__file__), '..', '..', 'Elaborated_Data', 'eps_quarterly_bar_chart.csv')
|
||||||
|
|
||||||
|
|
||||||
|
def get_eps(tickers: list[str]) -> list[dict]:
|
||||||
|
df = pd.read_csv(DF_EPS_PATH)
|
||||||
|
ticker_series = pd.Series(tickers)
|
||||||
|
df = df.loc[df.symbol.isin(ticker_series), :] \
|
||||||
|
.rename(columns={"epsActual": "quarterlyEps", "symbol": "ticker"}) \
|
||||||
|
.reset_index(drop=True)
|
||||||
|
df = df.pivot(index='quarter', columns='ticker', values='quarterlyEps').reset_index(drop=False)
|
||||||
|
return df.replace({ np.nan: None }).to_dict('records')
|
88
stockingly-frontend/src/components/EpsChart.vue
Normal file
88
stockingly-frontend/src/components/EpsChart.vue
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
<template>
|
||||||
|
<v-row>
|
||||||
|
<v-col cols="12">
|
||||||
|
<v-card>
|
||||||
|
<v-card-item>
|
||||||
|
<v-card-title>Earnings per Share (EPS)</v-card-title>
|
||||||
|
</v-card-item>
|
||||||
|
<v-card-text>
|
||||||
|
<v-skeleton-loader class="chart-loader" v-if="epsData.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 { EmployeeCount, Eps, getEmployees, getEps } from '@/api';
|
||||||
|
import { defineLoader } from '@/api/loader';
|
||||||
|
import { 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 epsData = defineLoader<Eps[]>(() => getEps(props.tickers));
|
||||||
|
|
||||||
|
const options = computed(() => {
|
||||||
|
if (epsData.loading) return null;
|
||||||
|
|
||||||
|
return {
|
||||||
|
theme: 'ag-material',
|
||||||
|
data: epsData.data?.map(e => ({ ...e, quarter: Date.parse(e.quarter) })),
|
||||||
|
series: props.tickers.map((t: string) => ({
|
||||||
|
xKey: 'quarter',
|
||||||
|
type: 'column',
|
||||||
|
yKey: t,
|
||||||
|
yName: t,
|
||||||
|
stroke: getTickerColor(t),
|
||||||
|
tooltip: { renderer: renderer },
|
||||||
|
marker: {
|
||||||
|
fill: getTickerColor(t),
|
||||||
|
stroke: getTickerColor(t)
|
||||||
|
}
|
||||||
|
})),
|
||||||
|
axes: [
|
||||||
|
{
|
||||||
|
type: 'time',
|
||||||
|
position: 'bottom',
|
||||||
|
tick: {
|
||||||
|
interval: time.month.every(3, {
|
||||||
|
snapTo: DateTime.utc(2000, 1, 1).toJSDate() // snap to solar year quarters
|
||||||
|
})
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
autoRotate: true,
|
||||||
|
autoRotateAngle: 335,
|
||||||
|
format: '%Y-%m'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'number',
|
||||||
|
position: 'left',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
legend: {
|
||||||
|
position: 'bottom',
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
epsData.load();
|
||||||
|
});
|
||||||
|
</script>
|
Reference in a new issue