Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions dal/stock-markets.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,15 @@ const predictedStockInfoSchema = new Schema(
market_name: String,
market_id: String,
stock_name: String,
ticker_id: String,
stock_id: String,
prediction_details: {
timestamp: Date,
date: Date,
volume: Number,
open: Number,
high: Number,
low: Number,
close: Number,
volume_traded: Number,
},
},
{ collection: 'PredictedStockInfo' }
Expand Down
116 changes: 96 additions & 20 deletions data/prediction.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,31 @@
const { realtimeStockInfo } = require('../dal/stock-markets');
const { predictedStockInfo } = require('../dal/stock-markets');
const { stockMarketInfo } = require('../dal/stock-markets');
const axios = require('axios');
const tickerToEndpointMap = {
AAPL: 'http://f6b1b502-ac55-4522-b0ef-f4becf1604a2.canadacentral.azurecontainer.io/score',
TWTR: '',
TXN: '',
FB: '',
GOOGL: '',
AMZN: '',
COST: '',
QCOM: '',
AVGO: '',
CSCO: '',
TSLA: '',
INTC: '',
CMCSA: '',
NFLX: '',
UBER: '',
PEP: '',
ADBE: 'http://15d1cdd8-a814-4b62-90ee-de15fc6d6225.eastus2.azurecontainer.io/score',
MSFT: 'http://08478e4a-bbc7-4e7b-bb07-38f4792fea4b.eastus2.azurecontainer.io/score',
PYPL: '',
NVDA: '',
};

const number_of_days = [1, 3, 6];
const numOfDays = [1, 3, 6];

const predictPrices = async () => {
const doc = await stockMarketInfo.find({});
Expand All @@ -13,7 +36,7 @@ const predictPrices = async () => {
ticker_id: stock_data.ticker,
});

