diff --git a/frontend/.env.development b/frontend/.env.development
new file mode 100644
index 0000000..8e79cb2
--- /dev/null
+++ b/frontend/.env.development
@@ -0,0 +1 @@
+VITE_SERVER_BASE_URL=http://127.0.0.1:3005
\ No newline at end of file
diff --git a/frontend/package.json b/frontend/package.json
index d71fd97..33d93c0 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -10,6 +10,7 @@
"@preact/signals": "^1.2.2",
"@trpc/client": "^10.45.0",
"chart.js": "^4.4.1",
+ "dotenv": "^16.4.1",
"preact": "^10.13.1",
"preact-iso": "^2.3.2",
"preact-render-to-string": "^6.3.1",
diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml
index e73e4ba..1785f4b 100644
--- a/frontend/pnpm-lock.yaml
+++ b/frontend/pnpm-lock.yaml
@@ -14,6 +14,9 @@ dependencies:
chart.js:
specifier: ^4.4.1
version: 4.4.1
+ dotenv:
+ specifier: ^16.4.1
+ version: 16.4.1
preact:
specifier: ^10.13.1
version: 10.19.3
@@ -724,6 +727,11 @@ packages:
domhandler: 5.0.3
dev: true
+ /dotenv@16.4.1:
+ resolution: {integrity: sha512-CjA3y+Dr3FyFDOAMnxZEGtnW9KBR2M0JvvUtXNW+dYJL5ROWxP9DUHCwgFqpMk0OXCc0ljhaNTr2w/kutYIcHQ==}
+ engines: {node: '>=12'}
+ dev: false
+
/electron-to-chromium@1.4.623:
resolution: {integrity: sha512-lKoz10iCYlP1WtRYdh5MvocQPWVRoI7ysp6qf18bmeBgR8abE6+I2CsfyNKztRDZvhdWc+krKT6wS7Neg8sw3A==}
dev: true
diff --git a/frontend/src/env.ts b/frontend/src/env.ts
new file mode 100644
index 0000000..428b1a9
--- /dev/null
+++ b/frontend/src/env.ts
@@ -0,0 +1,7 @@
+import dotenv from 'dotenv';
+
+if(process.env.NODE_DEV==="development"){
+ dotenv.config({ path:"../.env.development" });
+}
+
+export default null;
\ No newline at end of file
diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx
index f66fb47..0fa2b63 100644
--- a/frontend/src/index.tsx
+++ b/frontend/src/index.tsx
@@ -1,3 +1,4 @@
+import _ from './env';
import { render } from 'preact';
import { LocationProvider, Router, Route } from 'preact-iso';
diff --git a/frontend/src/pages/HistoricalCalendarPrices/HistoricalCalendarPrices.tsx b/frontend/src/pages/HistoricalCalendarPrices/HistoricalCalendarPrices.tsx
index d2ae7df..57bb858 100644
--- a/frontend/src/pages/HistoricalCalendarPrices/HistoricalCalendarPrices.tsx
+++ b/frontend/src/pages/HistoricalCalendarPrices/HistoricalCalendarPrices.tsx
@@ -32,12 +32,17 @@ const historicalCalendarQuoteChartData = signal([]);
const historicalCalendarExitQuoteChartData = signal([]);
+const chosenLookbackPeriodStart = signal("2022-01-01");
+const chosenLookbackPeriodEnd = signal("2024-01-01");
+
export function HistoricalCalendarPrices(){
const refreshHistoricalStockQuoteChartData = useCallback(()=>{
trpc.getHistoricalStockQuoteChartData
.query({
underlying:chosenUnderlying.value,
+ lookbackPeriodStart:chosenLookbackPeriodStart.value,
+ lookbackPeriodEnd:chosenLookbackPeriodEnd.value,
})
.then((getHistoricalStockQuoteChartDataResponse)=>{
historicalStockQuoteChartData.value = getHistoricalStockQuoteChartDataResponse;
@@ -51,6 +56,8 @@ export function HistoricalCalendarPrices(){
daysBetweenFrontAndBackExpiration:chosenDaysBetweenFrontAndBackExpiration.value,
strikePercentageFromUnderlyingPriceRangeMin:chosenStrikePercentageFromUnderlyingPrice.value - chosenStrikePercentageFromUnderlyingPriceRadius.value,
strikePercentageFromUnderlyingPriceRangeMax:chosenStrikePercentageFromUnderlyingPrice.value + chosenStrikePercentageFromUnderlyingPriceRadius.value,
+ lookbackPeriodStart:chosenLookbackPeriodStart.value,
+ lookbackPeriodEnd:chosenLookbackPeriodEnd.value,
})
.then((getHistoricalCalendarQuoteChartDataResponse)=>{
historicalCalendarQuoteChartData.value = getHistoricalCalendarQuoteChartDataResponse;
@@ -62,6 +69,8 @@ export function HistoricalCalendarPrices(){
underlying:chosenUnderlying.value,
daysToFrontExpiration:chosenExitToFrontExpiration.value,
daysBetweenFrontAndBackExpiration:chosenDaysBetweenFrontAndBackExpiration.value,
+ lookbackPeriodStart:chosenLookbackPeriodStart.value,
+ lookbackPeriodEnd:chosenLookbackPeriodEnd.value,
})
.then((getHistoricalCalendarExitQuoteChartDataResponse)=>{
historicalCalendarExitQuoteChartData.value = getHistoricalCalendarExitQuoteChartDataResponse;
@@ -106,6 +115,19 @@ export function HistoricalCalendarPrices(){
refreshHistoricalCalendarExitQuoteChartData();
},[]);
+ const handleLookbackPeriodStartChange = useCallback((e)=>{
+ chosenLookbackPeriodStart.value = e.target.value;
+ refreshHistoricalStockQuoteChartData();
+ refreshHistoricalCalendarQuoteChartData();
+ refreshHistoricalCalendarExitQuoteChartData();
+ },[]);
+ const handleLookbackPeriodEndChange = useCallback((e)=>{
+ chosenLookbackPeriodEnd.value = e.target.value;
+ refreshHistoricalStockQuoteChartData();
+ refreshHistoricalCalendarQuoteChartData();
+ refreshHistoricalCalendarExitQuoteChartData();
+ },[]);
+
useEffect(handleInit, []);
return (
@@ -145,6 +167,12 @@ export function HistoricalCalendarPrices(){
Days
+
+
+
+ -
+
+
{chosenUnderlying.value!==null && historicalStockQuoteChartData.value.length>0
?
diff --git a/server/.env.development b/server/.env.development
new file mode 100644
index 0000000..cca970c
--- /dev/null
+++ b/server/.env.development
@@ -0,0 +1,2 @@
+CLICKHOUSE_HOST=http://localhost:8123
+LISTEN_PORT=3005
\ No newline at end of file
diff --git a/server/package.json b/server/package.json
index d6716fe..0ffcf46 100644
--- a/server/package.json
+++ b/server/package.json
@@ -12,7 +12,8 @@
"@clickhouse/client": "^0.2.7",
"@sinclair/typebox": "^0.32.5",
"@trpc/server": "^10.45.0",
- "cors": "^2.8.5"
+ "cors": "^2.8.5",
+ "dotenv": "^16.4.1"
},
"devDependencies": {
"@types/cors": "^2.8.17",
diff --git a/server/pnpm-lock.yaml b/server/pnpm-lock.yaml
index 882e5ce..de42440 100644
--- a/server/pnpm-lock.yaml
+++ b/server/pnpm-lock.yaml
@@ -17,6 +17,9 @@ dependencies:
cors:
specifier: ^2.8.5
version: 2.8.5
+ dotenv:
+ specifier: ^16.4.1
+ version: 16.4.1
devDependencies:
'@types/cors':
@@ -386,6 +389,11 @@ packages:
object-keys: 1.1.1
dev: true
+ /dotenv@16.4.1:
+ resolution: {integrity: sha512-CjA3y+Dr3FyFDOAMnxZEGtnW9KBR2M0JvvUtXNW+dYJL5ROWxP9DUHCwgFqpMk0OXCc0ljhaNTr2w/kutYIcHQ==}
+ engines: {node: '>=12'}
+ dev: false
+
/error-ex@1.3.2:
resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
dependencies:
diff --git a/server/src/env.ts b/server/src/env.ts
new file mode 100644
index 0000000..428b1a9
--- /dev/null
+++ b/server/src/env.ts
@@ -0,0 +1,7 @@
+import dotenv from 'dotenv';
+
+if(process.env.NODE_DEV==="development"){
+ dotenv.config({ path:"../.env.development" });
+}
+
+export default null;
\ No newline at end of file
diff --git a/server/src/index.ts b/server/src/index.ts
index ebb00c1..131ba97 100644
--- a/server/src/index.ts
+++ b/server/src/index.ts
@@ -1,6 +1,7 @@
+import _ from './env';
import { publicProcedure, router } from './trpc.js';
import { query } from './clickhouse.js';
-import { createHTTPHandler, createHTTPServer } from '@trpc/server/adapters/standalone';
+import { createHTTPHandler } from '@trpc/server/adapters/standalone';
import cors from 'cors';
import { Object as ObjectT, String as StringT, TSchema, Number as NumberT } from '@sinclair/typebox';
import { TypeCompiler } from '@sinclair/typebox/compiler';
@@ -140,15 +141,19 @@ const appRouter = router({
getHistoricalStockQuoteChartData: publicProcedure
.input(RpcType(ObjectT({
underlying:StringT(),
+ lookbackPeriodStart:StringT(),
+ lookbackPeriodEnd:StringT(),
})))
.query(async (opts)=>{
- const {underlying, } = opts.input;
+ const { underlying, lookbackPeriodStart, lookbackPeriodEnd } = opts.input;
return (await query<[number,number]>(`
SELECT
toUnixTimestamp(tsStart) as x,
open as y
FROM stock_aggregates
WHERE symbol = '${underlying}'
+ AND tsStart >= '${lookbackPeriodStart} 00:00:00'
+ AND tsStart <= '${lookbackPeriodEnd} 00:00:00'
ORDER BY x ASC
`,'JSONEachRow'));
}),
@@ -159,9 +164,11 @@ const appRouter = router({
daysBetweenFrontAndBackExpiration:NumberT(),
strikePercentageFromUnderlyingPriceRangeMin:NumberT(),
strikePercentageFromUnderlyingPriceRangeMax:NumberT(),
+ lookbackPeriodStart:StringT(),
+ lookbackPeriodEnd:StringT(),
})))
.query(async (opts)=>{
- const {underlying, daysToFrontExpiration, daysBetweenFrontAndBackExpiration, strikePercentageFromUnderlyingPriceRangeMin, strikePercentageFromUnderlyingPriceRangeMax, } = opts.input;
+ const {underlying, daysToFrontExpiration, daysBetweenFrontAndBackExpiration, strikePercentageFromUnderlyingPriceRangeMin, strikePercentageFromUnderlyingPriceRangeMax, lookbackPeriodStart, lookbackPeriodEnd, } = opts.input;
return (await query<[number,number]>(`
SELECT
toUnixTimestamp(tsStart) as x,
@@ -172,6 +179,8 @@ const appRouter = router({
AND strikePercentageFromUnderlyingPrice >= ${strikePercentageFromUnderlyingPriceRangeMin}
AND strikePercentageFromUnderlyingPrice <= ${strikePercentageFromUnderlyingPriceRangeMax}
AND daysBetweenFrontAndBackExpiration = ${daysBetweenFrontAndBackExpiration}
+ AND tsStart >= '${lookbackPeriodStart} 00:00:00'
+ AND tsStart <= '${lookbackPeriodEnd} 00:00:00'
`,'JSONEachRow'));
}),
getHistoricalCalendarExitQuoteChartData: publicProcedure
@@ -179,9 +188,11 @@ const appRouter = router({
underlying:StringT(),
daysToFrontExpiration:NumberT(),
daysBetweenFrontAndBackExpiration:NumberT(),
+ lookbackPeriodStart:StringT(),
+ lookbackPeriodEnd:StringT(),
})))
.query(async (opts)=>{
- const {underlying, daysToFrontExpiration, daysBetweenFrontAndBackExpiration, } = opts.input;
+ const {underlying, daysToFrontExpiration, daysBetweenFrontAndBackExpiration, lookbackPeriodStart, lookbackPeriodEnd, } = opts.input;
return (await query<[number,number]>(`
SELECT
FLOOR(strikePercentageFromUnderlyingPrice, 1) as x,
@@ -192,6 +203,8 @@ const appRouter = router({
AND strikePercentageFromUnderlyingPrice >= -5.0
AND strikePercentageFromUnderlyingPrice <= 5.0
AND daysBetweenFrontAndBackExpiration = ${daysBetweenFrontAndBackExpiration}
+ AND tsStart >= '${lookbackPeriodStart} 00:00:00'
+ AND tsStart <= '${lookbackPeriodEnd} 00:00:00'
ORDER BY x ASC
`,'JSONEachRow'));
}),