Commit 2edafb02 authored by Emmanuel Raviart's avatar Emmanuel Raviart
Browse files

Rename stock to security.

parent 1d42f894
...@@ -15,7 +15,7 @@ Edit `src/server-config.js` to change database informations. Then ...@@ -15,7 +15,7 @@ Edit `src/server-config.js` to change database informations. Then
npm install npm install
``` ```
## Retrieve or generate JSON files of issuers, stocks, etc ## Retrieve or generate JSON files of issuers, securities, etc
### Either retrieve JSON files from their git repository ### Either retrieve JSON files from their git repository
...@@ -28,7 +28,7 @@ git clone https://gitlab.huma-num.fr/eurhisfirm/dfih-open-data.git data ...@@ -28,7 +28,7 @@ git clone https://gitlab.huma-num.fr/eurhisfirm/dfih-open-data.git data
```bash ```bash
node_modules/.bin/babel-node scripts/generate-issuers.js node_modules/.bin/babel-node scripts/generate-issuers.js
node_modules/.bin/babel-node scripts/generate-stock-exchanges.js node_modules/.bin/babel-node scripts/generate-stock-exchanges.js
node_modules/.bin/babel-node scripts/generate-stocks.js node_modules/.bin/babel-node scripts/generate-securities.js
``` ```
## Launch server ## Launch server
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
<ul> <ul>
{#each rows as row (row[0])} {#each rows as row (row[0])}
<li> <li>
<a id="{row[2]}" href="/stocks/{row[0]}/prices" data-container="body" data-trigger="manual" data-toggle="popover" <a id="{row[2]}" href="/securities/{row[0]}/prices" data-container="body" data-trigger="manual" data-toggle="popover"
data-html="true" data-placement="top" data-content="Loading price data..." on:mouseenter="popoverHover(event)" data-html="true" data-placement="top" data-content="Loading price data..." on:mouseenter="popoverHover(event)"
on:mouseleave="popoverLeave(event)">{row[1]}</a> on:mouseleave="popoverLeave(event)">{row[1]}</a>
</li> </li>
......
...@@ -3,123 +3,123 @@ import oracledb from "oracledb" ...@@ -3,123 +3,123 @@ import oracledb from "oracledb"
import { pool } from "../../../../database" import { pool } from "../../../../database"
export async function get(req, res) { export async function get(req, res) {
const { stock: stockId } = req.params const { security: securityId } = req.params
const connection = await pool.getConnection() const connection = await pool.getConnection()
let result = null let result = null
try { try {
result = await connection.execute( result = await connection.execute(
` `
select comptant.notation, select comptant.notation,
(comptant.day - to_date('1970/01/01','YYYY/MM/DD'))*86400000 as EPOCH, (comptant.day - to_date('1970/01/01','YYYY/MM/DD'))*86400000 as EPOCH,
comptant.prix as prix_comptant, comptant.prix as prix_comptant,
terme.Open_Liq15, terme.Open_LiqFin, terme.Open_Liq15, terme.Open_LiqFin,
terme.Close_Liq15, terme.Close_LiqFin, terme.Close_Liq15, terme.Close_LiqFin,
terme.Min_Liq15, terme.Min_LiqFin, terme.Min_Liq15, terme.Min_LiqFin,
terme.Max_Liq15, terme.Max_LiqFin terme.Max_Liq15, terme.Max_LiqFin
from from
( (
select last_value(notation ignore nulls) over (order by day, notation) as notation, select last_value(notation ignore nulls) over (order by day, notation) as notation,
day, day,
max(Open_Liq15) as Open_Liq15, max(Open_LiqFin) as Open_LiqFin, max(Open_Liq15) as Open_Liq15, max(Open_LiqFin) as Open_LiqFin,
max(Close_Liq15) as Close_Liq15, max(Close_LiqFin) as Close_LiqFin, max(Close_Liq15) as Close_Liq15, max(Close_LiqFin) as Close_LiqFin,
min(Min_Liq15) as Min_Liq15, min(Min_LiqFin) as Min_LiqFin, min(Min_Liq15) as Min_Liq15, min(Min_LiqFin) as Min_LiqFin,
max(Max_Liq15) as Max_Liq15, max(Max_LiqFin) as Max_LiqFin max(Max_Liq15) as Max_Liq15, max(Max_LiqFin) as Max_LiqFin
FROM FROM
(select c.notation, cd.exact_date as day, (select c.notation, cd.exact_date as day,
nvl(c.Open_Liq15, c.Open_Liq151) as Open_Liq15, nvl(c.Open_Liq15, c.Open_Liq151) as Open_Liq15,
nvl(c.Open_LiqFin, c.Open_LiqFin1) as Open_LiqFin, nvl(c.Open_LiqFin, c.Open_LiqFin1) as Open_LiqFin,
nvl(c.Close_Liq15, c.Close_Liq151) as Close_Liq15, nvl(c.Close_Liq15, c.Close_Liq151) as Close_Liq15,
nvl(c.Close_LiqFin, c.Close_LiqFin1) as Close_LiqFin, nvl(c.Close_LiqFin, c.Close_LiqFin1) as Close_LiqFin,
nvl(c.Min_Liq15, c.Min_Liq151) as Min_Liq15, nvl(c.Min_Liq15, c.Min_Liq151) as Min_Liq15,
nvl(c.Min_LiqFin, c.Min_LiqFin1) as Min_LiqFin, nvl(c.Min_LiqFin, c.Min_LiqFin1) as Min_LiqFin,
nvl(c.Max_Liq15, c.Max_Liq151) as Max_Liq15, nvl(c.Max_Liq15, c.Max_Liq151) as Max_Liq15,
nvl(c.Max_LiqFin, c.Max_LiqFin1) as Max_LiqFin nvl(c.Max_LiqFin, c.Max_LiqFin1) as Max_LiqFin
from from
control_dates cd control_dates cd
left join left join
( (
select np.day, np.notation, select np.day, np.notation,
decode(np.setdate, 20, np.open) Open_Liq15, decode(np.setdate, 20, np.open) Open_Liq15,
decode(np.setdate, 15, np.open, 17, np.open, 18, np.open, 19, np.open) Open_LiqFin, decode(np.setdate, 15, np.open, 17, np.open, 18, np.open, 19, np.open) Open_LiqFin,
(case when extract(day from np.day) between 10 and 20 (case when extract(day from np.day) between 10 and 20
then decode(np.setdate, 13, np.open) END) as Open_Liq151, then decode(np.setdate, 13, np.open) END) as Open_Liq151,
(case when extract(day from np.day) < 10 or extract(day from np.day) > 20 (case when extract(day from np.day) < 10 or extract(day from np.day) > 20
then decode(np.setdate, 13, np.open) END) as Open_LiqFin1, then decode(np.setdate, 13, np.open) END) as Open_LiqFin1,
decode(np.setdate, 20, np.close) Close_Liq15, decode(np.setdate, 20, np.close) Close_Liq15,
decode(np.setdate, 15, np.close, 17, np.close, 18, np.close, 19, np.close) Close_LiqFin, decode(np.setdate, 15, np.close, 17, np.close, 18, np.close, 19, np.close) Close_LiqFin,
(case when extract(day from np.day) between 10 and 20 (case when extract(day from np.day) between 10 and 20
then decode(np.setdate, 13, np.close) END) as Close_Liq151, then decode(np.setdate, 13, np.close) END) as Close_Liq151,
(case when extract(day from np.day) < 10 or extract(day from np.day) > 20 (case when extract(day from np.day) < 10 or extract(day from np.day) > 20
then decode(np.setdate, 13, np.close) END) as Close_LiqFin1, then decode(np.setdate, 13, np.close) END) as Close_LiqFin1,
decode(np.setdate, 20, np.min) Min_Liq15, decode(np.setdate, 20, np.min) Min_Liq15,
decode(np.setdate, 15, np.min, 17, np.min, 18, np.min, 19, np.min) Min_LiqFin, decode(np.setdate, 15, np.min, 17, np.min, 18, np.min, 19, np.min) Min_LiqFin,
(case when extract(day from np.day) between 10 and 20 (case when extract(day from np.day) between 10 and 20
then decode(np.setdate, 13, np.min) END) as Min_Liq151, then decode(np.setdate, 13, np.min) END) as Min_Liq151,
(case when extract(day from np.day) < 10 or extract(day from np.day) > 20 (case when extract(day from np.day) < 10 or extract(day from np.day) > 20
then decode(np.setdate, 13, np.min) END) as Min_LiqFin1, then decode(np.setdate, 13, np.min) END) as Min_LiqFin1,
decode(np.setdate, 20, np.max) Max_Liq15, decode(np.setdate, 20, np.max) Max_Liq15,
decode(np.setdate, 15, np.max, 17, np.max, 18, np.max, 19, np.max) Max_LiqFin, decode(np.setdate, 15, np.max, 17, np.max, 18, np.max, 19, np.max) Max_LiqFin,
(case when extract(day from np.day) between 10 and 20 (case when extract(day from np.day) between 10 and 20
then decode(np.setdate, 13, np.max) END) as Max_Liq151, then decode(np.setdate, 13, np.max) END) as Max_Liq151,
(case when extract(day from np.day) < 10 or extract(day from np.day) > 20 (case when extract(day from np.day) < 10 or extract(day from np.day) > 20
then decode(np.setdate, 13, np.max) END) as Max_LiqFin1 then decode(np.setdate, 13, np.max) END) as Max_LiqFin1
from notation_price np from notation_price np
where np.notation in (select id from notation where stock = :stockId) where np.notation in (select id from notation where stock = :securityId)
and np.market = 1 and np.market = 1
) c ON (cd.exact_date = c.day) ) c ON (cd.exact_date = c.day)
where nvl(cd.exact_date, c.day) >= (select min(startdate) from notation where stock = :stockId) where nvl(cd.exact_date, c.day) >= (select min(startdate) from notation where stock = :securityId)
and nvl(cd.exact_date, c.day) <= (select max(enddate) from notation where stock = :stockId) and nvl(cd.exact_date, c.day) <= (select max(enddate) from notation where stock = :securityId)
) )
group by notation, day group by notation, day
) terme ) terme
join join
( (
select distinct last_value(notation ignore nulls) over (order by day, notation) as notation, select distinct last_value(notation ignore nulls) over (order by day, notation) as notation,
day, day,
last_value(prix ignore nulls) over (order by day, notation) as prix last_value(prix ignore nulls) over (order by day, notation) as prix
from from
( (
select nvl(pnep.notation, pnp.notation) as notation, select nvl(pnep.notation, pnp.notation) as notation,
nvl(pnep.day, pnp.day) as day, nvl(pnep.day, pnp.day) as day,
nvl(pnep.prix, pnp.prix) as prix nvl(pnep.prix, pnp.prix) as prix
from from
( (
select notation, day, dernier_prix_comptant as prix from select notation, day, dernier_prix_comptant as prix from
( (
select distinct a.notation, cd.exact_date as day, a.dernier_prix_comptant select distinct a.notation, cd.exact_date as day, a.dernier_prix_comptant
from from
control_dates cd control_dates cd
left join left join
( (
select nep.day, nep.notation, select nep.day, nep.notation,
first_value(nep.price) first_value(nep.price)
over (partition by nep.day, nep.notation order by nep.id desc) as dernier_prix_comptant over (partition by nep.day, nep.notation order by nep.id desc) as dernier_prix_comptant
from notation_extra_price nep where nep.notation in (select id from notation where stock = :stockId) from notation_extra_price nep where nep.notation in (select id from notation where stock = :securityId)
) a ON (cd.exact_date = a.day) ) a ON (cd.exact_date = a.day)
where nvl(cd.exact_date, a.day) >= (select min(startdate) from notation where stock = :stockId) where nvl(cd.exact_date, a.day) >= (select min(startdate) from notation where stock = :securityId)
and nvl(cd.exact_date, a.day) <= (select max(enddate) from notation where stock = :stockId) and nvl(cd.exact_date, a.day) <= (select max(enddate) from notation where stock = :securityId)
) )
) pnep ) pnep
full outer join full outer join
( (
select notation, day, dernier_prix_comptant as prix from select notation, day, dernier_prix_comptant as prix from
( (
select distinct b.notation, nvl(cd.exact_date, b.day) as day, b.dernier_prix_comptant select distinct b.notation, nvl(cd.exact_date, b.day) as day, b.dernier_prix_comptant
from from
control_dates cd control_dates cd
left join left join
( (
select np.day, np.notation, nvl(np.price_yesterday, np.previous) as dernier_prix_comptant select np.day, np.notation, nvl(np.price_yesterday, np.previous) as dernier_prix_comptant
from notation_price np from notation_price np
where np.notation in (select id from notation where stock = :stockId) where np.notation in (select id from notation where stock = :securityId)
and np.market = 2 and np.market = 2
) b ON (cd.exact_date = b.day) ) b ON (cd.exact_date = b.day)
where nvl(cd.exact_date, b.day) >= (select min(startdate) from notation where stock = :stockId) where nvl(cd.exact_date, b.day) >= (select min(startdate) from notation where stock = :securityId)
and nvl(cd.exact_date, b.day) <= (select max(enddate) from notation where stock = :stockId) and nvl(cd.exact_date, b.day) <= (select max(enddate) from notation where stock = :securityId)
) )
) pnp ) pnp
ON (pnep.notation = pnp.notation and pnep.day = pnp.day) ON (pnep.notation = pnp.notation and pnep.day = pnp.day)
...@@ -128,7 +128,7 @@ export async function get(req, res) { ...@@ -128,7 +128,7 @@ export async function get(req, res) {
order by comptant.day order by comptant.day
`, `,
{ {
stockId: { dir: oracledb.BIND_IN, val: stockId, type: oracledb.STRING }, securityId: { dir: oracledb.BIND_IN, val: securityId, type: oracledb.STRING },
} }
) )
} catch (error) { } catch (error) {
......
...@@ -4,9 +4,9 @@ import path from "path" ...@@ -4,9 +4,9 @@ import path from "path"
import serverConfig from "../../../../server-config" import serverConfig from "../../../../server-config"
export function get(req, res) { export function get(req, res) {
const { stock: stockId } = req.params const { security: securityId } = req.params
const stockFilePath = path.join(serverConfig.dataDir, "stocks", `stock_${stockId}.json`) const securityFilePath = path.join(serverConfig.dataDir, "securities", `security_${securityId}.json`)
if (!fs.existsSync(stockFilePath)) { if (!fs.existsSync(securityFilePath)) {
res.writeHead(404, { res.writeHead(404, {
"Content-Type": "application/json", "Content-Type": "application/json",
}) })
...@@ -15,7 +15,7 @@ export function get(req, res) { ...@@ -15,7 +15,7 @@ export function get(req, res) {
{ {
error: { error: {
code: 404, code: 404,
message: `Stock ${stockId} doesn't exist.`, message: `Security ${securityId} doesn't exist.`,
}, },
}, },
null, null,
...@@ -23,7 +23,7 @@ export function get(req, res) { ...@@ -23,7 +23,7 @@ export function get(req, res) {
) )
) )
} }
if (!fs.lstatSync(stockFilePath).isFile()) { if (!fs.lstatSync(securityFilePath).isFile()) {
res.writeHead(404, { res.writeHead(404, {
"Content-Type": "application/json", "Content-Type": "application/json",
}) })
...@@ -32,7 +32,7 @@ export function get(req, res) { ...@@ -32,7 +32,7 @@ export function get(req, res) {
{ {
error: { error: {
code: 404, code: 404,
message: `Stock ${stockId} doesn't exist (not a file).`, message: `Security ${securityId} doesn't exist (not a file).`,
}, },
}, },
null, null,
...@@ -43,5 +43,5 @@ export function get(req, res) { ...@@ -43,5 +43,5 @@ export function get(req, res) {
res.writeHead(200, { res.writeHead(200, {
"Content-Type": "application/json", "Content-Type": "application/json",
}) })
res.end(fs.readFileSync(stockFilePath)) res.end(fs.readFileSync(securityFilePath))
} }
...@@ -28,10 +28,10 @@ ...@@ -28,10 +28,10 @@
{/if} {/if}
</li> </li>
<li class="nav-item"> <li class="nav-item">
{#if child.segment === "stocks"} {#if child.segment === "securities"}
<a class="nav-link active" href="/issuers/{issuer.id}/stocks" rel="prefetch">Stocks <span class="sr-only">(current)</span></a> <a class="nav-link active" href="/issuers/{issuer.id}/securities" rel="prefetch">Securities <span class="sr-only">(current)</span></a>
{:else} {:else}
<a class="nav-link" href="/issuers/{issuer.id}/stocks" rel="prefetch">Stocks</a> <a class="nav-link" href="/issuers/{issuer.id}/securities" rel="prefetch">Securities</a>
{/if} {/if}
</li> </li>
<li class="nav-item"> <li class="nav-item">
......
...@@ -50,15 +50,15 @@ ...@@ -50,15 +50,15 @@
</div> </div>
{/if} {/if}
<!-- {#if issuer.stocks} <!-- {#if issuer.securities}
<div class="card my-3"> <div class="card my-3">
<div class="card-header"> <div class="card-header">
<h3 class="mb-0"> <h3 class="mb-0">
<button class="btn btn-light" type="button"> <button class="btn btn-light" type="button">
{#if Object.keys(issuer.stocks).length > 1} {#if Object.keys(issuer.securities).length > 1}
{Object.keys(issuer.stocks).length} stocks {Object.keys(issuer.securities).length} securities
{:else} {:else}
{Object.keys(issuer.stocks).length} stock {Object.keys(issuer.securities).length} stock
{/if} {/if}
</button> </button>
</h3> </h3>
......
<p class="my-4 text-muted">
{#if Object.keys(issuer.securities).length > 1}
{Object.keys(issuer.securities).length} results
{:else}
{Object.keys(issuer.securities).length} result
{/if}
</p>
<div class="list-group">
{#each Object.values(issuer.securities) as security (security.id)}
<a class="list-group-item list-group-item-action" href="/securities/{security.id}">
<div>{(security.name || "Titre sans nom").toUpperCase()}</div>
<div class="text-muted">{security.share_type.name}</div>
<div class="text-muted">{[...new Set(security.types.map(securityType => securityType.name))].sort().join(", ")}</div>
</a>
{/each}
</div>
<p class="my-4 text-muted">
{#if Object.keys(issuer.stocks).length > 1}
{Object.keys(issuer.stocks).length} results
{:else}
{Object.keys(issuer.stocks).length} result
{/if}
</p>
<div class="list-group">
{#each Object.values(issuer.stocks) as stock (stock.id)}
<a class="list-group-item list-group-item-action" href="/stocks/{stock.id}">
<div>{(stock.name || "Titre sans nom").toUpperCase()}</div>
<div class="text-muted">{stock.share_type.name}</div>
<div class="text-muted">{[...new Set(stock.types.map(stockType => stockType.name))].sort().join(", ")}</div>
</a>
{/each}
</div>
<svelte:head> <svelte:head>
<title>{stock.name} | Stocks | Eurhisfirm</title> <title>{security.name} | Securities | Eurhisfirm</title>
</svelte:head> </svelte:head>
<main class="container-fluid"> <main class="container-fluid">
<h1> <h1>
<span class="text-muted">Stock</span> {stock.name} <span class="text-muted">Security</span> {security.name}
<small class="text-muted"> <small class="text-muted">
{stock.share_type.name} {security.share_type.name}
/ /
{[...new Set(stock.types.map(stockType => stockType.name))].sort().join(", ")} {[...new Set(security.types.map(securityType => securityType.name))].sort().join(", ")}
</small> </small>
</h1> </h1>
...@@ -32,35 +32,35 @@ ...@@ -32,35 +32,35 @@
<ul class="nav nav-tabs"> <ul class="nav nav-tabs">
<li class="nav-item"> <li class="nav-item">
{#if child.segment === undefined} {#if child.segment === undefined}
<a class="nav-link active" href="/stocks/{stock.id}" rel="prefetch">Summary <span class="sr-only">(current)</span></a> <a class="nav-link active" href="/securities/{security.id}" rel="prefetch">Summary <span class="sr-only">(current)</span></a>
{:else} {:else}
<a class="nav-link" href="/stocks/{stock.id}" rel="prefetch">Summary</a> <a class="nav-link" href="/securities/{security.id}" rel="prefetch">Summary</a>
{/if} {/if}
</li> </li>
<li class="nav-item"> <li class="nav-item">
{#if child.segment === "dividends"} {#if child.segment === "dividends"}
<a class="nav-link active" href="/stocks/{stock.id}/dividends" rel="prefetch">Dividends <span class="sr-only">(current)</span></a> <a class="nav-link active" href="/securities/{security.id}/dividends" rel="prefetch">Dividends <span class="sr-only">(current)</span></a>
{:else} {:else}
<a class="nav-link" href="/stocks/{stock.id}/dividends" rel="prefetch">Dividends</a> <a class="nav-link" href="/securities/{security.id}/dividends" rel="prefetch">Dividends</a>
{/if} {/if}
</li> </li>
<li class="nav-item"> <li class="nav-item">
{#if child.segment === "prices"} {#if child.segment === "prices"}
<a class="nav-link active" href="/stocks/{stock.id}/prices" rel="prefetch">Prices <span class="sr-only">(current)</span></a> <a class="nav-link active" href="/securities/{security.id}/prices" rel="prefetch">Prices <span class="sr-only">(current)</span></a>
{:else} {:else}
<a class="nav-link" href="/stocks/{stock.id}/prices" rel="prefetch">Prices</a> <a class="nav-link" href="/securities/{security.id}/prices" rel="prefetch">Prices</a>
{/if} {/if}
</li> </li>
</ul> </ul>
<svelte:component this={child.component} {...child.props} {stock} /> <svelte:component this={child.component} {...child.props} {security} />
</main> </main>
<script> <script>
export default { export default {
computed: { computed: {
simplifiedIssuers({ stock }) { simplifiedIssuers({ security }) {
const simplifiedIssuerByIdAndName = stock.issuers.reduce((accumulator, issuer) => { const simplifiedIssuerByIdAndName = security.issuers.reduce((accumulator, issuer) => {
accumulator[`${issuer.name} ${issuer.id}`] = { accumulator[`${issuer.name} ${issuer.id}`] = {
id: issuer.id, id: issuer.id,
name: issuer.name, name: issuer.name,
...@@ -71,8 +71,8 @@ ...@@ -71,8 +71,8 @@
}, },
}, },
async preload({ params /* , query */ }) { async preload({ params /* , query */ }) {
const { stock: stockId } = params const { security: securityId } = params
const response = await this.fetch(`/api/static/stocks/${stockId}`) const response = await this.fetch(`/api/static/securities/${securityId}`)
const result = const result =
response.ok || response.status === 400 response.ok || response.status === 400
? await response.json() ? await response.json()
...@@ -80,7 +80,7 @@ ...@@ -80,7 +80,7 @@
if (result.error) { if (result.error) {
return this.error(result.error.code, result.error.message) return this.error(result.error.code, result.error.message)
} }
return { stock: result } return { security: result }
}, },
} }
</script> </script>
\ No newline at end of file
<svelte:head> <svelte:head>
<title>Dividends | {stock.name} | Stocks | Eurhisfirm</title> <title>Dividends | {security.name} | Securities | Eurhisfirm</title>
</svelte:head> </svelte:head>
TODO TODO
{#each Object.values(stock.stock_exchanges || {}).sort(stockExchange => stockExchange.name) as stockExchange (`stock_exchange_${stockExchange.id}`)} {#each Object.values(security.stock_exchanges || {}).sort(stockExchange => stockExchange.name) as stockExchange (`stock_exchange_${stockExchange.id}`)}
<div class="card my-3"> <div class="card my-3">
<div class="card-header"> <div class="card-header">
Listed on <i>{stockExchange.name}</i> Listed on <i>{stockExchange.name}</i>
......
<svelte:head> <svelte:head>
<title>Prices | {stock.name} | Stocks | Eurhisfirm</title> <title>Prices | {security.name} | Securities | Eurhisfirm</title>
</svelte:head> </svelte:head>
<svelte:window on:resize="resize()"/> <svelte:window on:resize="resize()"/>
...@@ -112,8 +112,8 @@ ...@@ -112,8 +112,8 @@
) )
}, },
async preload({ params /* query */ }) { async preload({ params /* query */ }) {
const { stock: stockId } = params const { security: securityId } = params
const response = await this.fetch(`/api/stocks/${stockId}/prices`) const response = await this.fetch(`/api/securities/${securityId}/prices`)
const result = const result =
response.ok || response.status === 400 response.ok || response.status === 400
? await response.json() ? await response.json()
......
<svelte:head> <svelte:head>
<title>Prices | {stock.name} | Stocks | Eurhisfirm</title> <title>Prices | {security.name} | Securities | Eurhisfirm</title>