get_dependent_variables(stock_data.ticker)
getDependentVariables(stock_data.ticker)
.then(async (dependent_variable_list) => {
if (stockPredictionInfo) {
await predictedStockInfo.updateOne(
Expand Down Expand Up @@ -47,35 +70,88 @@ const predictPrices = async () => {
}
};

const get_dependent_variables = async (ticker) => {
// get Date, Volume, Open, High, Low, values from database and fluctuate their values
const getDependentVariables = async (ticker) => {
const {
stock_details: { timestamp, open, close, high, low, volume },
stock_details: { timestamp, volume, open, high, low },
} = await realtimeStockInfo.findOne({ ticker_id: ticker });
console.log(timestamp, open, high, low, volume);
const new_open = open + open * 0.05;
const new_high = high + high * 0.05;
const new_low = low + low * 0.05;
const new_volume = volume + volume * 0.05;
const new_close = close + close * 0.05;

const res = [];

for (let days of number_of_days) {
for (let days of numOfDays) {
const date = new Date(timestamp);
const new_date = new Date(date.setDate(date.getDate() + days));
const new_time = new Date(new_date.setUTCHours(0));
let newDate = new Date(date.setDate(date.getDate() + days));
let currentDay = newDate.getDay();
let addDays = 0;

// if date is weekend, set date to Monday since no predictions available for weekends
if (currentDay == 5) {
// saturday
addDays = 2;
} else if (currentDay == 6) {
// sunday
addDays = 1;
}

newDate.setDate(newDate.getDate() + addDays);
const newDateWithTime = new Date(newDate.setUTCHours(0));

// randomize dependent variables
const randomPercent = (Math.random() * 5 + 1) * 0.01;
const new_volume = volume + volume * randomPercent;
const new_open = open + open * randomPercent;
const new_high = high + high * randomPercent;
const new_low = low + low * randomPercent;

res.push({
timestamp: new_time,
open: new_open,
close: new_close,
high: new_high,
low: new_low,
volume: new_volume * 1000,
Date: newDateWithTime,
Volume: Math.round(new_volume),
Open: roundToTwoDecimals(new_open),
High: roundToTwoDecimals(new_high),
Low: roundToTwoDecimals(new_low),
});
}

return res;
return getPredictionScoreFromAPI(res, ticker);
};

// Returns a list of updated prediction_details with prediction scores from Azure AutoML endpoint
const getPredictionScoreFromAPI = async (dependentVariableList, ticker) => {
let scoreURI = '';
for (const [key, value] of Object.entries(tickerToEndpointMap)) {
if (ticker === key) scoreURI = value;
}

const data = {
data: dependentVariableList,
};

if (scoreURI !== '') {
let scoreRes = await axios.post(scoreURI, JSON.stringify(data), {
headers: { 'Content-Type': 'application/json' },
});
let score = scoreRes.data.replace('NaN', 0.0); // having NaN in JSON throws error
const scoreObj = JSON.parse(score);
const scoreList = scoreObj['forecast'];
let count = 0;
dependentVariableList.forEach(function (element) {
if (isNaN(scoreList[count])) {
element.Close = 0.0;
} else {
element.Close = roundToTwoDecimals(scoreList[count]);
}
count += 1;
});
} else {
console.log('Score URI is an empty string');
}
const newList = [...dependentVariableList]; // create new list of prediction_details to return
return newList;
};

// Rounds input to two decimal places
const roundToTwoDecimals = (num) => {
return +(Math.round(num + 'e+2') + 'e-2');
};

predictPrices().then((_) => {
Expand Down
4 changes: 4 additions & 0 deletions data/stock-market.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ const MARKET_DATA = [
ticker: 'AAPL',
name: 'Apple',
},
{
ticker: 'AAPL',
name: 'Apple',
},
],
},
];
Expand Down
63 changes: 29 additions & 34 deletions src/components/StockDetails/StockPredictionDetails.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,11 @@ const PricePrediction = () => {
const formatDate = useDateFormat();
const redColor = useColorModeValue('red.light', 'red.dark');
const greenColor = useColorModeValue('green.light', 'green.dark');

return (
<CustomGridItem>
<VStack spacing={4}>
<Heading as="h3" size="lg" p={8} textAlign="center">
Prediction
Prediction of Closing Prices
</Heading>
<CustomBox
p={4}
Expand All @@ -54,40 +53,36 @@ const PricePrediction = () => {
>
<VStack spacing={4}>
{prediction_details
? prediction_details.map(
({ close, timestamp, _id }) => (
<Box
key={_id}
p={4}
w="100%"
borderRadius="lg"
? prediction_details.map(({ Close, Date, _id }) => (
<Box
key={_id}
p={4}
w="100%"
borderRadius="lg"
>
<SimpleGrid
columns={{ base: 1, lg: 2 }}
spacing={1}
>
<SimpleGrid
columns={{ base: 1, lg: 2 }}
spacing={1}
>
<Center>
<Heading as="h4" size="md">
{formatDate(timestamp)}
</Heading>
</Center>
<Heading
as="h3"
size="lg"
color={
close >= 0
? greenColor
: redColor
}
>
$
{close?.toFixed(2) ??
' --.--'}
<Center>
<Heading as="h4" size="md">
{formatDate(Date)}
</Heading>
</SimpleGrid>
</Box>
)
)
</Center>
<Heading
as="h3"
size="lg"
color={
Close >= 0
? greenColor
: redColor
}
>
${Close?.toFixed(2) ?? ' --.--'}
</Heading>
</SimpleGrid>
</Box>
))
: null}
</VStack>
</CustomBox>
Expand Down
6 changes: 3 additions & 3 deletions src/hooks/useDateFormat.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ const useDateFormat = () => (date) => {
if (date) {
let year = parseInt(date.slice(0, 4));
let month = parseInt(date.slice(6, 7));
let day = parseInt(date.slice(9, 10));
let day = parseInt(date.slice(8, 10));
let dateObj = new Date(year, month - 1, day);
let options = { year: 'numeric', month: 'long', day: '2-digit' };

let options = {year: 'numeric', month: 'long', day: '2-digit'};
return new Intl.DateTimeFormat('en-US', options).format(dateObj);
} else {
return null
return null;
}
};

Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -12353,6 +12353,11 @@ simple-swizzle@^0.2.2:
dependencies:
is-arrayish "^0.3.1"

simplejson@^0.0.2:
version "0.0.2"
resolved "https://registry.yarnpkg.com/simplejson/-/simplejson-0.0.2.tgz#9e3d9875aecec49565028cd9278b2a1ac6bcaaef"
integrity sha1-nj2Yda7OxJVlAozZJ4sqGsa8qu8=

sisteransi@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed"
Expand Down