├── .gitignore ├── v2 ├── backend │ ├── Procfile │ ├── .env.sample │ ├── models │ │ ├── mongoose-setup.js │ │ ├── model.js │ │ └── user.js │ ├── middleware │ │ └── authenticate.js │ ├── package.json │ ├── app.js │ ├── routes │ │ ├── userRoutes.js │ │ └── routes.js │ ├── assets │ │ ├── symbols.txt │ │ └── symbols.json │ └── yarn.lock ├── src │ ├── react-app-env.d.ts │ ├── assets │ │ ├── live.png │ │ ├── mail.png │ │ ├── avatar.png │ │ ├── closed.png │ │ ├── locked.png │ │ ├── search.png │ │ ├── arrow-up.png │ │ ├── favicon.png │ │ ├── padlock.png │ │ ├── closed (1).png │ │ ├── github-logo.png │ │ ├── street-name.png │ │ └── arrow-pointing-down.png │ ├── .env │ ├── actions │ │ ├── DeleteCompany.tsx │ │ ├── Sell.tsx │ │ ├── Buy.tsx │ │ ├── SetMoney.tsx │ │ ├── FetchSymbols.tsx │ │ ├── Refresh.tsx │ │ └── Addcompany.tsx │ ├── components │ │ ├── LoadingPage.tsx │ │ ├── clock.tsx │ │ ├── LogOut.tsx │ │ ├── StockAreaChart.tsx │ │ ├── AutoCompleteInput.tsx │ │ ├── Leaderboard.tsx │ │ ├── Assets.tsx │ │ ├── LogIn.tsx │ │ ├── SellButton.tsx │ │ ├── Home.tsx │ │ ├── Header.tsx │ │ ├── Signup.tsx │ │ ├── Buy.tsx │ │ └── View.tsx │ ├── router │ │ ├── PublicRouter.tsx │ │ ├── PrivateRouter.tsx │ │ └── Approuter.tsx │ ├── reducers │ │ ├── Symbols.tsx │ │ ├── Portfolio.tsx │ │ └── Money.tsx │ ├── index.tsx │ ├── reduxStore │ │ └── store.tsx │ ├── App.tsx │ ├── styles │ │ ├── reset.css │ │ └── main.css │ ├── utils │ │ └── utils.tsx │ └── serviceWorker.ts ├── public │ ├── favicon.ico │ ├── favicon.png │ ├── manifest.json │ └── index.html ├── .gitignore ├── tsconfig.json ├── package.json ├── README.md └── package-lock.json ├── .netlify └── state.json ├── v1 ├── src │ ├── styles │ │ ├── components │ │ │ ├── _table.scss │ │ │ ├── _container.scss │ │ │ ├── _navbar.scss │ │ │ ├── _jumbotron.scss │ │ │ └── _input.scss │ │ ├── base │ │ │ ├── _settings.scss │ │ │ └── _base.scss │ │ └── styles.scss │ ├── Actions │ │ ├── Refresh.js │ │ ├── BuyAction.js │ │ ├── SellAction.js │ │ ├── DeleteCompany.js │ │ └── AddCompany.js │ ├── components │ │ ├── NotFoundPage.js │ │ ├── GraphPage.js │ │ ├── DashboardPage.js │ │ ├── Header.js │ │ ├── Piechart.js │ │ ├── BuyPage.js │ │ └── Table.js │ ├── app.js │ ├── reduxStore │ │ └── store.js │ ├── Reducer │ │ ├── Money.js │ │ └── Portfolio.js │ └── router │ │ └── Approuter.js ├── public │ └── images │ │ ├── Input.png │ │ ├── logo.png │ │ ├── favicon.png │ │ ├── GraphPage.png │ │ └── mainScreen.png ├── README.md ├── webpack.config.js ├── LICENSE └── package.json ├── Wall street ss.PNG └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /v1/playground 2 | -------------------------------------------------------------------------------- /v2/backend/Procfile: -------------------------------------------------------------------------------- 1 | web: yarn start -------------------------------------------------------------------------------- /v2/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /.netlify/state.json: -------------------------------------------------------------------------------- 1 | { 2 | "siteId": "6ca59a8c-e83a-4adb-a4b4-972745ba6de3" 3 | } -------------------------------------------------------------------------------- /v1/src/styles/components/_table.scss: -------------------------------------------------------------------------------- 1 | .-striped { 2 | background: blue; 3 | } 4 | -------------------------------------------------------------------------------- /v1/src/styles/components/_container.scss: -------------------------------------------------------------------------------- 1 | .rt-td { 2 | text-align: center; 3 | } 4 | -------------------------------------------------------------------------------- /Wall street ss.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jigar3/Wall-Street/HEAD/Wall street ss.PNG -------------------------------------------------------------------------------- /v2/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jigar3/Wall-Street/HEAD/v2/public/favicon.ico -------------------------------------------------------------------------------- /v2/public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jigar3/Wall-Street/HEAD/v2/public/favicon.png -------------------------------------------------------------------------------- /v2/src/assets/live.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jigar3/Wall-Street/HEAD/v2/src/assets/live.png -------------------------------------------------------------------------------- /v2/src/assets/mail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jigar3/Wall-Street/HEAD/v2/src/assets/mail.png -------------------------------------------------------------------------------- /v2/backend/.env.sample: -------------------------------------------------------------------------------- 1 | USERNAME= 2 | PASSWORD= 3 | SALT= 4 | -------------------------------------------------------------------------------- /v2/src/assets/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jigar3/Wall-Street/HEAD/v2/src/assets/avatar.png -------------------------------------------------------------------------------- /v2/src/assets/closed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jigar3/Wall-Street/HEAD/v2/src/assets/closed.png -------------------------------------------------------------------------------- /v2/src/assets/locked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jigar3/Wall-Street/HEAD/v2/src/assets/locked.png -------------------------------------------------------------------------------- /v2/src/assets/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jigar3/Wall-Street/HEAD/v2/src/assets/search.png -------------------------------------------------------------------------------- /v1/public/images/Input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jigar3/Wall-Street/HEAD/v1/public/images/Input.png -------------------------------------------------------------------------------- /v1/public/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jigar3/Wall-Street/HEAD/v1/public/images/logo.png -------------------------------------------------------------------------------- /v2/src/assets/arrow-up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jigar3/Wall-Street/HEAD/v2/src/assets/arrow-up.png -------------------------------------------------------------------------------- /v2/src/assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jigar3/Wall-Street/HEAD/v2/src/assets/favicon.png -------------------------------------------------------------------------------- /v2/src/assets/padlock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jigar3/Wall-Street/HEAD/v2/src/assets/padlock.png -------------------------------------------------------------------------------- /v1/public/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jigar3/Wall-Street/HEAD/v1/public/images/favicon.png -------------------------------------------------------------------------------- /v2/src/.env: -------------------------------------------------------------------------------- 1 | REACT_APP_BACKEND_URL=http://localhost:3001 2 | REACT_APP_API_URL=https://api.iextrading.com/1.0/stock -------------------------------------------------------------------------------- /v2/src/assets/closed (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jigar3/Wall-Street/HEAD/v2/src/assets/closed (1).png -------------------------------------------------------------------------------- /v2/src/assets/github-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jigar3/Wall-Street/HEAD/v2/src/assets/github-logo.png -------------------------------------------------------------------------------- /v2/src/assets/street-name.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jigar3/Wall-Street/HEAD/v2/src/assets/street-name.png -------------------------------------------------------------------------------- /v1/public/images/GraphPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jigar3/Wall-Street/HEAD/v1/public/images/GraphPage.png -------------------------------------------------------------------------------- /v1/public/images/mainScreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jigar3/Wall-Street/HEAD/v1/public/images/mainScreen.png -------------------------------------------------------------------------------- /v2/src/assets/arrow-pointing-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jigar3/Wall-Street/HEAD/v2/src/assets/arrow-pointing-down.png -------------------------------------------------------------------------------- /v1/src/Actions/Refresh.js: -------------------------------------------------------------------------------- 1 | const Refresh = () => { 2 | return { 3 | type: "REFRESH" 4 | }; 5 | }; 6 | 7 | export default Refresh; 8 | -------------------------------------------------------------------------------- /v2/src/actions/DeleteCompany.tsx: -------------------------------------------------------------------------------- 1 | export default (id) => { 2 | return { 3 | type: "DELETE", 4 | payload: id, 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /v2/src/actions/Sell.tsx: -------------------------------------------------------------------------------- 1 | export default (sellValue) => { 2 | return { 3 | type: "SELL", 4 | payload: sellValue 5 | }; 6 | }; -------------------------------------------------------------------------------- /v2/src/actions/Buy.tsx: -------------------------------------------------------------------------------- 1 | export default (buyValue: number) => { 2 | return { 3 | type: "BUY", 4 | payload: buyValue 5 | }; 6 | }; -------------------------------------------------------------------------------- /v2/src/actions/SetMoney.tsx: -------------------------------------------------------------------------------- 1 | export default (money: number) => { 2 | return { 3 | type: "SET", 4 | payload: money 5 | }; 6 | }; -------------------------------------------------------------------------------- /v2/src/components/LoadingPage.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | export default () => ( 4 |
5 | Loading.... 6 |
7 | ) -------------------------------------------------------------------------------- /v2/src/actions/FetchSymbols.tsx: -------------------------------------------------------------------------------- 1 | export default (symbols: any) => { 2 | return { 3 | type: "SET_SYMBOL", 4 | payload: symbols 5 | }; 6 | }; -------------------------------------------------------------------------------- /v1/src/styles/base/_settings.scss: -------------------------------------------------------------------------------- 1 | // Spacing 2 | $s-size: 1.2rem; 3 | $m-size: 1.6rem; 4 | $l-size: 2.3rem; 5 | $xl-size: 4.8rem; 6 | $desktop-breakpoint: 45rem; -------------------------------------------------------------------------------- /v1/src/Actions/BuyAction.js: -------------------------------------------------------------------------------- 1 | const BuyAction = (buyValue) => { 2 | return { 3 | type: "BUY", 4 | payload: buyValue 5 | } 6 | } 7 | 8 | export default BuyAction; -------------------------------------------------------------------------------- /v1/src/Actions/SellAction.js: -------------------------------------------------------------------------------- 1 | const SellAction = (sellValue) => { 2 | return { 3 | type: "SELL", 4 | payload: sellValue 5 | } 6 | } 7 | 8 | export default SellAction; -------------------------------------------------------------------------------- /v1/src/Actions/DeleteCompany.js: -------------------------------------------------------------------------------- 1 | const DeleteCompany = ( index = 0 ) => { 2 | return { 3 | type: "DELETE", 4 | payLoad: index, 5 | } 6 | } 7 | 8 | export default DeleteCompany; -------------------------------------------------------------------------------- /v1/src/components/NotFoundPage.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const NotFoundPage = () => ( 4 |
5 |

Page Not Found

6 |
7 | ); 8 | 9 | export default NotFoundPage; 10 | -------------------------------------------------------------------------------- /v1/src/styles/components/_navbar.scss: -------------------------------------------------------------------------------- 1 | .nav-item { 2 | padding: 0 25px 0 25px; 3 | } 4 | 5 | .navbar { 6 | border-bottom: 2px #4682b4 solid; 7 | } 8 | 9 | .navbar-brand { 10 | padding-left: 15px; 11 | } 12 | -------------------------------------------------------------------------------- /v2/src/actions/Refresh.tsx: -------------------------------------------------------------------------------- 1 | export default ({id, companyDetails}) => { 2 | return { 3 | type: "REFRESH", 4 | payload: { 5 | id, 6 | companyDetails 7 | } 8 | }; 9 | }; -------------------------------------------------------------------------------- /v1/src/components/GraphPage.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PieChart from "./Piechart"; 3 | 4 | const GraphPage = () => ( 5 |
6 | 7 |
8 | ); 9 | 10 | export default GraphPage; 11 | -------------------------------------------------------------------------------- /v1/src/styles/styles.scss: -------------------------------------------------------------------------------- 1 | @import "./base/settings"; 2 | @import "./base/base"; 3 | 4 | @import "./components/container"; 5 | @import "./components/navbar"; 6 | @import "./components/jumbotron"; 7 | @import "./components/input"; 8 | -------------------------------------------------------------------------------- /v1/src/styles/components/_jumbotron.scss: -------------------------------------------------------------------------------- 1 | .jumbotron { 2 | background: #00bfff; 3 | color: white; 4 | border-bottom: 2px #4682b4 solid; 5 | display: flex; 6 | justify-content: space-between; 7 | } 8 | 9 | .btn-refresh { 10 | font-size: 24px; 11 | padding: 14px; 12 | } 13 | -------------------------------------------------------------------------------- /v1/src/styles/components/_input.scss: -------------------------------------------------------------------------------- 1 | .col-form-label { 2 | font-size: 32px; 3 | } 4 | 5 | .btn-block { 6 | font-size: 36px; 7 | padding: 10px; 8 | border-bottom: 4px #4682b4 solid; 9 | position: relative; 10 | top: 4rem; 11 | } 12 | 13 | .custom-container { 14 | width: 40%; 15 | position: relative; 16 | top: 20rem; 17 | } 18 | -------------------------------------------------------------------------------- /v2/src/components/clock.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Clock from 'react-live-clock'; 3 | 4 | export default class LiveClock extends React.Component { 5 | render() { 6 | return( 7 |
8 | IST   9 | 10 |
11 | ) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /v2/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /v2/src/router/PublicRouter.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Route, Redirect } from 'react-router-dom'; 3 | 4 | export default ({component: Component, ...rest}) => ( 5 | ( 6 | sessionStorage.getItem("User_ID") ? ( 7 | 8 | ) : ( 9 | 10 | ) 11 | )} /> 12 | ); -------------------------------------------------------------------------------- /v1/src/styles/base/_base.scss: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | html { 5 | font-size: 62.5%; 6 | } 7 | 8 | body { 9 | font-family: Helvetica, Arial, sans-serif; 10 | font-size: $m-size; 11 | } 12 | 13 | button { 14 | cursor: pointer; 15 | } 16 | 17 | button:disabled { 18 | cursor: default; 19 | } 20 | 21 | .selected { 22 | color: Blue; 23 | font-weight: bold; 24 | } 25 | -------------------------------------------------------------------------------- /v2/src/reducers/Symbols.tsx: -------------------------------------------------------------------------------- 1 | const symbols = [] 2 | 3 | interface Action { 4 | type: string, 5 | payload: any 6 | } 7 | 8 | export default (state: any = symbols, action: Action) => { 9 | switch(action.type) { 10 | case "GET": 11 | return state 12 | 13 | case "SET_SYMBOL": 14 | return state.concat(action.payload) 15 | 16 | default: 17 | return state 18 | } 19 | } -------------------------------------------------------------------------------- /v2/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /backend/node_modules 6 | /backend/.env 7 | /.pnp 8 | .pnp.js 9 | 10 | # testing 11 | /coverage 12 | 13 | # production 14 | /build 15 | 16 | # misc 17 | .DS_Store 18 | .env.local 19 | .env.development.local 20 | .env.test.local 21 | .env.production.local 22 | 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | -------------------------------------------------------------------------------- /v2/backend/models/mongoose-setup.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose") 2 | require('dotenv').config() 3 | 4 | // Local Database 5 | const url = "mongodb://localhost:27017/wall-street" 6 | 7 | // Mlab Database 8 | // const url = `mongodb://${process.env.USERNAME}:${process.env.PASSWORD}@ds225308.mlab.com:25308/wall-street` 9 | 10 | mongoose.connect(url, { useNewUrlParser: true, useCreateIndex: true }).then(() => { 11 | console.log("Connected to DB") 12 | }) 13 | 14 | module.exports = {mongoose} -------------------------------------------------------------------------------- /v2/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | import * as serviceWorker from './serviceWorker'; 5 | // import "./styles/reset.css" 6 | 7 | ReactDOM.render(, document.getElementById('root')); 8 | 9 | // If you want your app to work offline and load faster, you can change 10 | // unregister() to register() below. Note this comes with some pitfalls. 11 | // Learn more about service workers: http://bit.ly/CRA-PWA 12 | serviceWorker.unregister(); 13 | -------------------------------------------------------------------------------- /v2/backend/middleware/authenticate.js: -------------------------------------------------------------------------------- 1 | let { User } = require('../models/user'); 2 | 3 | let authenticate = (req, res, next) => { 4 | let token = req.header('x-auth'); 5 | 6 | User.findByToken(token).then((user) => { 7 | if (!user) { 8 | return Promise.reject(); 9 | } 10 | 11 | req.user = user; 12 | req.token = token; 13 | next(); 14 | }).catch((e) => { 15 | res.status(401).send(); 16 | }); 17 | }; 18 | 19 | module.exports = { authenticate }; 20 | -------------------------------------------------------------------------------- /v1/README.md: -------------------------------------------------------------------------------- 1 | # Wall-Street ![](./public/images/favicon.png "Wall-Street") 2 | 3 | This is a Virtual Trader built using React. 4 | 5 | Here are some screenshots => 6 | 7 | ## DashBoard 8 | 9 | ![](./public/images/mainScreen.png "DashBoard") 10 | 11 | ## Buy Page 12 | 13 | ![](./public/images/Input.png "Buy Page") 14 | 15 | ## Graph Page 16 | 17 | ![](./public/images/GraphPage.png "Graph Page") 18 | 19 | To Develop Locally => 20 | 21 | ``` 22 | yarn run dev-server 23 | ``` 24 | 25 | Built With :heartbeat: by Jigar Chavada 26 | -------------------------------------------------------------------------------- /v1/src/app.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import { Provider } from "react-redux"; 4 | 5 | import store from "./reduxStore/store"; 6 | import AppRouter from "./router/Approuter"; 7 | 8 | import "./styles/styles.scss"; 9 | import "../node_modules/normalize.css"; 10 | 11 | const App = () => ( 12 | 13 |
14 | 15 |
16 |
17 | ); 18 | 19 | ReactDOM.render(, document.getElementById("root")); 20 | -------------------------------------------------------------------------------- /v2/src/reduxStore/store.tsx: -------------------------------------------------------------------------------- 1 | import { createStore, combineReducers } from "redux"; 2 | 3 | import Portfolio from "../reducers/Portfolio"; 4 | import Money from "../reducers/Money"; 5 | import Symbols from "../reducers/Symbols"; 6 | 7 | const store = createStore( 8 | combineReducers({ 9 | portfolio: Portfolio, 10 | money: Money, 11 | symbol: Symbols 12 | }), 13 | (window as any).__REDUX_DEVTOOLS_EXTENSION__ && (window as any).__REDUX_DEVTOOLS_EXTENSION__() 14 | ); 15 | 16 | export default store; 17 | 18 | -------------------------------------------------------------------------------- /v2/src/router/PrivateRouter.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Route, Redirect } from 'react-router-dom'; 3 | 4 | import Header from "../components/Header" 5 | 6 | export default ({component: Component, ...rest}) => ( 7 | ( 8 | sessionStorage.getItem("User_ID") ? ( 9 |
10 |
11 | 12 |
13 | ) : ( 14 | 15 | ) 16 | )} /> 17 | ); -------------------------------------------------------------------------------- /v1/src/reduxStore/store.js: -------------------------------------------------------------------------------- 1 | import { createStore, combineReducers, applyMiddleware } from 'redux'; 2 | import thunk from 'redux-thunk'; 3 | import Portfolio from '../Reducer/Portfolio'; 4 | import Money from '../Reducer/Money'; 5 | 6 | const store = createStore( 7 | combineReducers({ 8 | portfolio: Portfolio, 9 | money: Money 10 | }), 11 | window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() 12 | ); 13 | 14 | 15 | // store.dispatch(SampleAction()) 16 | // console.log(store.getState()) 17 | export default store; -------------------------------------------------------------------------------- /v2/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "allowJs": true, 5 | "skipLibCheck": false, 6 | "esModuleInterop": true, 7 | "allowSyntheticDefaultImports": true, 8 | "strict": false, 9 | "forceConsistentCasingInFileNames": true, 10 | "module": "esnext", 11 | "moduleResolution": "node", 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "noEmit": true, 15 | "jsx": "preserve", 16 | "lib": [ "es2015", "dom"], 17 | }, 18 | "include": [ 19 | "src" 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /v1/src/Actions/AddCompany.js: -------------------------------------------------------------------------------- 1 | const AddCompany = ( companyDetail = {} ) => { 2 | const { 3 | company = '', 4 | quantity = 0, 5 | buyPrice = 0, 6 | currPrice = 0, 7 | shareWorth = 0, 8 | profitLoss = 0, 9 | } = companyDetail; 10 | 11 | return { 12 | type: "ADD", 13 | payLoad: { 14 | company, 15 | quantity, 16 | buyPrice, 17 | currPrice, 18 | shareWorth, 19 | profitLoss, 20 | } 21 | } 22 | } 23 | 24 | export default AddCompany; -------------------------------------------------------------------------------- /v1/src/Reducer/Money.js: -------------------------------------------------------------------------------- 1 | const as = require("as-type"); 2 | 3 | const money = { 4 | money: 10000 5 | }; 6 | 7 | const Money = (state = money, action) => { 8 | switch (action.type) { 9 | case "BUY": 10 | return { 11 | money: 12 | as.float(state.money).toFixed(2) - as.float(action.payload).toFixed(2) 13 | }; 14 | 15 | case "SELL": 16 | return { 17 | money: (as.float(state.money) + as.float(action.payload)).toFixed(2) 18 | }; 19 | 20 | default: 21 | return state; 22 | } 23 | }; 24 | 25 | export default Money; 26 | -------------------------------------------------------------------------------- /v2/backend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "backend", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "scripts": { 7 | "start": "node app.js", 8 | "start:dev": "nodemon app.js" 9 | }, 10 | "dependencies": { 11 | "axios": "^0.18.0", 12 | "bcryptjs": "^2.4.3", 13 | "body-parser": "^1.18.3", 14 | "cheerio": "^1.0.0-rc.2", 15 | "dotenv": "^6.2.0", 16 | "express": "^4.16.4", 17 | "jsonwebtoken": "^8.4.0", 18 | "lodash": "^4.17.11", 19 | "mongoose": "^5.4.1", 20 | "mongoose-unique-validator": "^2.0.2", 21 | "validator": "^10.10.0" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /v2/src/App.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Provider } from "react-redux"; 3 | 4 | import store from "./reduxStore/store"; 5 | import AppRouter from "./router/Approuter"; 6 | import { getInitialValue } from "./utils/utils" 7 | 8 | class App extends React.Component { 9 | 10 | state = { 11 | once: false 12 | } 13 | 14 | componentDidMount() { 15 | this.handleOnce() 16 | } 17 | 18 | handleOnce = () => { 19 | if(!this.state.once) { 20 | getInitialValue() 21 | this.setState({once: true}) 22 | } 23 | } 24 | 25 | render() { 26 | return ( 27 | 28 | 29 | 30 | ) 31 | } 32 | } 33 | 34 | export { 35 | App as default 36 | } 37 | 38 | -------------------------------------------------------------------------------- /v1/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | // entry: './playground/stock', 5 | entry: './src/app', 6 | output: { 7 | path: path.join(__dirname, 'public'), 8 | filename: 'bundle.js' 9 | }, 10 | module: { 11 | rules: [{ 12 | loader: 'babel-loader', 13 | test: /\.js$/, 14 | exclude: /node_modules/ 15 | }, { 16 | test: /\.s?css$/, 17 | use: [ 18 | 'style-loader', 19 | 'css-loader', 20 | 'sass-loader' 21 | ] 22 | }] 23 | }, 24 | devtool: 'cheap-module-eval-source-map', 25 | devServer: { 26 | contentBase: path.join(__dirname, 'public'), 27 | historyApiFallback: true, 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /v2/src/components/LogOut.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import axios from "axios"; 3 | 4 | import { history } from "../router/Approuter"; 5 | 6 | export default class LogOut extends React.Component { 7 | 8 | handleClick = () => { 9 | axios.delete(`${process.env.REACT_APP_BACKEND_URL}/users/logout`, {headers: { 10 | "x-auth": sessionStorage.getItem("JWT_Token") 11 | }}).then(() => { 12 | sessionStorage.removeItem("JWT_Token") 13 | sessionStorage.removeItem("User_ID") 14 | sessionStorage.removeItem("name") 15 | sessionStorage.removeItem("status") 16 | history.push("/login") 17 | }) 18 | } 19 | 20 | render() { 21 | return ( 22 | 25 | ) 26 | } 27 | } -------------------------------------------------------------------------------- /v1/src/router/Approuter.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Switch, Route } from "react-router-dom"; 3 | import { BrowserRouter as Router, NavLink } from "react-router-dom"; 4 | 5 | import Header from "../components/Header"; 6 | import DashboardPage from "../components/DashboardPage"; 7 | import BuyPage from "../components/BuyPage"; 8 | import NotFoundPage from "../components/NotFoundPage"; 9 | import GraphPage from "../components/GraphPage"; 10 | 11 | const Approuter = () => ( 12 | 13 |
14 |
15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 |
24 |
25 | ); 26 | 27 | export default Approuter; 28 | -------------------------------------------------------------------------------- /v2/src/actions/Addcompany.tsx: -------------------------------------------------------------------------------- 1 | import uuidv4 from 'uuid/v4' 2 | 3 | interface CompanyDetail { 4 | _id: string, 5 | companyName: string, 6 | company: string, 7 | quantity: number, 8 | buyPrice: number, 9 | currPrice: number, 10 | shareWorth: number, 11 | profitLoss: number 12 | } 13 | 14 | export default (companyDetail: CompanyDetail) => { 15 | const { 16 | _id = '', 17 | company = '', 18 | companyName = '', 19 | quantity = 0, 20 | buyPrice = 0, 21 | currPrice = 0, 22 | shareWorth = 0, 23 | profitLoss = 0, 24 | } = companyDetail; 25 | 26 | return { 27 | type: "ADD", 28 | payload: { 29 | _id, 30 | company, 31 | companyName, 32 | quantity, 33 | buyPrice, 34 | currPrice, 35 | shareWorth, 36 | profitLoss 37 | } 38 | }; 39 | }; -------------------------------------------------------------------------------- /v2/src/reducers/Portfolio.tsx: -------------------------------------------------------------------------------- 1 | const portfolio = [] 2 | 3 | interface Action { 4 | type: string, 5 | payload: any 6 | } 7 | 8 | export default (state: any = portfolio, action: Action) => { 9 | switch(action.type) { 10 | case "ADD": 11 | if(!state.includes(action.payload)) { 12 | return state.concat(action.payload); 13 | } 14 | return state 15 | 16 | case "DELETE": 17 | return state.filter(item => item._id !== action.payload); 18 | 19 | case "REFRESH": 20 | return state.map((item) => { 21 | if(item._id !== action.payload.id) { 22 | return item; 23 | } 24 | 25 | return { 26 | ...item, 27 | ...action.payload.companyDetails 28 | } 29 | }) 30 | 31 | default: 32 | return state; 33 | }; 34 | }; -------------------------------------------------------------------------------- /v1/src/Reducer/Portfolio.js: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | 3 | const portfolio = []; 4 | 5 | const Portfolio = (state = portfolio, action) => { 6 | switch (action.type) { 7 | case "ADD": 8 | return state.concat(action.payLoad); 9 | 10 | case "DELETE": 11 | return state.filter(item => state.indexOf(item) !== action.payLoad); 12 | 13 | case "REFRESH": 14 | state.forEach(childState => { 15 | const symbol = childState.company; 16 | axios 17 | .get( 18 | `https://api.iextrading.com/1.0/stock/${symbol}/batch?types=quote` 19 | ) 20 | .then(data => { 21 | console.log(data.data.quote.latestPrice); 22 | state.concat({ 23 | currPrice: data.data.quote.latestPrice, 24 | ...childState 25 | }); 26 | }); 27 | }); 28 | 29 | default: 30 | return state; 31 | } 32 | }; 33 | 34 | export default Portfolio; 35 | -------------------------------------------------------------------------------- /v1/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Jigar Chavada 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /v1/src/components/DashboardPage.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Table from "./Table"; 3 | import { connect } from "react-redux"; 4 | import Refresh from "../Actions/Refresh"; 5 | 6 | class DashboardPage extends React.Component { 7 | render() { 8 | return ( 9 |
10 |
11 |

{`Total money left : $${ 12 | this.props.money.money 13 | }`}

14 | 20 |
21 | 22 | 23 | ); 24 | } 25 | } 26 | 27 | const mapStatetoProps = state => { 28 | return { 29 | money: state.money, 30 | portfolio: state.portfolio 31 | }; 32 | }; 33 | 34 | const mapDispatchToProps = dispatch => { 35 | return { 36 | refresh: () => { 37 | dispatch(Refresh()); 38 | } 39 | }; 40 | }; 41 | 42 | export default connect( 43 | mapStatetoProps, 44 | mapDispatchToProps 45 | )(DashboardPage); 46 | -------------------------------------------------------------------------------- /v2/backend/models/model.js: -------------------------------------------------------------------------------- 1 | const {mongoose} = require("./mongoose-setup") 2 | const uniqueValidator = require('mongoose-unique-validator'); 3 | 4 | require('dotenv').config() 5 | 6 | const Schema = mongoose.Schema 7 | 8 | const moneySchema = new Schema({ 9 | money: { 10 | type: Number, 11 | required: true, 12 | default: 10000 13 | }, 14 | _creator: { 15 | type: mongoose.Schema.Types.ObjectId, 16 | unique: true, 17 | required: true 18 | } 19 | }) 20 | 21 | const companySchema = new Schema({ 22 | companyName: { type: String, required: true }, 23 | company: { type: String, required: true }, 24 | quantity: { type: Number, required: true }, 25 | buyPrice: { type: Number, required: true }, 26 | currPrice: { type: Number, required: true }, 27 | shareWorth: { type: Number, required: true }, 28 | profitLoss: { type: Number, required: true }, 29 | _creator: { type: mongoose.Schema.Types.ObjectId, required: true } 30 | }) 31 | 32 | moneySchema.plugin(uniqueValidator) 33 | companySchema.plugin(uniqueValidator) 34 | 35 | module.exports = { 36 | Money: mongoose.model("Money", moneySchema), 37 | Portfolio: mongoose.model("Portfolio", companySchema) 38 | } -------------------------------------------------------------------------------- /v1/src/components/Header.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { NavLink } from "react-router-dom"; 3 | 4 | const Header = () => ( 5 | 37 | ); 38 | 39 | export default Header; 40 | -------------------------------------------------------------------------------- /v2/backend/app.js: -------------------------------------------------------------------------------- 1 | const express = require("express") 2 | const bodyParser = require("body-parser") 3 | const cors = require("cors") 4 | const state = require("./routes/routes") 5 | const users = require("./routes/userRoutes.js") 6 | 7 | const app = express() 8 | 9 | // Body Parser Middleware 10 | app.use(bodyParser.json()) 11 | app.use(bodyParser.urlencoded({ extended: false })); 12 | 13 | let allowCrossDomain = function(req, res, next) { 14 | res.header('Access-Control-Allow-Origin', '*'); 15 | res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS,PATCH'); 16 | res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With, x-auth'); 17 | res.header('Access-Control-Expose-Headers', 'x-auth'); 18 | 19 | // intercept OPTIONS method 20 | if ('OPTIONS' == req.method) { 21 | res.sendStatus(200); 22 | } 23 | else { 24 | next(); 25 | } 26 | }; 27 | 28 | app.use(allowCrossDomain) 29 | 30 | 31 | // app.use(cors()) 32 | 33 | app.use("/state", state) 34 | app.use("/users", users) 35 | 36 | app.get("/", (req, res) => { 37 | res.send("Hey There How are you?") 38 | }) 39 | 40 | const PORT = process.env.PORT || 3001 41 | app.listen(PORT, () => { 42 | console.log("Started the backend server at port " + PORT) 43 | }) -------------------------------------------------------------------------------- /v2/src/reducers/Money.tsx: -------------------------------------------------------------------------------- 1 | import { RoundOf } from "../utils/utils"; 2 | import axios from "axios"; 3 | 4 | require("dotenv").config() 5 | 6 | interface Money { 7 | money: number 8 | _creator: string 9 | } 10 | 11 | interface Action { 12 | type: string, 13 | payload: number 14 | } 15 | 16 | const money: Money = { 17 | money: 10000, 18 | _creator: null 19 | } 20 | 21 | export default (state: Money = money, action: Action) => { 22 | switch (action.type) { 23 | case "BUY": 24 | const value = RoundOf(state.money - action.payload, 2) 25 | axios.patch(`${process.env.REACT_APP_BACKEND_URL}/state/money`, {money: value}, {headers: {"x-auth": sessionStorage.getItem("JWT_Token")}}) 26 | return { 27 | money: value 28 | } 29 | 30 | case "SELL": 31 | const sValue = RoundOf(state.money + action.payload, 2) 32 | axios.patch(`${process.env.REACT_APP_BACKEND_URL}/state/money`, {money: sValue}, {headers: {"x-auth": sessionStorage.getItem("JWT_Token")}}) 33 | return { 34 | money: sValue 35 | } 36 | 37 | case "SET": 38 | return { 39 | money: action.payload 40 | } 41 | 42 | default: 43 | return state; 44 | }; 45 | } -------------------------------------------------------------------------------- /v2/src/components/StockAreaChart.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import {AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, Label} from "recharts" 3 | import axios from "axios" 4 | import { RoundOf } from "../utils/utils" 5 | import { spawn } from "child_process"; 6 | 7 | interface PassedProps { 8 | data: any 9 | } 10 | 11 | class StockAreaChart extends React.Component { 12 | 13 | componentDidMount() { 14 | console.log(this.props) 15 | } 16 | 17 | render() { 18 | return ( 19 |
20 | 21 | 22 | 23 | 25 | 26 | 27 | 28 | 29 |
30 | ) 31 | } 32 | } 33 | 34 | export default StockAreaChart -------------------------------------------------------------------------------- /v2/src/router/Approuter.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { createBrowserHistory } from 'history'; 3 | import { Switch, Router } from "react-router-dom"; 4 | 5 | import PublicRoute from "./PublicRouter" 6 | import PrivateRoute from "./PrivateRouter" 7 | 8 | import Home from "../components/Home" 9 | import Buy from "../components/Buy" 10 | import View from "../components/View" 11 | import Assets from "../components/Assets" 12 | import SignUp from "../components/Signup" 13 | import LogIn from "../components/LogIn" 14 | import LogOut from "../components/LogOut" 15 | import Leaderboard from "../components/Leaderboard" 16 | 17 | export const history = createBrowserHistory(); 18 | 19 | export default () => ( 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | ); -------------------------------------------------------------------------------- /v2/src/styles/reset.css: -------------------------------------------------------------------------------- 1 | /* http://meyerweb.com/eric/tools/css/reset/ 2 | v4.0 | 20180602 3 | License: none (public domain) 4 | */ 5 | 6 | html, body, div, span, applet, object, iframe, 7 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 8 | a, abbr, acronym, address, big, cite, code, 9 | del, dfn, em, img, ins, kbd, q, s, samp, 10 | small, strike, strong, sub, sup, tt, var, 11 | b, u, i, center, 12 | dl, dt, dd, ol, ul, li, 13 | fieldset, form, label, legend, 14 | table, caption, tbody, tfoot, thead, tr, th, td, 15 | article, aside, canvas, details, embed, 16 | figure, figcaption, footer, header, hgroup, 17 | main, menu, nav, output, ruby, section, summary, 18 | time, mark, audio, video { 19 | margin: 0; 20 | padding: 0; 21 | border: 0; 22 | font-size: 100%; 23 | font: inherit; 24 | vertical-align: baseline; 25 | } 26 | /* HTML5 display-role reset for older browsers */ 27 | article, aside, details, figcaption, figure, 28 | footer, header, hgroup, main, menu, nav, section { 29 | display: block; 30 | } 31 | /* HTML5 hidden-attribute fix for newer browsers */ 32 | *[hidden] { 33 | display: none; 34 | } 35 | body { 36 | line-height: 1; 37 | } 38 | ol, ul { 39 | list-style: none; 40 | } 41 | blockquote, q { 42 | quotes: none; 43 | } 44 | blockquote:before, blockquote:after, 45 | q:before, q:after { 46 | content: ''; 47 | content: none; 48 | } 49 | table { 50 | border-collapse: collapse; 51 | border-spacing: 0; 52 | } 53 | -------------------------------------------------------------------------------- /v1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "boilerplate", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "scripts": { 7 | "serve": "live-server public/", 8 | "build": "webpack", 9 | "dev-server": "webpack-dev-server", 10 | "start": "node server/server.js", 11 | "heroku-postbuild": "yarn run build" 12 | }, 13 | "engines": { 14 | "node": "8.11.3" 15 | }, 16 | "dependencies": { 17 | "as-type": "^1.0.0", 18 | "axios": "^0.18.0", 19 | "babel-cli": "^6.24.1", 20 | "babel-core": "6.25.0", 21 | "babel-loader": "7.1.1", 22 | "babel-plugin-transform-class-properties": "6.24.1", 23 | "babel-plugin-transform-object-rest-spread": "^6.26.0", 24 | "babel-preset-env": "^1.7.0", 25 | "babel-preset-react": "^6.24.1", 26 | "css-loader": "0.28.4", 27 | "express": "^4.16.3", 28 | "firebase": "^5.0.4", 29 | "history": "^4.7.2", 30 | "live-server": "^1.2.0", 31 | "node-sass": "^4.9.0", 32 | "normalize.css": "7.0.0", 33 | "react": "16.0.0", 34 | "react-dom": "16.0.0", 35 | "react-redux": "^5.0.7", 36 | "react-router-dom": "^4.3.1", 37 | "react-table": "^6.8.6", 38 | "react-thunk": "^1.0.0", 39 | "recharts": "^1.0.0-beta.10", 40 | "redux": "^4.0.0", 41 | "redux-thunk": "^2.3.0", 42 | "sass-loader": "6.0.6", 43 | "style-loader": "0.18.2", 44 | "validator": "8.0.0", 45 | "webpack": "3.1.0", 46 | "webpack-dev-server": "2.5.1" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /v2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wallstreet", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@emotion/core": "^10.0.4", 7 | "@types/jest": "23.3.10", 8 | "@types/node": "10.12.12", 9 | "@types/react": "16.7.13", 10 | "@types/react-dom": "16.0.11", 11 | "@types/react-router-dom": "^4.3.1", 12 | "axios": "^0.18.0", 13 | "concurrently": "^4.1.0", 14 | "cors": "^2.8.5", 15 | "dotenv": "^6.2.0", 16 | "fs": "^0.0.1-security", 17 | "history": "^4.7.2", 18 | "lodash": "^4.17.11", 19 | "moment": "^2.23.0", 20 | "react": "^16.6.3", 21 | "react-autosuggest": "^9.4.2", 22 | "react-dom": "^16.6.3", 23 | "react-live-clock": "^3.0.0", 24 | "react-redux": "^6.0.0", 25 | "react-router-dom": "^4.3.1", 26 | "react-scripts": "2.1.1", 27 | "react-thunk": "^1.0.0", 28 | "recharts": "^1.4.2", 29 | "redux": "^4.0.1", 30 | "typescript": "3.2.2", 31 | "uuid": "^3.3.2" 32 | }, 33 | "scripts": { 34 | "start": "REACT_APP_BACKEND_URL=http://localhost:3001 REACT_APP_API_URL=https://api.iextrading.com/1.0/stock react-scripts start", 35 | "start:both": "concurrently \"yarn start\" \"node backend/app.js\" ", 36 | "build": "react-scripts build", 37 | "test": "react-scripts test", 38 | "eject": "react-scripts eject" 39 | }, 40 | "eslintConfig": { 41 | "extends": "react-app" 42 | }, 43 | "browserslist": [ 44 | ">0.2%", 45 | "not dead", 46 | "not ie <= 11", 47 | "not op_mini all" 48 | ] 49 | } 50 | -------------------------------------------------------------------------------- /v2/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 22 | 23 | 24 | Wall Street 25 | 26 | 27 | 30 |
31 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /v2/src/components/AutoCompleteInput.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import Autosuggest from 'react-autosuggest'; 3 | import store from "../reduxStore/store" 4 | 5 | const getSuggestions = value => { 6 | const inputValue = value.trim().toLowerCase(); 7 | const inputLength = inputValue.length; 8 | 9 | return inputLength === 0 ? [] : store.getState().symbol.filter(sym => { 10 | return sym.toLowerCase().slice(0, inputLength) === inputValue 11 | } 12 | ).slice(0, 5); 13 | }; 14 | 15 | const getSuggestionValue = suggestion => suggestion; 16 | 17 | const renderSuggestion = suggestion => ( 18 |
19 | {suggestion} 20 |
21 | ); 22 | 23 | 24 | class AutoCompleteInput extends React.Component { 25 | 26 | state = { 27 | value: '', 28 | suggestions: [] 29 | } 30 | 31 | onChange = (event, { newValue }) => { 32 | this.setState({value: newValue}) 33 | } 34 | 35 | onSuggestionsFetchRequested = ({ value }) => { 36 | this.setState({ 37 | suggestions: getSuggestions(value) 38 | }); 39 | }; 40 | 41 | onSuggestionsClearRequested = () => { 42 | this.setState({ 43 | suggestions: [] 44 | }); 45 | }; 46 | 47 | 48 | 49 | render() { 50 | const { value, suggestions } = this.state; 51 | 52 | const inputProps = { 53 | placeholder: this.props.placeholder, 54 | value, 55 | onChange: this.onChange 56 | }; 57 | 58 | return ( 59 | 67 | ) 68 | } 69 | } 70 | 71 | export default AutoCompleteInput -------------------------------------------------------------------------------- /v2/README.md: -------------------------------------------------------------------------------- 1 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 2 | 3 | ## Available Scripts 4 | 5 | In the project directory, you can run: 6 | 7 | ### `npm start` 8 | 9 | Runs the app in the development mode.
10 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 11 | 12 | The page will reload if you make edits.
13 | You will also see any lint errors in the console. 14 | 15 | ### `npm test` 16 | 17 | Launches the test runner in the interactive watch mode.
18 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 19 | 20 | ### `npm run build` 21 | 22 | Builds the app for production to the `build` folder.
23 | It correctly bundles React in production mode and optimizes the build for the best performance. 24 | 25 | The build is minified and the filenames include the hashes.
26 | Your app is ready to be deployed! 27 | 28 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 29 | 30 | ### `npm run eject` 31 | 32 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!** 33 | 34 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 35 | 36 | Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. 37 | 38 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. 39 | 40 | ## Learn More 41 | 42 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 43 | 44 | To learn React, check out the [React documentation](https://reactjs.org/). 45 | -------------------------------------------------------------------------------- /v2/src/components/Leaderboard.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import axios from "axios" 3 | 4 | class Leaderboard extends React.Component { 5 | 6 | state = { 7 | gotData: false, 8 | leaderBoard: [] 9 | } 10 | 11 | componentDidMount() { 12 | axios.get(`${process.env.REACT_APP_BACKEND_URL}/users/leaderboard`).then(data => { 13 | this.setState({gotData: true, leaderBoard: data.data}) 14 | }) 15 | } 16 | 17 | render() { 18 | return ( 19 |
20 | 21 |
22 |
23 |

Leaderboard

24 |
25 |
26 | { !this.state.gotData ?

Loading....

: 27 | 28 |
29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | { 38 | this.state.leaderBoard.map((user, index) => { 39 | if(index < 10) { 40 | return ( 41 | 42 | 43 | 44 | 45 | 46 | ) 47 | } 48 | }) 49 | } 50 | 51 |
Sr. NoName of the UserTotal Profit
{index+1} {user.name.toUpperCase()} $ {user.profitLoss}
52 | } 53 | 54 | 55 | ) 56 | } 57 | } 58 | 59 | export default Leaderboard 60 | -------------------------------------------------------------------------------- /v2/src/utils/utils.tsx: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | require("dotenv").config() 3 | 4 | import store from "../reduxStore/store"; 5 | import AddCompany from "../actions/Addcompany" 6 | import FetchSymbols from "../actions/FetchSymbols" 7 | import Set from "../actions/SetMoney" 8 | 9 | const RoundOf = (num: number, roundTo: number): number=> { 10 | return Number((num*1).toFixed(roundTo)); 11 | }; 12 | 13 | const getUpdate = async (symbol: string) => { 14 | return await axios.get(`${process.env.REACT_APP_API_URL}/${symbol}/batch?types=quote`) 15 | } 16 | 17 | const getMarketStatus = () => { 18 | axios.get("https://api.iextrading.com/1.0/stock/aapl/batch?types=quote").then(data => { 19 | 20 | let status = data.data.quote.latestSource 21 | if(status.localeCompare("Close") == 0 || status.localeCompare("Previous close") == 0) { 22 | sessionStorage.setItem("status", "CLOSE") 23 | } else { 24 | sessionStorage.setItem("status", "OPEN") 25 | } 26 | }) 27 | 28 | } 29 | 30 | const setUserName = () => { 31 | axios.get(`${process.env.REACT_APP_BACKEND_URL}/users/me`, {headers: {"x-auth": sessionStorage.getItem("JWT_Token")}}).then(data => { 32 | sessionStorage.setItem("name", data.data.name) 33 | return data.data.name 34 | }) 35 | } 36 | 37 | const getInitialValue = () => { 38 | if(sessionStorage.getItem("User_ID")) { 39 | axios.get(`${process.env.REACT_APP_BACKEND_URL}/state/company`, {headers: {"x-auth": sessionStorage.getItem("JWT_Token")}}).then(data => { 40 | data.data.map(item => { 41 | store.dispatch(AddCompany(item)) 42 | }) 43 | }) 44 | 45 | axios.get(`${process.env.REACT_APP_BACKEND_URL}/state/money`, {headers: {"x-auth": sessionStorage.getItem("JWT_Token")}}).then(data => { 46 | if(data.data[0] === undefined) { 47 | axios.post(`${process.env.REACT_APP_BACKEND_URL}/state/money`, {money: 10000}, {headers: {"x-auth": sessionStorage.getItem("JWT_Token")}}).then(() => { 48 | store.dispatch(Set(10000)) 49 | }) 50 | } 51 | store.dispatch(Set(data.data[0].money)) 52 | }) 53 | 54 | axios.get(`${process.env.REACT_APP_BACKEND_URL}/state/symbols`).then(data => { 55 | store.dispatch(FetchSymbols(data.data.data)) 56 | }) 57 | 58 | setUserName() 59 | getMarketStatus() 60 | } 61 | } 62 | 63 | export { 64 | RoundOf, 65 | getUpdate, 66 | getInitialValue, 67 | getMarketStatus, 68 | setUserName 69 | } 70 | -------------------------------------------------------------------------------- /v2/src/components/Assets.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { connect } from "react-redux"; 3 | 4 | import { RoundOf } from "../utils/utils" 5 | import "../styles/main.css" 6 | 7 | interface PassedProps { 8 | money: { 9 | money: number 10 | }, 11 | portfolio: any 12 | } 13 | 14 | class Asset extends React.Component { 15 | 16 | calcAsset = () => { 17 | let assets = 0; 18 | this.props.portfolio.map(item => { 19 | assets = assets + item.shareWorth; 20 | }) 21 | 22 | return RoundOf(assets, 2); 23 | } 24 | 25 | render() { 26 | return ( 27 |
28 | 60 |
61 | ) 62 | }; 63 | }; 64 | 65 | const mapStateToProps = (state) => { 66 | return { 67 | portfolio: state.portfolio, 68 | money: state.money 69 | } 70 | } 71 | 72 | export default connect(mapStateToProps)(Asset); -------------------------------------------------------------------------------- /v2/backend/routes/userRoutes.js: -------------------------------------------------------------------------------- 1 | const express = require("express") 2 | const router = express.Router() 3 | const _ = require("lodash") 4 | 5 | const { authenticate } = require("../middleware/authenticate") 6 | const { User } = require("../models/user") 7 | 8 | router.post("/signup", (req, res) => { 9 | let body = _.pick(req.body, ["email", "password", "name"]) 10 | 11 | let user = new User(body) 12 | 13 | user.save().then(() => { 14 | return user.generateAuthToken() 15 | }).then((token) => { 16 | res.header('x-auth', token).send(user) 17 | }).catch(err => { 18 | res.status(400).send(err) 19 | }) 20 | }) 21 | 22 | router.get("/me", authenticate, (req, res) => { 23 | res.send(req.user) 24 | }) 25 | 26 | router.post("/login", (req, res) => { 27 | let body = _.pick(req.body, ["email", "password"]) 28 | 29 | User.findByCredentials(body.email, body.password).then(user => { 30 | return user.generateAuthToken().then(token => { 31 | res.header('x-auth', token).send(user) 32 | }) 33 | }).catch(err => { 34 | res.status(400).send(err) 35 | }) 36 | }) 37 | 38 | router.delete("/logout", authenticate, (req, res) => { 39 | req.user.removeToken(req.token).then(() => { 40 | res.status(200).send("logged out") 41 | }).catch(err => { 42 | res.status(400).send(err) 43 | }) 44 | }) 45 | 46 | router.get("/leaderboard", (req, res) => { 47 | User.aggregate([ 48 | { 49 | $lookup: 50 | { 51 | from: "portfolios", 52 | localField: "_id", 53 | foreignField: "_creator", 54 | as: "portfolio" 55 | } 56 | }, 57 | { 58 | $lookup: 59 | { 60 | from: "money", 61 | localField: "_id", 62 | foreignField: "_creator", 63 | as: "money" 64 | } 65 | } 66 | ]).then(data => { 67 | leaderboard = [] 68 | data.map(user => { 69 | money = user.money[0].money 70 | shareWorth = 0 71 | user.portfolio.map(port => { 72 | shareWorth += port.shareWorth 73 | }) 74 | 75 | leaderboard_data = { 76 | creator: user._id, 77 | name: user.name, 78 | profitLoss: (money + shareWorth - 10000).toFixed(2) 79 | } 80 | 81 | leaderboard.push(leaderboard_data) 82 | }) 83 | leaderboard.sort((a,b) => { 84 | return b.profitLoss - a.profitLoss 85 | }) 86 | res.send(leaderboard) 87 | }) 88 | }) 89 | 90 | module.exports = router -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## What is Wall Street? 2 | Wall Street is a virtual stock trading web application made using React. This application intends to help future investors learn the ups and downs of the stock market and build a portfolio of stocks for themselves. Beginning with a sum of **$10,000** you get a chance to get accustomed to the buying and selling of stocks, track your progress over a period of time and make yourself ready to conquer the stock market. 3 | 4 | ## Why Wall Street? 5 | 6 | The stock market has always been considered a risky business, infact, some might even go to the extents of calling these investments as gambles. Wall Street is a Web Application that will prove otherwise. With access to virtual money and a starting sum of **$10,000**, Wall Street will enable you to build your very own portfolio from scratch. Here, you get a chance to learn about how the stock market operates in the real world, find your way through profits and losses and gain a practical hand on experience of this trade business without the risk of stepping into the real stock exchange. 7 | 8 | 9 | ## Installation 10 | 11 | You need to have Node installed on your local machine. [Node](https://nodejs.org/en/) 12 | 13 | NPM(Node Package Manager is already bundled with Node). You can use yarn as well. Install Yarn from [here](https://yarnpkg.com/lang/en/docs/install/) 14 | 15 | To run the project 16 | 17 | ``` 18 | cd v2/ 19 | yarn install 20 | yarn start 21 | ``` 22 | 23 | Yarn can be replaced by npm. 24 | 25 | The above command will start the frontend 26 | 27 | To start the backend 28 | ``` 29 | cd v2/backend 30 | yarn install 31 | yarn start 32 | ``` 33 | 34 | The App uses a [Mongo database](https://docs.mongodb.com/v3.2/administration/install-community/) so you will need to start a mongo service first on your local machine or if you don't want local mongo instance you can use [mLab](http://mlab.com). Replace your mLabURI with the local one in v2/backend/models/mongoose-setup.js and put your username and password in a .env file. Sample env file is given backend/.env.sample. Just replace it with your mLab credentials and rename the file to .env 35 | 36 | To add a feature request just create an issue. 37 | 38 | The v1 of this project was made when I just started out learning React, so it has lots of bugs and some core features didn't work properly(blame decimal alegbra in JavaScript) 39 | 40 | To improve on all of it, I have made a v2 which is just more stable and better and with good practices. I have used TypeScript in React for the first time and really liked it, having static checking goes a long way in development process. 41 | 42 | **For all the participants of OpenCode, I just want to tell you that this project might be a litle daunting given your experience level. You may face many problems in the setup itself, don't get disheartned and leave it in the middle. You may contact me anytime on [Facebook](https://www.facebook.com/jsc3998) and resolve your doubts. If you get stuck or don't know how to solve a particular issue or need some suggestions always feel free to ask me or anyone. Feel free to comment on any issues to get clarification, hint or any doubt you might have.** 43 | 44 | Enjoy!! 45 | 46 | 47 | -------------------------------------------------------------------------------- /v2/src/components/LogIn.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import axios from "axios"; 3 | 4 | import { Link } from "react-router-dom" 5 | import { history } from "../router/Approuter"; 6 | 7 | interface State { 8 | email: String, 9 | password: String, 10 | error: String, 11 | loading: Boolean 12 | } 13 | 14 | class LogIn extends React.Component { 15 | 16 | state = { 17 | email: "", 18 | password: "", 19 | error: undefined, 20 | loading: false 21 | } 22 | 23 | handleChange = (e) => { 24 | this.setState({ 25 | [e.target.name]: [e.target.value] 26 | } as Pick) 27 | this.setState({error: ""}) 28 | } 29 | 30 | handleSubmit = (e) => { 31 | e.preventDefault() 32 | 33 | this.setState({loading: true}) 34 | axios.post(`${process.env.REACT_APP_BACKEND_URL}/users/login`, {email: this.state.email[0], password: this.state.password[0]}).then(data => { 35 | sessionStorage.setItem("JWT_Token", data.headers["x-auth"]) 36 | sessionStorage.setItem("User_ID", data.data._id) 37 | // history.push("/") 38 | window.location.href = "/" 39 | }).catch((err) => { 40 | console.log(err) 41 | this.setState({error: "Email & Password didn't match", loading: false}) 42 | }) 43 | } 44 | 45 | render() { 46 | return( 47 |
48 | 49 |
50 |

Log In

51 |

Sign Up

52 |
53 |
54 | 55 |
56 |

57 | 58 | 59 | 60 | 61 |

62 |
63 | 64 |
65 |

66 | 67 | 68 | 69 | 70 |

71 |

{this.state.error}

72 |
73 | 74 |
75 |
76 | {this.state.loading ? : } 77 |
78 |
79 |
80 | 81 |
82 | ) 83 | } 84 | } 85 | 86 | export default LogIn -------------------------------------------------------------------------------- /v2/backend/models/user.js: -------------------------------------------------------------------------------- 1 | const {mongoose} = require('./mongoose-setup'); 2 | const uniqueValidator = require('mongoose-unique-validator'); 3 | const validator = require('validator'); 4 | const jwt = require('jsonwebtoken'); 5 | const _ = require('lodash'); 6 | const bcrypt = require('bcryptjs'); 7 | 8 | let UserSchema = new mongoose.Schema({ 9 | name: { 10 | type: String, 11 | required: true, 12 | minlength: 3 13 | }, 14 | email: { 15 | type: String, 16 | required: true, 17 | trim: true, 18 | minlength: 1, 19 | unique: true, 20 | index: true, 21 | validate: { 22 | validator: validator.isEmail, 23 | message: '{VALUE} is not a valid email' 24 | } 25 | }, 26 | password: { 27 | type: String, 28 | require: true, 29 | minlength: 4 30 | }, 31 | tokens: [{ 32 | access: { 33 | type: String, 34 | required: true 35 | }, 36 | token: { 37 | type: String, 38 | required: true 39 | } 40 | }] 41 | }); 42 | 43 | UserSchema.methods.toJSON = function () { 44 | let user = this; 45 | let userObject = user.toObject(); 46 | 47 | return _.pick(userObject, ['_id', 'email', 'name']); 48 | }; 49 | 50 | UserSchema.methods.generateAuthToken = function () { 51 | let user = this; 52 | let access = 'auth'; 53 | let token = jwt.sign({_id: user._id.toHexString(), access}, process.env.SALT).toString(); 54 | 55 | user.tokens = user.tokens.concat([{access, token}]); 56 | 57 | return user.save().then(() => { 58 | return token; 59 | }); 60 | }; 61 | 62 | UserSchema.methods.removeToken = function (token) { 63 | let user = this; 64 | 65 | return user.update({ 66 | $pull: { 67 | tokens: {token} 68 | } 69 | }); 70 | }; 71 | 72 | UserSchema.statics.findByToken = function (token) { 73 | let User = this; 74 | let decoded; 75 | 76 | try { 77 | decoded = jwt.verify(token, process.env.SALT); 78 | } catch (e) { 79 | return Promise.reject(); 80 | } 81 | 82 | return User.findOne({ 83 | '_id': decoded._id, 84 | 'tokens.token': token, 85 | 'tokens.access': 'auth' 86 | }); 87 | }; 88 | 89 | UserSchema.statics.findByCredentials = function (email, password) { 90 | let User = this; 91 | 92 | return User.findOne({email}).then((user) => { 93 | if (!user) { 94 | return Promise.reject(); 95 | } 96 | 97 | return new Promise((resolve, reject) => { 98 | // Use bcrypt.compare to compare password and user.password 99 | bcrypt.compare(password, user.password, (err, res) => { 100 | if (res) { 101 | resolve(user); 102 | } else { 103 | reject(); 104 | } 105 | }); 106 | }); 107 | }); 108 | }; 109 | 110 | UserSchema.pre('save', function (next) { 111 | let user = this; 112 | 113 | if (user.isModified('password')) { 114 | bcrypt.genSalt(10, (err, salt) => { 115 | bcrypt.hash(user.password, salt, (err, hash) => { 116 | user.password = hash; 117 | next(); 118 | }); 119 | }); 120 | } else { 121 | next(); 122 | } 123 | }); 124 | 125 | UserSchema.plugin(uniqueValidator) 126 | 127 | let User = mongoose.model('User', UserSchema); 128 | 129 | module.exports = { User } 130 | -------------------------------------------------------------------------------- /v2/src/styles/main.css: -------------------------------------------------------------------------------- 1 | .table th{ 2 | text-align: center 3 | } 4 | 5 | .table td { 6 | text-align: center 7 | } 8 | 9 | .table { 10 | margin-top: 0.75rem; 11 | } 12 | 13 | .container { 14 | width: 40% 15 | } 16 | 17 | #login_signup { 18 | display: flex; 19 | justify-content: space-around 20 | } 21 | 22 | #search_box_view { 23 | margin-top: 2rem; 24 | } 25 | 26 | .view_list li span { 27 | font-weight: 600 28 | } 29 | 30 | #chart { 31 | margin: 0 auto; 32 | width: 120%; 33 | transform: translateX(-12%) translateY(-1rem) 34 | } 35 | 36 | #view_title { 37 | padding-top: 2rem; 38 | } 39 | 40 | #github { 41 | display: flex; 42 | } 43 | 44 | #currPrice { 45 | padding: 0px 5px; 46 | border: 1px black solid; 47 | background: black; 48 | color: white; 49 | font-weight: 300; 50 | } 51 | 52 | #github img { 53 | padding-right: 0.4rem; 54 | } 55 | 56 | .view_list { 57 | width: 100%; 58 | margin: 0 auto; 59 | font-family: Arial, Helvetica, sans-serif 60 | } 61 | 62 | .view_list li { 63 | display: flex; 64 | text-align: left; 65 | justify-content: space-between 66 | } 67 | 68 | #arrow { 69 | vertical-align: baseline; 70 | padding-left: 0.5rem; 71 | } 72 | 73 | #status_label { 74 | padding-right: 0.5rem; 75 | text-decoration: none; 76 | color: black; 77 | } 78 | 79 | .react-autosuggest__container{ 80 | box-shadow: 0px 0px 12px 1px rgba(10,10,10,.1); 81 | } 82 | 83 | .react-autosuggest__input { 84 | background: #ffffff; 85 | width: 100%; 86 | line-height: 2rem; 87 | border: 1px #dbdbdb solid; 88 | padding-left: 0.6rem; 89 | font-size: 1rem; 90 | 91 | } 92 | 93 | .react-autosuggest__input::placeholder { 94 | color: rgba(10,10,10, 0.3); 95 | } 96 | 97 | .react-autosuggest__input:focus { 98 | outline: outset 1px #3273DC solid; 99 | } 100 | 101 | .react-autosuggest__suggestion { 102 | padding: 0.25rem 0rem 0.25rem 0.6rem; 103 | } 104 | 105 | .react-autosuggest__suggestion--highlighted { 106 | background: rgba(230, 230, 230, 0.6); 107 | } 108 | 109 | .leaderboard { 110 | width: 40%; 111 | margin-top: 2rem; 112 | user-select: none; 113 | } 114 | 115 | .leaderboard_loader { 116 | text-align: center; 117 | margin: 0 auto; 118 | font-size: 1.5rem; 119 | } 120 | 121 | #close { 122 | border: 1px red solid; 123 | color: red; 124 | padding: 0.5rem; 125 | font-weight: 600 126 | } 127 | 128 | #open { 129 | border: 1px green solid; 130 | color: green; 131 | padding: 0.5rem; 132 | font-weight: 600 133 | } 134 | 135 | #loginactive, #signupactive { 136 | text-decoration: underline; 137 | text-underline-position: under; 138 | } 139 | 140 | #login { 141 | margin-top: 10%; 142 | width: 30%; 143 | } 144 | 145 | #signup { 146 | margin-top: 10%; 147 | width: 30%; 148 | } 149 | 150 | #usericon { 151 | vertical-align: middle; 152 | } 153 | 154 | #name { 155 | padding-left: 0.75rem; 156 | } 157 | 158 | #sellGroup { 159 | display: flex; 160 | justify-content: center; 161 | } 162 | 163 | #sellGroup input { 164 | width: 50%; 165 | float: right; 166 | } 167 | 168 | #profit { 169 | color: green; 170 | } 171 | 172 | #loss { 173 | color: red; 174 | } 175 | 176 | #nav { 177 | width: 50%; 178 | display: flex; 179 | justify-content: space-around; 180 | } 181 | 182 | .level { 183 | padding: 1.75rem 0px; 184 | } 185 | #clock { 186 | margin-top: 0.9px; 187 | color: black; 188 | font-size: 16px; 189 | } 190 | -------------------------------------------------------------------------------- /v2/backend/routes/routes.js: -------------------------------------------------------------------------------- 1 | const express = require("express") 2 | const _ = require("lodash") 3 | const cheerio = require('cheerio') 4 | const axios = require("axios") 5 | const fs = require('fs') 6 | const path = require("path") 7 | 8 | const router = express.Router() 9 | const { authenticate } = require("../middleware/authenticate") 10 | 11 | const { Money, Portfolio } = require("../models/model") 12 | 13 | router.get("/money", authenticate, (req, res) => { 14 | Money.find({_creator: req.user._id}).then(data => { 15 | res.send(data) 16 | }).catch(err => { 17 | res.send(err) 18 | }) 19 | }) 20 | 21 | router.post("/money", authenticate, (req, res) => { 22 | const money = new Money({ 23 | money: req.body.money, 24 | _creator: req.user._id 25 | }) 26 | 27 | money.save().then(data => { 28 | res.send(data) 29 | }).catch(err => { 30 | res.send(err) 31 | }) 32 | }) 33 | 34 | router.patch("/money", authenticate, (req, res) => { 35 | const body = _.pick(req.body, ["money"]) 36 | 37 | Money.findOneAndUpdate({_creator: req.user._id}, {$set: body}, {new: true}).then(data => { 38 | if(data == null) { 39 | return res.status(404).send() 40 | } 41 | res.send(data) 42 | }).catch(err => { 43 | res.send(data) 44 | }) 45 | }) 46 | 47 | router.delete("/money", authenticate, (req, res) => { 48 | Money.deleteOne({_creator: req.user._id}) 49 | .then(data => { 50 | res.send(data); 51 | }) 52 | .catch(err => { 53 | res.send(err); 54 | }); 55 | }); 56 | 57 | router.get("/company", authenticate, (req, res) => { 58 | Portfolio.find({_creator: req.user._id}).then(data => { 59 | res.send(data) 60 | }).catch(err => { 61 | res.send(err) 62 | }) 63 | }) 64 | 65 | router.post("/company", authenticate, (req, res) => { 66 | const company = _.pick(req.body, ["company", "companyName", "quantity", "buyPrice", "currPrice", "shareWorth", "profitLoss"]) 67 | company["_creator"] = req.user._id 68 | 69 | Portfolio.create(company).then(data => { 70 | res.send(data) 71 | }).catch(err => { 72 | res.send(err) 73 | }) 74 | }) 75 | 76 | router.patch("/company", authenticate, (req, res) => { 77 | const updatedValue = _.pick(req.body, ["company", "companyName", "quantity", "buyPrice", "currPrice", "shareWorth", "profitLoss", "_id"]) 78 | 79 | Portfolio.findOneAndUpdate({"_creator": req.user._id, "_id": updatedValue._id}, {$set: updatedValue}, {new: true}).then(data => { 80 | if(data == null) { 81 | return res.status(404).send() 82 | } 83 | res.send(data) 84 | }).catch(err => { 85 | res.send(err) 86 | }) 87 | }) 88 | 89 | router.delete("/company", authenticate, (req, res) => { 90 | Portfolio.findOneAndDelete({"_id": req.body.id}) 91 | .then(data => { 92 | res.send(data) 93 | }).catch(err => { 94 | res.send(err) 95 | }) 96 | }) 97 | 98 | router.get("/market", (req, res) => { 99 | axios.get("https://www.nasdaq.com/").then(data => { 100 | let $ = cheerio.load(data.data) 101 | let status; 102 | let title = $('.indexmktstatus').text().trim(); 103 | 104 | if(title.localeCompare("US Market Open") == 1) { 105 | status = "OPEN" 106 | } else { 107 | status = "CLOSE" 108 | } 109 | 110 | data = { 111 | status 112 | } 113 | 114 | res.send(data) 115 | }) 116 | }) 117 | 118 | router.get("/symbols", (req, res) => { 119 | res.sendFile(path.join(__dirname, '..', 'assets', 'symbols.json')) 120 | }) 121 | 122 | module.exports = router -------------------------------------------------------------------------------- /v2/src/components/SellButton.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { connect } from "react-redux"; 3 | 4 | import DeleteCompany from "../actions/DeleteCompany"; 5 | import SellAction from "../actions/Sell"; 6 | import Refresh from "../actions/Refresh"; 7 | 8 | import axios from "axios"; 9 | import { RoundOf } from "../utils/utils"; 10 | 11 | interface PassedProps { 12 | id: string, 13 | // currValue: number, 14 | deleteCompany: any, 15 | addToMoney: any, 16 | // quantity: number, 17 | // buyPrice: number, 18 | refresh: any, 19 | allValue: any 20 | } 21 | 22 | interface State { 23 | quantity: any, 24 | error: string 25 | } 26 | 27 | class SellButton extends React.Component { 28 | 29 | state = { 30 | quantity: undefined, 31 | error: "" 32 | } 33 | 34 | handleSubmit = (id, currValue, maxQuantity, buyPrice) => { 35 | if(this.state.quantity == maxQuantity) { 36 | this.props.deleteCompany(id); 37 | axios.delete(`${process.env.REACT_APP_BACKEND_URL}/state/company`, {data: {id}, headers: {"x-auth": sessionStorage.getItem("JWT_Token")}}).then(() => { 38 | this.props.addToMoney(RoundOf(maxQuantity * currValue, 2)) 39 | this.setState({quantity: ""}) 40 | }) 41 | } else if(this.state.quantity < maxQuantity && this.state.quantity > 0) { 42 | const changedQuantity = maxQuantity - this.state.quantity 43 | const shareWorth = RoundOf(changedQuantity * currValue, 2) 44 | const profitLoss = RoundOf((currValue - buyPrice) * changedQuantity, 2) 45 | 46 | const companyDetails = { 47 | ...this.props.allValue, 48 | quantity: changedQuantity, 49 | shareWorth, 50 | profitLoss, 51 | _id: id 52 | } 53 | 54 | axios.patch(`${process.env.REACT_APP_BACKEND_URL}/state/company`, companyDetails, { 55 | headers: {"x-auth": sessionStorage.getItem("JWT_Token")} 56 | }).then(() => { 57 | this.props.deleteCompany({id}) 58 | this.props.refresh({id, companyDetails}) 59 | this.props.addToMoney(RoundOf(this.state.quantity * currValue, 2)) 60 | this.setState({quantity: ""}) 61 | }) 62 | 63 | } else { 64 | this.setState({error: "Invalid Quantity"}) 65 | } 66 | 67 | 68 | } 69 | 70 | handleChange = (e) => { 71 | this.setState({quantity: e.target.value}) 72 | this.setState({error: ""}) 73 | } 74 | 75 | render() { 76 | return ( 77 |
78 |
79 | 80 | 81 |
82 |

{this.state.error ?

{this.state.error}

: undefined }

83 |
84 | ) 85 | } 86 | } 87 | 88 | const mapDispatchToProps = (dispatch) => { 89 | return { 90 | deleteCompany: id => { 91 | dispatch(DeleteCompany(id)); 92 | }, 93 | addToMoney: sellValue => { 94 | dispatch(SellAction(sellValue)); 95 | }, 96 | refresh: ({id, companyDetails}) => { 97 | dispatch(Refresh({id, companyDetails})); 98 | } 99 | } 100 | } 101 | 102 | export default connect(null, mapDispatchToProps)(SellButton); -------------------------------------------------------------------------------- /v1/src/components/Piechart.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { PieChart, Pie, Sector, Cell, ResponsiveContainer } from "recharts"; 3 | import { connect } from "react-redux"; 4 | const as = require("as-type"); 5 | 6 | const colors = [ 7 | "#00B2EE", 8 | "#33A1C9", 9 | "#38B0DE", 10 | "#0BB5FF", 11 | "#00BFFF", 12 | "#0BB5FF" 13 | ]; 14 | const data = [ 15 | { name: "Group A", value: 400 }, 16 | { name: "Group B", value: 300 }, 17 | { name: "Group C", value: 300 }, 18 | { name: "Group D", value: 200 } 19 | ]; 20 | 21 | const renderActiveShape = props => { 22 | const RADIAN = Math.PI / 180; 23 | const { 24 | cx, 25 | cy, 26 | midAngle, 27 | innerRadius, 28 | outerRadius, 29 | startAngle, 30 | endAngle, 31 | fill, 32 | payload, 33 | percent, 34 | value 35 | } = props; 36 | const sin = Math.sin(-RADIAN * midAngle); 37 | const cos = Math.cos(-RADIAN * midAngle); 38 | const sx = cx + (outerRadius + 10) * cos; 39 | const sy = cy + (outerRadius + 10) * sin; 40 | const mx = cx + (outerRadius + 30) * cos; 41 | const my = cy + (outerRadius + 30) * sin; 42 | const ex = mx + (cos >= 0 ? 1 : -1) * 22; 43 | const ey = my; 44 | const textAnchor = cos >= 0 ? "start" : "end"; 45 | 46 | return ( 47 | 48 | 57 | {payload.name} 58 | 59 | 68 | 77 | 82 | 83 | = 0 ? 1 : -1) * 12} 85 | y={ey} 86 | textAnchor={textAnchor} 87 | fill="#333" 88 | >{`$ ${value}`} 89 | = 0 ? 1 : -1) * 12} 91 | y={ey} 92 | dy={18} 93 | textAnchor={textAnchor} 94 | fill="#999" 95 | > 96 | {`(${(percent * 100).toFixed(2)}%)`} 97 | 98 | 99 | ); 100 | }; 101 | 102 | class CustomPieChart extends React.Component { 103 | state = { 104 | activeIndex: 0 105 | }; 106 | 107 | onPieEnter = (data, index) => { 108 | this.setState(() => ({ 109 | activeIndex: index 110 | })); 111 | }; 112 | 113 | render() { 114 | return ( 115 | 116 | 128 | {data.map((entry, index) => ( 129 | 130 | ))} 131 | 132 | 133 | ); 134 | } 135 | } 136 | 137 | const mapStateToProps = state => { 138 | let companyDetails = []; 139 | state.portfolio.map(child => { 140 | companyDetails.push({ 141 | name: child.company, 142 | value: parseFloat(child.shareWorth) 143 | }); 144 | }); 145 | companyDetails.push({ 146 | name: "Money", 147 | value: as.float(state.money.money) 148 | }); 149 | return { 150 | name: companyDetails 151 | }; 152 | }; 153 | 154 | export default connect(mapStateToProps)(CustomPieChart); 155 | -------------------------------------------------------------------------------- /v2/src/components/Home.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { connect } from "react-redux"; 3 | 4 | import SellButton from "./SellButton"; 5 | import Asset from "./Assets"; 6 | import Refresh from "../actions/Refresh"; 7 | import { getUpdate, RoundOf, getMarketStatus } from "../utils/utils"; 8 | import SellAction from "../actions/Sell"; 9 | import BuyAction from "../actions/Buy"; 10 | 11 | import "../styles/main.css" 12 | import axios from "axios"; 13 | import { setInterval } from "timers"; 14 | 15 | interface PassedProps { 16 | money: { 17 | money: number 18 | }, 19 | portfolio: any, 20 | refresh: any, 21 | addToMoney: any 22 | } 23 | 24 | class Home extends React.Component { 25 | 26 | state = { 27 | intervalId: null, 28 | statusInterval: null 29 | } 30 | 31 | componentDidMount() { 32 | if(sessionStorage.getItem("status") === "OPEN") { 33 | clearInterval(this.state.statusInterval) 34 | } 35 | let statusInterval = setInterval(() => getMarketStatus(), 10000) 36 | let interval = setInterval(this.update, 2000); 37 | this.setState({intervalId: interval, statusInterval}); 38 | } 39 | 40 | componentDidUpdate(prevProps) { 41 | if(JSON.stringify(this.props.portfolio) !== JSON.stringify(prevProps.portfolio)) { 42 | this.props.portfolio.map(item => { 43 | axios.patch(`${process.env.REACT_APP_BACKEND_URL}/state/company`, item, {headers: {"x-auth": sessionStorage.getItem("JWT_Token")}}).then(() => { 44 | }) 45 | }) 46 | } 47 | } 48 | 49 | componentWillUnmount() { 50 | clearInterval(this.state.intervalId); 51 | clearInterval(this.state.statusInterval) 52 | } 53 | 54 | update = () => { 55 | if(sessionStorage.getItem("status") !== "CLOSE") { 56 | this.props.portfolio.map((item, index) => { 57 | const id = item._id 58 | getUpdate(item.company).then(data => { 59 | let companyDetails = { 60 | ...item, 61 | currPrice: data.data.quote.latestPrice, 62 | profitLoss: RoundOf((data.data.quote.latestPrice - item.buyPrice) * item.quantity, 2), 63 | shareWorth: RoundOf(item.quantity * data.data.quote.latestPrice, 2) 64 | }; 65 | this.props.refresh({id, companyDetails}); 66 | }); 67 | }) 68 | } 69 | 70 | } 71 | 72 | render() { 73 | return ( 74 |
75 | 76 | 77 |
78 |
79 |

Portfolio

80 |
81 |
82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | { 97 | this.props.portfolio.map((e, index) => { 98 | return ( 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | )} 109 | ) 110 | } 111 | 112 |
CompanyQuantityBuyPriceCurrentPriceShareWorthProfitLossSell Button
{e.companyName}{e.quantity}$ RoundOf({e.buyPrice},2)$ RoundOf({e.currPrice},2)$ RoundOf({e.shareWorth},2){e.profitLoss >= 0 ? $ {e.profitLoss} : $ {e.profitLoss}}
113 | 114 |
115 | ) 116 | }; 117 | }; 118 | 119 | const mapStateToProps = state => { 120 | return { 121 | money: state.money, 122 | portfolio: state.portfolio 123 | }; 124 | }; 125 | 126 | const mapDisptachToProps = (dispatch) => { 127 | return { 128 | refresh: ({id, companyDetails}) => { 129 | dispatch(Refresh({id, companyDetails})); 130 | }, 131 | addToMoney: (value) => { 132 | dispatch(SellAction(value)); 133 | }, 134 | subtractFromMoney: (value) => { 135 | dispatch(BuyAction(value)); 136 | } 137 | } 138 | } 139 | 140 | export default connect(mapStateToProps, mapDisptachToProps)(Home); 141 | 142 | -------------------------------------------------------------------------------- /v2/src/components/Header.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { NavLink } from "react-router-dom" 3 | 4 | import LogOut from "../components/LogOut" 5 | import { getMarketStatus, setUserName } from "../utils/utils" 6 | import LiveClock from "../components/clock"; 7 | 8 | 9 | export default class Header extends React.Component { 10 | 11 | componentDidMount() { 12 | getMarketStatus() 13 | setUserName() 14 | setTimeout(() => { 15 | this.forceUpdate() 16 | }, 2000); 17 | } 18 | 19 | render() { 20 | return ( 21 |
22 | 74 | 75 | {/* View Me on Github */} 76 |
77 | ) 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /v1/src/components/BuyPage.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { connect } from "react-redux"; 3 | import AddCompany from "../Actions/AddCompany"; 4 | import BuyAction from "../Actions/BuyAction"; 5 | import axios from "axios"; 6 | const as = require("as-type"); 7 | 8 | class BuyPage extends React.Component { 9 | constructor(props) { 10 | super(props); 11 | 12 | this.state = { 13 | error: false 14 | }; 15 | } 16 | 17 | handleOnSubmit = e => { 18 | e.preventDefault(); 19 | e.persist(); 20 | const company = e.target.elements.symbol.value; 21 | const quantity = as.integer(e.target.elements.quantity.value); 22 | axios 23 | .get(`https://api.iextrading.com/1.0/stock/${company}/batch?types=quote`) 24 | .then(data => { 25 | const buyPrice = data.data.quote.latestPrice; 26 | const companyDetails = { 27 | company, 28 | quantity, 29 | buyPrice, 30 | currPrice: as.float(data.data.quote.latestPrice).toFixed(2), 31 | shareWorth: as 32 | .float(quantity * data.data.quote.latestPrice) 33 | .toFixed(2), 34 | profitLoss: 0 35 | }; 36 | // console.log(this.props.money.money, companyDetails.shareWorth) 37 | if (this.props.money.money >= companyDetails.shareWorth) { 38 | this.props.subtractFromMoney(companyDetails.shareWorth); 39 | this.props.addData(companyDetails); 40 | 41 | e.target.elements.symbol.value = ""; 42 | e.target.elements.quantity.value = ""; 43 | 44 | this.props.history.push("/"); 45 | } else { 46 | this.setState(() => { 47 | return { 48 | error: true 49 | }; 50 | }); 51 | e.target.elements.symbol.value = ""; 52 | e.target.elements.quantity.value = ""; 53 | } 54 | }) 55 | .catch(e => { 56 | console.log(e); 57 | }); 58 | }; 59 | 60 | render() { 61 | return ( 62 |
63 |
64 |
65 | {" "} 66 |
71 |
72 | 75 | 83 |
84 | 85 |
86 | 89 | 98 |
99 | {this.state.error ? ( 100 |

You don't have enough money

101 | ) : ( 102 | undefined 103 | )} 104 | 107 |
108 |
109 |
110 |
111 | ); 112 | } 113 | } 114 | 115 | const mapStateToProps = state => { 116 | return { 117 | money: state.money 118 | }; 119 | }; 120 | 121 | const mapDispatchToProps = dispatch => { 122 | return { 123 | addData: companyDetails => { 124 | dispatch(AddCompany(companyDetails)); 125 | }, 126 | subtractFromMoney: buyValue => { 127 | dispatch(BuyAction(buyValue)); 128 | } 129 | }; 130 | }; 131 | 132 | export default connect( 133 | mapStateToProps, 134 | mapDispatchToProps 135 | )(BuyPage); 136 | -------------------------------------------------------------------------------- /v2/src/components/Signup.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import axios from "axios"; 3 | import { Link } from "react-router-dom"; 4 | 5 | interface State { 6 | email: String, 7 | name: String, 8 | password: String, 9 | error: String, 10 | loading: Boolean 11 | } 12 | 13 | class SignUp extends React.Component { 14 | 15 | state = { 16 | email: "", 17 | password: "", 18 | name: "", 19 | error: undefined, 20 | loading: false 21 | } 22 | 23 | handleChange = (e) => { 24 | this.setState({ 25 | [e.target.name]: [e.target.value] 26 | } as Pick) 27 | this.setState({error: undefined}) 28 | } 29 | 30 | handleSubmit = (e) => { 31 | e.preventDefault() 32 | 33 | this.setState({loading: true}) 34 | axios.post(`${process.env.REACT_APP_BACKEND_URL}/users/signup`, 35 | {email: this.state.email[0], password: this.state.password[0], name: this.state.name[0]}).then(data => { 36 | 37 | axios.post(`${process.env.REACT_APP_BACKEND_URL}/users/login`, {email: this.state.email[0], password: this.state.password[0]}).then(data => { 38 | sessionStorage.setItem("JWT_Token", data.headers["x-auth"]) 39 | sessionStorage.setItem("User_ID", data.data._id) 40 | 41 | axios.post(`${process.env.REACT_APP_BACKEND_URL}/state/money`, {money: 10000}, {headers: {"x-auth": sessionStorage.getItem("JWT_Token")}}) 42 | 43 | window.location.href = "/" 44 | }).catch(() => {this.setState({error: "Some Error Ocurred. Please Try Again Later", loading: false})}) 45 | }).catch((err) => { 46 | console.log(err) 47 | this.setState({error: "This Email Address already is registered or you have entered an invalid email address", loading: false}) 48 | }) 49 | } 50 | 51 | render() { 52 | return( 53 |
54 | 55 |
56 |

Sign Up

57 |

Log In

58 |
59 | 60 |
61 | 62 |
63 |

64 | 65 | 66 | 67 | 68 |

69 |
70 | 71 |
72 |

73 | 74 | 75 | 76 | 77 |

78 |
79 | 80 |
81 |

82 | 83 | 84 | 85 | 86 |

87 |

{this.state.error}

88 |
89 | 90 |
91 |
92 | {this.state.loading ? : } 93 |
94 |
95 |
96 |
97 | ) 98 | } 99 | } 100 | 101 | export default SignUp -------------------------------------------------------------------------------- /v1/src/components/Table.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { connect } from "react-redux"; 3 | import axios from "axios"; 4 | const as = require("as-type"); 5 | // Import React Table 6 | import ReactTable from "react-table"; 7 | import "react-table/react-table.css"; 8 | 9 | import SellAction from "../Actions/SellAction"; 10 | import DeleteCompany from "../Actions/DeleteCompany"; 11 | import Refresh from "../Actions/Refresh"; 12 | 13 | class Table extends React.Component { 14 | onSell(row) { 15 | this.props.sellStocks(as.float(this.props.data[row].shareWorth)); 16 | this.props.deleteCompany(row); 17 | } 18 | 19 | render() { 20 | // console.log(this.props.data) 21 | return ( 22 |
23 | 27 | String(row[filter.id]) === filter.value 28 | } 29 | data={this.props.data} 30 | columns={[ 31 | { 32 | Header: "Portfolio", 33 | columns: [ 34 | { 35 | Header: "Company Name", 36 | accessor: "company", 37 | Filter: ({ filter, onChange }) => ( 38 | onChange(event.target.value)} 43 | /> 44 | ) 45 | }, 46 | { 47 | Header: "Quantity", 48 | accessor: "quantity" 49 | }, 50 | { 51 | Header: "Buy Price", 52 | accessor: "buyPrice" 53 | }, 54 | { 55 | Header: "Current Price", 56 | accessor: "currPrice" 57 | }, 58 | { 59 | Header: "Share Worth", 60 | accessor: "shareWorth" 61 | }, 62 | { 63 | Header: "Profit/Loss", 64 | accessor: "profitLoss", 65 | id: "over", 66 | Cell: ({ value }) => (value >= 0 ? value : value), 67 | filterMethod: (filter, row) => { 68 | if (filter.value === "all") { 69 | return true; 70 | } 71 | if (filter.value === "Profit") { 72 | return row[filter.id] >= 0; 73 | } 74 | return row[filter.id] < 0; 75 | }, 76 | Filter: ({ filter, onChange }) => ( 77 | 86 | ) 87 | }, 88 | { 89 | Header: "Sell", 90 | accessor: "index", 91 | Cell: row => ( 92 | 95 | ) 96 | } 97 | ] 98 | } 99 | ]} 100 | defaultPageSize={10} 101 | className="-striped -highlight" 102 | style={{ 103 | background: "#F0FFFF", 104 | color: "black", 105 | fontSize: "20px", 106 | padding: "25px", 107 | marginTop: "0" 108 | }} 109 | /> 110 |
111 |
112 | ); 113 | } 114 | } 115 | 116 | const mapDispatchToProps = dispatch => { 117 | return { 118 | sellStocks: sellValue => { 119 | dispatch(SellAction(sellValue)); 120 | }, 121 | deleteCompany: index => { 122 | dispatch(DeleteCompany(index)); 123 | }, 124 | refresh: () => { 125 | dispatch(Refresh()); 126 | } 127 | }; 128 | }; 129 | 130 | const mapStatetoProps = state => { 131 | state.portfolio.forEach(childState => { 132 | const symbol = childState.company; 133 | axios 134 | .get(`https://api.iextrading.com/1.0/stock/${symbol}/batch?types=quote`) 135 | .then(data => { 136 | (childState.currPrice = as 137 | .float(data.data.quote.latestPrice) 138 | .toFixed(2)), 139 | (childState.shareWorth = as 140 | .float(childState.quantity * childState.currPrice) 141 | .toFixed(2)), 142 | (childState.profitLoss = 143 | childState.quantity * (childState.currPrice - childState.buyPrice)); 144 | }); 145 | }); 146 | 147 | return { 148 | data: state.portfolio, 149 | money: state.money 150 | }; 151 | }; 152 | 153 | export default connect( 154 | mapStatetoProps, 155 | mapDispatchToProps 156 | )(Table); 157 | -------------------------------------------------------------------------------- /v2/src/serviceWorker.ts: -------------------------------------------------------------------------------- 1 | // This optional code is used to register a service worker. 2 | // register() is not called by default. 3 | 4 | // This lets the app load faster on subsequent visits in production, and gives 5 | // it offline capabilities. However, it also means that developers (and users) 6 | // will only see deployed updates on subsequent visits to a page, after all the 7 | // existing tabs open on the page have been closed, since previously cached 8 | // resources are updated in the background. 9 | 10 | // To learn more about the benefits of this model and instructions on how to 11 | // opt-in, read http://bit.ly/CRA-PWA 12 | 13 | const isLocalhost = Boolean( 14 | window.location.hostname === 'localhost' || 15 | // [::1] is the IPv6 localhost address. 16 | window.location.hostname === '[::1]' || 17 | // 127.0.0.1/8 is considered localhost for IPv4. 18 | window.location.hostname.match( 19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ 20 | ) 21 | ); 22 | 23 | type Config = { 24 | onSuccess?: (registration: ServiceWorkerRegistration) => void; 25 | onUpdate?: (registration: ServiceWorkerRegistration) => void; 26 | }; 27 | 28 | export function register(config?: Config) { 29 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 30 | // The URL constructor is available in all browsers that support SW. 31 | const publicUrl = new URL( 32 | (process as { env: { [key: string]: string } }).env.PUBLIC_URL, 33 | window.location.href 34 | ); 35 | if (publicUrl.origin !== window.location.origin) { 36 | // Our service worker won't work if PUBLIC_URL is on a different origin 37 | // from what our page is served on. This might happen if a CDN is used to 38 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374 39 | return; 40 | } 41 | 42 | window.addEventListener('load', () => { 43 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 44 | 45 | if (isLocalhost) { 46 | // This is running on localhost. Let's check if a service worker still exists or not. 47 | checkValidServiceWorker(swUrl, config); 48 | 49 | // Add some additional logging to localhost, pointing developers to the 50 | // service worker/PWA documentation. 51 | navigator.serviceWorker.ready.then(() => { 52 | console.log( 53 | 'This web app is being served cache-first by a service ' + 54 | 'worker. To learn more, visit http://bit.ly/CRA-PWA' 55 | ); 56 | }); 57 | } else { 58 | // Is not localhost. Just register service worker 59 | registerValidSW(swUrl, config); 60 | } 61 | }); 62 | } 63 | } 64 | 65 | function registerValidSW(swUrl: string, config?: Config) { 66 | navigator.serviceWorker 67 | .register(swUrl) 68 | .then(registration => { 69 | registration.onupdatefound = () => { 70 | const installingWorker = registration.installing; 71 | if (installingWorker == null) { 72 | return; 73 | } 74 | installingWorker.onstatechange = () => { 75 | if (installingWorker.state === 'installed') { 76 | if (navigator.serviceWorker.controller) { 77 | // At this point, the updated precached content has been fetched, 78 | // but the previous service worker will still serve the older 79 | // content until all client tabs are closed. 80 | console.log( 81 | 'New content is available and will be used when all ' + 82 | 'tabs for this page are closed. See http://bit.ly/CRA-PWA.' 83 | ); 84 | 85 | // Execute callback 86 | if (config && config.onUpdate) { 87 | config.onUpdate(registration); 88 | } 89 | } else { 90 | // At this point, everything has been precached. 91 | // It's the perfect time to display a 92 | // "Content is cached for offline use." message. 93 | console.log('Content is cached for offline use.'); 94 | 95 | // Execute callback 96 | if (config && config.onSuccess) { 97 | config.onSuccess(registration); 98 | } 99 | } 100 | } 101 | }; 102 | }; 103 | }) 104 | .catch(error => { 105 | console.error('Error during service worker registration:', error); 106 | }); 107 | } 108 | 109 | function checkValidServiceWorker(swUrl: string, config?: Config) { 110 | // Check if the service worker can be found. If it can't reload the page. 111 | fetch(swUrl) 112 | .then(response => { 113 | // Ensure service worker exists, and that we really are getting a JS file. 114 | const contentType = response.headers.get('content-type'); 115 | if ( 116 | response.status === 404 || 117 | (contentType != null && contentType.indexOf('javascript') === -1) 118 | ) { 119 | // No service worker found. Probably a different app. Reload the page. 120 | navigator.serviceWorker.ready.then(registration => { 121 | registration.unregister().then(() => { 122 | window.location.reload(); 123 | }); 124 | }); 125 | } else { 126 | // Service worker found. Proceed as normal. 127 | registerValidSW(swUrl, config); 128 | } 129 | }) 130 | .catch(() => { 131 | console.log( 132 | 'No internet connection found. App is running in offline mode.' 133 | ); 134 | }); 135 | } 136 | 137 | export function unregister() { 138 | if ('serviceWorker' in navigator) { 139 | navigator.serviceWorker.ready.then(registration => { 140 | registration.unregister(); 141 | }); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /v2/src/components/Buy.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import axios from "axios"; 3 | import { connect } from "react-redux"; 4 | import { NavLink } from "react-router-dom"; 5 | 6 | import { RoundOf } from "../utils/utils"; 7 | import BuyAction from "../actions/Buy"; 8 | import Addcompany from "../actions/Addcompany"; 9 | 10 | import { history } from "../router/Approuter"; 11 | 12 | interface State { 13 | symbol: string, 14 | quantity: number | string, 15 | shareWorth: number, 16 | loader: boolean, 17 | symerror: string, 18 | quanerror: string 19 | } 20 | 21 | class Buy extends React.Component { 22 | 23 | state = { 24 | symbol: "", 25 | quantity: "", 26 | shareWorth: 0, 27 | loader: false, 28 | symerror: "", 29 | quanerror: "" 30 | } 31 | 32 | handleSubmit = e => { 33 | e.preventDefault(); 34 | 35 | this.setState({loader: true}); 36 | if(Number(this.state.quantity) <= 0 || Number(this.state.quantity) % 1 !== 0) { 37 | this.setState({quanerror: "Please enter a Positive Integer as quantity", loader: false, symbol: "", quantity: ""}) 38 | return -1; 39 | } 40 | 41 | axios 42 | .get(`${process.env.REACT_APP_API_URL}/${String(this.state.symbol).trim()}/batch?types=quote`) 43 | .then(data => { 44 | 45 | const shareWorth = RoundOf(data.data.quote.latestPrice * Number(this.state.quantity), 2); 46 | 47 | if ( shareWorth > this.props.money.money ) { 48 | this.setState({ 49 | quanerror: "Don't have enough cash", 50 | loader: false, 51 | symbol: "", 52 | quantity: "" 53 | }); 54 | return -1; 55 | } else { 56 | this.setState({shareWorth}); 57 | this.setState({loader: false}); 58 | 59 | const companyDetails = { 60 | company: this.state.symbol[0], 61 | quantity: this.state.quantity[0], 62 | shareWorth: this.state.shareWorth, 63 | companyName: data.data.quote.companyName, 64 | currPrice: data.data.quote.latestPrice, 65 | buyPrice: data.data.quote.latestPrice, 66 | profitLoss: 0 67 | } 68 | 69 | 70 | 71 | axios.post(`${process.env.REACT_APP_BACKEND_URL}/state/company`, companyDetails, {headers: {"x-auth": sessionStorage.getItem("JWT_Token")}}).then((data) => { 72 | this.props.addCompany(data.data); 73 | this.props.subtractFromMoney(this.state.shareWorth); 74 | this.setState({ 75 | symbol: "", 76 | quantity: "" 77 | }) 78 | 79 | history.push("/"); 80 | }) 81 | } 82 | } 83 | ).catch(() => { 84 | this.setState({symerror: "Please check if you have entered correct symbol", loader: false}) 85 | }) 86 | } 87 | 88 | handleOnChange = e => { 89 | this.setState({ 90 | [e.target.name] : [e.target.value] 91 | } as Pick ) 92 | 93 | this.setState({ 94 | symerror: "", 95 | quanerror: "" 96 | }) 97 | } 98 | 99 | render() { 100 | return ( 101 |
102 |
103 | 104 |

Total Money Left : $ {this.props.money.money}

105 | 106 |
107 | 108 |
109 | 110 |
111 | 112 |

{this.state.symerror == "" ? undefined : this.state.symerror}

113 |
114 |
115 | 116 |
117 | 118 |
119 | 120 |

{this.state.quanerror == "" ? undefined : this.state.quanerror}

121 |
122 |
123 | 124 |
125 |
126 | {this.state.loader ? : } 127 |
128 |
129 |
130 | 131 | 132 | 133 | 134 | 135 |
136 | 137 |
138 | ) 139 | }; 140 | }; 141 | 142 | const mapStateToProps = (state) => { 143 | return { 144 | money: state.money 145 | }; 146 | }; 147 | 148 | const mapDispatchToProps = (dispatch) => { 149 | return { 150 | subtractFromMoney: buyValue => { 151 | dispatch(BuyAction(buyValue)); 152 | }, 153 | addCompany: companyDetails => { 154 | dispatch(Addcompany(companyDetails)) 155 | } 156 | } 157 | } 158 | 159 | export default connect(mapStateToProps, mapDispatchToProps)(Buy); -------------------------------------------------------------------------------- /v2/src/components/View.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import axios from "axios"; 3 | import Autosuggest from 'react-autosuggest'; 4 | 5 | import store from "../reduxStore/store" 6 | import StockAreaChart from "./StockAreaChart" 7 | import { RoundOf } from "../utils/utils" 8 | 9 | const _ = require("lodash"); 10 | 11 | const getSuggestions = value => { 12 | const inputValue = value.trim().toLowerCase(); 13 | const inputLength = inputValue.length; 14 | 15 | return inputLength === 0 ? [] : store.getState().symbol.filter(sym => { 16 | return sym.toLowerCase().slice(0, inputLength) === inputValue 17 | } 18 | ).slice(0, 5); 19 | }; 20 | 21 | const getSuggestionValue = suggestion => suggestion; 22 | 23 | const renderSuggestion = suggestion => ( 24 |
25 | {suggestion} 26 |
27 | ); 28 | 29 | class View extends React.Component { 30 | 31 | state = { 32 | symbol: "", 33 | quote: null, 34 | loading: false, 35 | error: "", 36 | data: [], 37 | dataLoad: false, 38 | suggestions: [] 39 | } 40 | 41 | getData = () => { 42 | this.setState({loading: true}) 43 | axios. 44 | get(`${process.env.REACT_APP_API_URL}/${String(this.state.symbol)}/batch?types=quote`). 45 | then(data => { 46 | this.setState({quote: data.data.quote, symbol: "", loading: false}); 47 | }).catch(() => { 48 | this.setState({error: "Please check the Stock Symbol again", loading: false}) 49 | }) 50 | } 51 | 52 | handleEnterPress = (e) => { 53 | if(e.key === 'Enter') { 54 | this.getData(); 55 | this.getStockData() 56 | } 57 | } 58 | 59 | handleClick = () => { 60 | this.getData(); 61 | this.getStockData() 62 | } 63 | 64 | handleOnChange = (e, { newValue }) => { 65 | this.setState({symbol: newValue, quote: null, error: "", loading: false, dataLoad: false}) 66 | } 67 | 68 | onSuggestionsFetchRequested = ({ value }) => { 69 | this.setState({ 70 | suggestions: getSuggestions(value) 71 | }); 72 | }; 73 | 74 | onSuggestionsClearRequested = () => { 75 | this.setState({ 76 | suggestions: [] 77 | }); 78 | }; 79 | 80 | getStockData = () => { 81 | let stockData = [] 82 | axios.get(`${process.env.REACT_APP_API_URL}/${this.state.symbol}/chart/1y?chartInterval=10`).then(data => { 83 | data.data.map(item => { 84 | let temp = { 85 | "date": item.date, 86 | "price": RoundOf(item.close, 2) 87 | } 88 | stockData.push(temp) 89 | }) 90 | 91 | this.setState({data: stockData, dataLoad: true}) 92 | }) 93 | } 94 | 95 | onSuggestionSelected = () => { 96 | this.getData() 97 | this.getStockData() 98 | } 99 | 100 | render() { 101 | 102 | const { symbol, suggestions } = this.state; 103 | 104 | const inputProps = { 105 | placeholder: "Enter a NASDAQ Stock Symbol(Ex.AAPL)", 106 | value: symbol, 107 | onChange: this.handleOnChange, 108 | onKeyPress: this.handleEnterPress 109 | }; 110 | 111 | return ( 112 |
113 |
114 |
115 | 116 | 117 | 118 | {/* */} 128 | 137 | {this.state.error ?

{this.state.error}

: undefined} 138 |
139 | 140 |
141 | {this.state.loading ? : 142 | } 143 |
144 |
145 | 146 | {_.isEmpty(this.state.quote) ? undefined : 147 |
148 |
    149 |
  • Company Name: {this.state.quote.companyName}
  • 150 |
  • Symbol: {this.state.quote.symbol}
  • 151 |
  • Sector: {this.state.quote.sector}
  • 152 |
  • Current Price: $ {this.state.quote.latestPrice}
  • 153 |
  • Open Price: $ {this.state.quote.open}
  • 154 |
  • Hign Price $ {this.state.quote.high}
  • 155 |
  • Low Price $ {this.state.quote.low}
  • 156 |
  • Close Price: $ {this.state.quote.close}
  • 157 |
  • 52 Week High: $ {this.state.quote.week52High}
  • 158 |
  • 52 Week Low: $ {this.state.quote.week52Low}
  • 159 |
160 |
161 | } 162 | 163 | {(!this.state.dataLoad || _.isEmpty(this.state.quote)) ? undefined : 164 |
165 |

Historical Data of {this.state.quote.companyName}

166 | 167 |
168 | } 169 | 170 | 171 |
172 | ) 173 | }; 174 | }; 175 | 176 | export default View; -------------------------------------------------------------------------------- /v2/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "requires": true, 3 | "lockfileVersion": 1, 4 | "dependencies": { 5 | "asap": { 6 | "version": "2.0.6", 7 | "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", 8 | "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" 9 | }, 10 | "core-js": { 11 | "version": "1.2.7", 12 | "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", 13 | "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=" 14 | }, 15 | "encoding": { 16 | "version": "0.1.12", 17 | "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", 18 | "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", 19 | "requires": { 20 | "iconv-lite": "~0.4.13" 21 | } 22 | }, 23 | "fbjs": { 24 | "version": "0.8.17", 25 | "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz", 26 | "integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=", 27 | "requires": { 28 | "core-js": "^1.0.0", 29 | "isomorphic-fetch": "^2.1.1", 30 | "loose-envify": "^1.0.0", 31 | "object-assign": "^4.1.0", 32 | "promise": "^7.1.1", 33 | "setimmediate": "^1.0.5", 34 | "ua-parser-js": "^0.7.18" 35 | } 36 | }, 37 | "iconv-lite": { 38 | "version": "0.4.24", 39 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 40 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 41 | "requires": { 42 | "safer-buffer": ">= 2.1.2 < 3" 43 | } 44 | }, 45 | "is-stream": { 46 | "version": "1.1.0", 47 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", 48 | "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" 49 | }, 50 | "isomorphic-fetch": { 51 | "version": "2.2.1", 52 | "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", 53 | "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", 54 | "requires": { 55 | "node-fetch": "^1.0.1", 56 | "whatwg-fetch": ">=0.10.0" 57 | } 58 | }, 59 | "js-tokens": { 60 | "version": "4.0.0", 61 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 62 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" 63 | }, 64 | "loose-envify": { 65 | "version": "1.4.0", 66 | "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", 67 | "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", 68 | "requires": { 69 | "js-tokens": "^3.0.0 || ^4.0.0" 70 | } 71 | }, 72 | "moment": { 73 | "version": "2.19.3", 74 | "resolved": "https://registry.npmjs.org/moment/-/moment-2.19.3.tgz", 75 | "integrity": "sha1-vbmdJw1tf9p4zA+6zoVeJ/59pp8=" 76 | }, 77 | "moment-timezone": { 78 | "version": "0.5.13", 79 | "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.13.tgz", 80 | "integrity": "sha1-mc5cfYJyYusPH3AgRBd/YHRde5A=", 81 | "requires": { 82 | "moment": ">= 2.9.0" 83 | } 84 | }, 85 | "node-fetch": { 86 | "version": "1.7.3", 87 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", 88 | "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", 89 | "requires": { 90 | "encoding": "^0.1.11", 91 | "is-stream": "^1.0.1" 92 | } 93 | }, 94 | "object-assign": { 95 | "version": "4.1.1", 96 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 97 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 98 | }, 99 | "promise": { 100 | "version": "7.3.1", 101 | "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", 102 | "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", 103 | "requires": { 104 | "asap": "~2.0.3" 105 | } 106 | }, 107 | "prop-types": { 108 | "version": "15.6.2", 109 | "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz", 110 | "integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==", 111 | "requires": { 112 | "loose-envify": "^1.3.1", 113 | "object-assign": "^4.1.1" 114 | } 115 | }, 116 | "react": { 117 | "version": "16.7.0", 118 | "resolved": "https://registry.npmjs.org/react/-/react-16.7.0.tgz", 119 | "integrity": "sha512-StCz3QY8lxTb5cl2HJxjwLFOXPIFQp+p+hxQfc8WE0QiLfCtIlKj8/+5tjjKm8uSTlAW+fCPaavGFS06V9Ar3A==", 120 | "requires": { 121 | "loose-envify": "^1.1.0", 122 | "object-assign": "^4.1.1", 123 | "prop-types": "^15.6.2", 124 | "scheduler": "^0.12.0" 125 | } 126 | }, 127 | "react-live-clock": { 128 | "version": "3.0.0", 129 | "resolved": "https://registry.npmjs.org/react-live-clock/-/react-live-clock-3.0.0.tgz", 130 | "integrity": "sha512-O8RzHC928sejDKhguT/u//8nI4YcFZDmAGQUfG/jY+mbCPSYm2TiHdQWXe0QbxbCyioLddzgG2/JISeE6K66gA==", 131 | "requires": { 132 | "moment": "2.19.3", 133 | "moment-timezone": "0.5.13", 134 | "prop-types": "15.5.10" 135 | }, 136 | "dependencies": { 137 | "prop-types": { 138 | "version": "15.5.10", 139 | "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.5.10.tgz", 140 | "integrity": "sha1-J5ffwxJhguOpXj37suiT3ddFYVQ=", 141 | "requires": { 142 | "fbjs": "^0.8.9", 143 | "loose-envify": "^1.3.1" 144 | } 145 | } 146 | } 147 | }, 148 | "safer-buffer": { 149 | "version": "2.1.2", 150 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 151 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 152 | }, 153 | "scheduler": { 154 | "version": "0.12.0", 155 | "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.12.0.tgz", 156 | "integrity": "sha512-t7MBR28Akcp4Jm+QoR63XgAi9YgCUmgvDHqf5otgAj4QvdoBE4ImCX0ffehefePPG+aitiYHp0g/mW6s4Tp+dw==", 157 | "requires": { 158 | "loose-envify": "^1.1.0", 159 | "object-assign": "^4.1.1" 160 | } 161 | }, 162 | "setimmediate": { 163 | "version": "1.0.5", 164 | "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", 165 | "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" 166 | }, 167 | "ua-parser-js": { 168 | "version": "0.7.19", 169 | "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.19.tgz", 170 | "integrity": "sha512-T3PVJ6uz8i0HzPxOF9SWzWAlfN/DavlpQqepn22xgve/5QecC+XMCAtmUNnY7C9StehaV6exjUCI801lOI7QlQ==" 171 | }, 172 | "whatwg-fetch": { 173 | "version": "3.0.0", 174 | "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz", 175 | "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==" 176 | } 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /v2/backend/assets/symbols.txt: -------------------------------------------------------------------------------- 1 | ['YI', 'PIH', 'PIHPP', 'TURN', 'FLWS', 'FCCY', 'SRCE', 'VNET', 'TWOU', 'QFIN', 'TPNL', 'JOBS', 'EGHT', 'AAON', 'ABEO', 'ABEOW', 'ABIL', 'ABMD', 'ABP', 'AXAS', 'ACIU', 'ACIA', 'ACTG', 'ACHC', 'ACAD', 'ACST', 'AXDX', 'ACCP', 'XLRN', 'ANCX', 'ARAY', 'ACRX', 'ACER', 'ACET', 'AKAO', 'ACHV', 'ACHN', 'ACIW', 'ACRS', 'ACMR', 'ACNB', 'ACOR', 'ATVI', 'ADMS', 'ADMP', 'ADAP', 'ADUS', 'AEY', 'IOTS', 'ADIL', 'ADILW', 'ADMA', 'ADBE', 'ADOM', 'ADTN', 'ADRO', 'ADES', 'AEIS', 'AMD', 'ADXS', 'ADVM', 'DWMC', 'DWSH', 'ACT', 'AEGN', 'AGLE', 'AEHR', 'AMTX', 'AERI', 'AVAV', 'ARPO', 'AEZS', 'AEMD', 'GNMX', 'AFMD', 'AGEN', 'AGRX', 'AGYS', 'AGIO', 'AGMH', 'AGNC', 'AGNCB', 'AGNCN', 'AGFS', 'AGFSW', 'ALRN', 'AIMT', 'AIRT', 'ATSG', 'AIRG', 'AMCN', 'AKAM', 'AKTX', 'AKCA', 'AKBA', 'AKER', 'AKRX', 'AKTS', 'ALRM', 'ALSK', 'ALAC', 'ALACR', 'ALACU', 'ALACW', 'ALBO', 'ABDC', 'ALDR', 'ALDX', 'ALXN', 'ALCO', 'ALGN', 'ALIM', 'ALYA', 'ALJJ', 'ALKS', 'ALLK', 'ABTX', 'ALGT', 'ALGR', 'ALGRR', 'ALGRU', 'ALGRW', 'ALNA', 'AMMA', 'ARLP', 'LNT', 'AHPI', 'AMOT', 'ALQA', 'ALLO', 'ALLT', 'MDRX', 'ALNY', 'AOSL', 'GOOG', 'GOOGL', 'SMCP', 'ATEC', 'ALPN', 'AMR', 'AMRWW', 'AABA', 'ALTR', 'ALT', 'ASPS', 'AIMC', 'ALTM', 'ALZH', 'AMAG', 'AMAL', 'AMRN', 'AMRK', 'AMZN', 'AMBC', 'AMBCW', 'AMBA', 'AMCX', 'AMCI', 'AMCIU', 'AMCIW', 'DOX', 'AMED', 'UHAL', 'AMRH', 'AMRHW', 'ATAX', 'AMOV', 'AAL', 'AETI', 'AFIN', 'AMNB', 'ANAT', 'AOBC', 'APEI', 'AMRB', 'AMSWA', 'AMSC', 'AMWD', 'CRMT', 'ABCB', 'AMSF', 'ASRV', 'ASRVP', 'ATLO', 'AMGN', 'FOLD', 'AMKR', 'AMPH', 'IBUY', 'ASYS', 'AMRS', 'ADI', 'ANAB', 'AVXL', 'ANGI', 'ANGO', 'ANIP', 'ANIK', 'ANIX', 'ANSS', 'ATRS', 'APLS', 'APOG', 'APEN', 'AINV', 'AMEH', 'APPF', 'APPN', 'AAPL', 'ARCI', 'APDN', 'APDNW', 'AGTC', 'AMAT', 'AAOI', 'AREX', 'APTI', 'APRI', 'APVO', 'APTX', 'APM', 'APTO', 'AQMS', 'AQB', 'AQST', 'AQXP', 'ARDM', 'PETX', 'ARAV', 'ABUS', 'ARCW', 'ABIO', 'RKDA', 'ARCB', 'ACGL', 'ACGLO', 'ACGLP', 'FUV', 'ARCE', 'ARCT', 'ARDX', 'ARNA', 'ARCC', 'ARGX', 'ARDS', 'ARKR', 'ARTX', 'ARQL', 'ARRY', 'ARRS', 'DWCR', 'DWAT', 'AROW', 'ARWR', 'ASNS', 'ARTNA', 'ARTW', 'ARVN', 'ARYA', 'ARYAU', 'ARYAW', 'ASNA', 'ASND', 'ASCMA', 'APWC', 'ASLN', 'ASML', 'ASPU', 'AZPN', 'ASMB', 'ASRT', 'ASFI', 'ASTE', 'ATRO', 'ALOT', 'ASTC', 'ASUR', 'ASV', 'ATAI', 'ATRA', 'ATHN', 'ATNX', 'ATHX', 'AAME', 'ACBI', 'AY', 'ATLC', 'AAWW', 'AFH', 'AFHBL', 'TEAM', 'ATNI', 'ATOM', 'ATOS', 'ATRC', 'ATRI', 'ATIS', 'ATISW', 'ATTU', 'LIFE', 'AUBN', 'BOLD', 'AUDC', 'AEYE', 'AUPH', 'EARS', 'JG', 'ADSK', 'AUTL', 'ADP', 'AUTO', 'AVDL', 'AVCO', 'ATXI', 'AVEO', 'AVNW', 'CDMO', 'CDMOP', 'AVID', 'AVGR', 'CAR', 'AVT', 'AVRO', 'AWRE', 'ACLS', 'AXGN', 'AAXN', 'AXNX', 'AXON', 'AXSM', 'AXTI', 'AYTU', 'AZRX', 'BCOM', 'RILY', 'RILYG', 'RILYH', 'RILYI', 'RILYL', 'RILYZ', 'BOSC', 'BIDU', 'BCPC', 'BLDP', 'BANF', 'BANFP', 'BCTF', 'BAND', 'BFC', 'BOCH', 'BMRC', 'BMLP', 'BKSC', 'BOTJ', 'OZK', 'BSVN', 'BFIN', 'BWFG', 'BANR', 'BZUN', 'DFVL', 'DFVS', 'DLBS', 'DTUL', 'DTUS', 'DTYL', 'DTYS', 'FLAT', 'STPP', 'TAPR', 'BBSI', 'GOLD', 'BSET', 'ZTEST', 'BCML', 'BCBP', 'BECN', 'BBGI', 'BBBY', 'BGNE', 'BELFA', 'BELFB', 'BLPH', 'BLCM', 'BNCL', 'BNFT', 'BNTC', 'BNTCW', 'BRY', 'BYSI', 'BGCP', 'BGFV', 'BRPA', 'BRPAR', 'BRPAU', 'BRPAW', 'BILI', 'BASI', 'ORPN', 'BIOC', 'BCRX', 'BDSI', 'BFRA', 'BIIB', 'BHTG', 'BKYI', 'BIOL', 'BLFS', 'BLRX', 'BMRN', 'BMRA', 'BNGO', 'BNGOW', 'BVXV', 'BVXVW', 'BPTH', 'BIOS', 'BSGM', 'BSTC', 'TECH', 'BEAT', 'BTAI', 'BCAC', 'BCACR', 'BCACU', 'BCACW', 'BJRI', 'BBOX', 'BRAC', 'BRACR', 'BRACU', 'BRACW', 'BLKB', 'BL', 'BKCC', 'TCPC', 'BLNK', 'BLNKW', 'BLMN', 'BCOR', 'BLBD', 'BHBK', 'BLUE', 'BKEP', 'BKEPP', 'BPMC', 'ITEQ', 'BMCH', 'WIFI', 'BOJA', 'BOKF', 'BOKFL', 'BNSO', 'BKNG', 'BRQS', 'BOMN', 'BPFH', 'EPAY', 'BOXL', 'BWMCU', 'BBRX', 'BCLI', 'BVNSC', 'BDGE', 'BLIN', 'BWB', 'BRID', 'BCOV', 'BHF', 'BHFAL', 'AVGO', 'BVSN', 'BYFC', 'BWEN', 'BPY', 'BPR', 'BPRAP', 'BRKL', 'BRKS', 'DOOO', 'BRKR', 'BMTC', 'BLMT', 'BSQR', 'BLDR', 'BFST', 'CFFI', 'CHRW', 'CCMP', 'CDNS', 'CDZI', 'CZR', 'CSTE', 'CLBS', 'CHY', 'CHI', 'CCD', 'CHW', 'CGO', 'CSQ', 'CAMP', 'CVGW', 'CALA', 'CALM', 'CLMT', 'CRUSC', 'CLXT', 'CATC', 'CAC', 'CAMT', 'CSIQ', 'CGIX', 'CPHC', 'CBNK', 'CCBG', 'CPLP', 'CSWC', 'CSWCL', 'CPTA', 'CPTAG', 'CPTAL', 'CFFN', 'CAPR', 'CSTR', 'CPST', 'CARA', 'CBLK', 'CARB', 'CSII', 'CDLX', 'CATM', 'CDNA', 'CECO', 'CTRE', 'CARG', 'CARO', 'CART', 'CRZO', 'TAST', 'CARV', 'CASM', 'CASA', 'CWST', 'CASY', 'CASI', 'CASS', 'CATB', 'CBIO', 'CPRX', 'CATS', 'CATY', 'CGVIC', 'CIVEC', 'CVCO', 'CBFV', 'CBAT', 'CBMB', 'CBOE', 'CBTX', 'CDK', 'CDW', 'CECE', 'CELC', 'CELG', 'CELGZ', 'CLDX', 'APOP', 'APOPW', 'CLRB', 'CLRBW', 'CLRBZ', 'CLLS', 'CBMG', 'CLSN', 'CELH', 'CYAD', 'CETX', 'CETXP', 'CETXW', 'CDEV', 'CSFL', 'CETV', 'CFBK', 'CENT', 'CENTA', 'CVCY', 'CNTX', 'CTRC', 'CENX', 'CNBKA', 'CNTY', 'CRNT', 'CERC', 'CERN', 'CERS', 'KOOL', 'CEVA', 'CFFAU', 'CSBR', 'CYOU', 'BURG', 'CTHR', 'GTLS', 'CHTR', 'CTAC', 'CTACU', 'CTACW', 'CHKP', 'CHEK', 'CHEKW', 'CHEKZ', 'CKPT', 'CEMI', 'CHFC', 'CCXI', 'CHMG', 'CHKE', 'CHFS', 'CHMA', 'CSSE', 'CSSEP', 'PLCE', 'CMRX', 'CADC', 'CAAS', 'CBPO', 'CCCL', 'GLG', 'CCRC', 'JRJC', 'HGSH', 'CIFS', 'CJJD', 'CLDC', 'CHNR', 'CREG', 'CNTF', 'CXDC', 'CCIH', 'CNET', 'IMOS', 'CDXC', 'CHSCL', 'CHSCM', 'CHSCN', 'CHSCO', 'CHSCP', 'CHDN', 'CHUY', 'CDTX', 'CMCT', 'CMCTP', 'CMPR', 'CINF', 'CIDM', 'CTAS', 'CRUS', 'CSCO', 'CTRN', 'CTXR', 'CTXRW', 'CZNC', 'CZWI', 'CZFC', 'CIZN', 'CTXS', 'CHCO', 'CIVB', 'CIVBP', 'CLAR', 'CLNE', 'CACG', 'YLDE', 'LRGE', 'CLFD', 'CLRO', 'CLSD', 'CLIR', 'CLIRW', 'CMTA', 'CBLI', 'CLVS', 'CLPS', 'CMFN', 'CMFNL', 'CMSS', 'CMSSR', 'CMSSU', 'CMSSW', 'CME', 'CCNE', 'CCB', 'COKE', 'COCP', 'CODA', 'CDXS', 'CODX', 'CVLY', 'JVA', 'CCOI', 'CGNX', 'CTSH', 'CWBR', 'COHR', 'CHRS', 'COHU', 'CLCT', 'COLL', 'CIGI', 'CLGN', 'CBAN', 'COLB', 'CLBK', 'COLM', 'CMCO', 'CMCSA', 'CCNI', 'CBSH', 'CBSHP', 'CVGI', 'COMM', 'JCS', 'ESXB', 'CFBI', 'CYHHZ', 'CTBI', 'CWBC', 'CVLT', 'CGEN', 'CPSI', 'CTG', 'SCOR', 'CHCI', 'CMTL', 'CNAT', 'CNCE', 'BBCP', 'BBCPW', 'CDOR', 'CFMS', 'CNFR', 'CNFRL', 'CNMD', 'CTWS', 'CNOB', 'CONN', 'CNSL', 'CWCO', 'CNAC', 'CNACR', 'CNACU', 'CNACW', 'CNST', 'ROAD', 'CPSS', 'CFRX', 'CTRV', 'CTRL', 'CVON', 'AWSM', 'CPRT', 'CRBP', 'CORT', 'CORE', 'CSOD', 'CORV', 'CRVL', 'CRVS', 'CSGP', 'COST', 'CPAH', 'ICBK', 'COUP', 'CVTI', 'COWN', 'COWNL', 'COWNZ', 'PMTS', 'CPSH', 'CRAI', 'CBRL', 'BREW', 'CRAY', 'CREX', 'CREXW', 'CACC', 'DGLD', 'DSLV', 'GLDI', 'SLVO', 'TVIX', 'UGLD', 'USLV', 'USOI', 'VIIX', 'ZIV', 'CREE', 'CRESY', 'CRNX', 'CRSP', 'CRTO', 'CROX', 'CRON', 'CCRN', 'CRWS', 'CYRX', 'CYRXW', 'CSGS', 'CCLP', 'CSPI', 'CSWI', 'CSX', 'CTIC', 'CTIB', 'CTRP', 'CUE', 'CUI', 'CPIX', 'CMLS', 'CRIS', 'CUTR', 'CVBF', 'CVV', 'CYAN', 'CYBR', 'CYBE', 'CYCC', 'CYCCP', 'CBAY', 'CY', 'CYRN', 'CONE', 'CYTK', 'CTMX', 'CYTX', 'CYTXZ', 'CTSO', 'CYTR', 'DJCO', 'DAKT', 'DARE', 'DRIO', 'DRIOW', 'DZSI', 'DSKE', 'DSKEW', 'DAIO', 'DTSS', 'PLAY', 'DTEA', 'DFNL', 'DINT', 'DUSA', 'DWLD', 'DWSN', 'DBVT', 'DDMX', 'DDMXU', 'DDMXW', 'DCPH', 'DFRG', 'TACO', 'TACOW', 'DMPI', 'DELT', 'DNLI', 'DENN', 'XRAY', 'DDOC', 'DERM', 'DEST', 'DXLG', 'DSWL', 'DXCM', 'DFBH', 'DFBHU', 'DFBHW', 'DHXM', 'DMAC', 'DHIL', 'FANG', 'DCIX', 'DRNA', 'DFFN', 'DGII', 'DMRC', 'DRAD', 'DGLY', 'APPS', 'DCOM', 'DIOD', 'DISCA', 'DISCB', 'DISCK', 'DISH', 'DVCR', 'SAUC', 'DLHC', 'BOOM', 'DNBF', 'DOCU', 'DOGZ', 'DLTR', 'DLPN', 'DLPNW', 'DOMO', 'DGICA', 'DGICB', 'DMLP', 'DORM', 'DOVA', 'LYL', 'DBX', 'DCAR', 'DRYS', 'DSPG', 'DLTH', 'DNKN', 'DRRX', 'DXPE', 'DYSL', 'DYNT', 'DVAX', 'ETFC', 'SSP', 'EBMT', 'EGBN', 'EGLE', 'EFBI', 'EGRX', 'IGLE', 'EWBC', 'EML', 'EAST', 'EVGBC', 'EVSTC', 'EVFTC', 'EVLMC', 'OKDCC', 'EBAY', 'EBAYL', 'EBIX', 'ECHO', 'SATS', 'EEI', 'EDAP', 'EDGE', 'EDNT', 'EDIT', 'EDTX', 'EDTXU', 'EDTXW', 'EDUC', 'EGAN', 'EHTH', 'EIDX', 'EIGR', 'EKSO', 'LOCO', 'EMITF', 'ESLT', 'ERI', 'SOLO', 'SOLOW', 'ESIO', 'ECOR', 'EA', 'EFII', 'ELSE', 'ESBK', 'ELOX', 'ELTK', 'EMCI', 'EMCF', 'EMKR', 'EMMS', 'NYNY', 'ENTA', 'ECPG', 'WIRE', 'ENDP', 'ELGX', 'NDRA', 'NDRAW', 'EIGI', 'WATT', 'EFOI', 'EHR', 'ERII', 'ENG', 'ENOB', 'ENPH', 'ESGR', 'ESGRO', 'ESGRP', 'ETTX', 'ENFC', 'ENTG', 'ENTX', 'ENTXW', 'EBTC', 'EFSC', 'EPZM', 'PLUS', 'EQ', 'EQIX', 'EQBK', 'ERIC', 'ERIE', 'ERYP', 'ESCA', 'ESPR', 'ESQ', 'ESSA', 'EPIX', 'ESND', 'ESTA', 'ESTR', 'ESTRW', 'VBND', 'VUSE', 'VIDI', 'ETON', 'ETSY', 'CLWT', 'EDRY', 'EEFT', 'ESEA', 'EVLO', 'EVBG', 'EVK', 'EVER', 'MRAM', 'EVLV', 'EVOP', 'EVFM', 'EVGN', 'EVOK', 'EOLS', 'EVOL', 'EXAS', 'FLAG', 'ROBO', 'XELA', 'EXEL', 'EXFO', 'EXLS', 'EXPI', 'EXPE', 'EXPD', 'EXPO', 'STAY', 'XOG', 'EXTR', 'EYEG', 'EYEGW', 'EYEN', 'EYPT', 'EZPW', 'FFIV', 'FB', 'FLMN', 'FLMNW', 'DAVE', 'FANH', 'FARM', 'FMAO', 'FMNB', 'FAMI', 'FARO', 'FAST', 'FAT', 'FATE', 'FBSS', 'FLF', 'FSAC', 'FSACU', 'FSACW', 'FNHC', 'FENC', 'GSM', 'FFBW', 'FCSC', 'FGEN', 'FDBC', 'ONEQ', 'LION', 'FDUS', 'FDUSL', 'FRGI', 'FITB', 'FITBI', 'FISI', 'FNSR', 'FNJN', 'FTACU', 'FEYE', 'FBNC', 'FNLC', 'FRBA', 'BUSE', 'FBIZ', 'FCAP', 'FCBP', 'FCNCA', 'FCBC', 'FCCO', 'FDEF', 'FFBC', 'FFIN', 'THFF', 'FFNW', 'FFWM', 'FGBI', 'FHB', 'INBK', 'INBKL', 'FIBK', 'FRME', 'FMBH', 'FMBI', 'FNWB', 'FSFG', 'FSLR', 'FAAR', 'FPA', 'BICK', 'FBZ', 'FTHI', 'FCAL', 'FCAN', 'FTCS', 'FCEF', 'FCA', 'SKYY', 'RNDM', 'FDT', 'FDTS', 'FVC', 'FV', 'IFV', 'DDIV', 'DVOL', 'DVLU', 'DWPP', 'DALI', 'FDNI', 'FEM', 'RNEM', 'FEMB', 'FEMS', 'FTSM', 'FEP', 'FEUZ', 'FGM', 'FTGC', 'FTLB', 'HYLS', 'FHK', 'NFTY', 'FTAG', 'FTRI', 'LEGR', 'FPXI', 'FPXE', 'FJP', 'FEX', 'FTC', 'RNLC', 'FTA', 'FLN', 'LMBS', 'FMB', 'FMK', 'FNX', 'FNY', 'RNMC', 'FNK', 'FAD', 'FAB', 'MDIV', 'MCEF', 'FMHI', 'QABA', 'ROBT', 'FTXO', 'QCLN', 'GRID', 'CIBR', 'FTXG', 'CARZ', 'FTXN', 'FTXH', 'FTXD', 'FTXL', 'FONE', 'TDIV', 'FTXR', 'QQEW', 'QQXT', 'QTEC', 'AIRR', 'RDVY', 'RFAP', 'RFDI', 'RFEM', 'RFEU', 'FID', 'FTSL', 'FYX', 'FYC', 'RNSC', 'FYT', 'SDVY', 'FKO', 'FCVT', 'FDIV', 'FSZ', 'FIXD', 'TUSA', 'FKU', 'RNDV', 'FUNC', 'FUSB', 'MYFW', 'FCFS', 'SVVC', 'FSV', 'FISV', 'FIVE', 'FPRX', 'FVE', 'FIVN', 'FLEX', 'FLKS', 'FLXN', 'SKOR', 'LKOR', 'MBSD', 'ASET', 'ESGG', 'ESG', 'QLC', 'FPAY', 'FPAYW', 'FLXS', 'FLIR', 'FLNT', 'FLDM', 'FFIC', 'FNCB', 'FOMX', 'FOCS', 'FONR', 'FSCT', 'FRSX', 'FORM', 'FORTY', 'FORR', 'FRTA', 'FTNT', 'FBIO', 'FBIOP', 'FTSV', 'FMCI', 'FMCIU', 'FMCIW', 'FWRD', 'FORD', 'FWP', 'FOSL', 'FOXF', 'FRAN', 'FELE', 'FKLY', 'FRED', 'RAIL', 'FEIM', 'FRPT', 'FTDR', 'FTEO', 'FTR', 'FRPH', 'FSBW', 'FSBC', 'FTD', 'FTEK', 'FCEL', 'FLGT', 'FORK', 'FLL', 'FMAX', 'FULT', 'FNKO', 'FSNN', 'FTFT', 'FFHL', 'FVCB', 'WILC', 'GTHX', 'FOANC', 'GRBIC', 'MOGLC', 'PETZC', 'GAIA', 'GLPG', 'GALT', 'GLMD', 'GMDA', 'GLPI', 'GPIC', 'GRMN', 'GARS', 'GLIBA', 'GLIBP', 'GDS', 'GEMP', 'GENC', 'GFN', 'GFNCP', 'GFNSL', 'GENE', 'GNUS', 'GNMK', 'GNCA', 'GHDX', 'GNPX', 'GNST', 'GNTX', 'THRM', 'GEOS', 'GABC', 'GERN', 'GEVO', 'ROCK', 'GIGM', 'GIII', 'GILT', 'GILD', 'GBCI', 'GLAD', 'GLADD', 'GLADN', 'GOOD', 'GOODM', 'GOODO', 'GOODP', 'GAIN', 'GAINL', 'GAINM', 'LAND', 'LANDP', 'GLBZ', 'GBT', 'ENT', 'GBLI', 'GBLIL', 'GBLIZ', 'SELF', 'GWRS', 'DRIV', 'KRMA', 'DAX', 'EBIZ', 'FINX', 'AIQ', 'BFIT', 'SNSR', 'LNGR', 'MILN', 'CHIC', 'EFAS', 'QYLD', 'BOTZ', 'CATH', 'SOCL', 'ALTY', 'SRET', 'YLCO', 'GLBS', 'GLUU', 'GLYC', 'GOGO', 'GLNG', 'GMLP', 'GMLPP', 'DNJR', 'GDEN', 'GOGL', 'GBDC', 'GTIM', 'GBLK', 'GSHD', 'GPRO', 'GPAQ', 'GPAQU', 'GPAQW', 'GRSH', 'GRSHU', 'GRSHW', 'LOPE', 'GRVY', 'GECC', 'GECCL', 'GECCM', 'GEC', 'GLDD', 'GSBC', 'GRBK', 'GPP', 'GPRE', 'GCBC', 'GLAC', 'GLACR', 'GLACU', 'GLACW', 'GLRE', 'GRNQ', 'GSKY', 'GSUM', 'GRIF', 'GRFS', 'GRIN', 'GRTS', 'GRPN', 'OMAB', 'GGAL', 'GVP', 'GSIT', 'GSVC', 'GTXI', 'GTYH', 'GTYHU', 'GTYHW', 'GNTY', 'GFED', 'GH', 'GIFI', 'GURE', 'GPOR', 'GWPH', 'GWGH', 'GYRO', 'HEES', 'HLG', 'HNRG', 'HALL', 'HALO', 'HBK', 'HLNE', 'HJLI', 'HJLIW', 'HWC', 'HWCPL', 'HAFC', 'HQCL', 'HONE', 'HLIT', 'HFGIC', 'HBIO', 'HCAP', 'HCAPZ', 'HAS', 'HA', 'HWKN', 'HWBK', 'HYAC', 'HYACU', 'HYACW', 'HAYN', 'HDS', 'HIIQ', 'HCSG', 'HQY', 'HSTM', 'HTLD', 'HTLF', 'HTBX', 'HEBT', 'HSII', 'HELE', 'HMNY', 'HSDT', 'HMTV', 'HNNA', 'HSIC', 'HTBK', 'HFWA', 'HCCI', 'MLHR', 'HRTX', 'HSKA', 'HX', 'HFFG', 'HIBB', 'SNLN', 'HPJ', 'HIHO', 'HIMX', 'HIFS', 'HSGX', 'HCCH', 'HCCHR', 'HCCHU', 'HCCHW', 'HMNF', 'HMSY', 'HOLI', 'HOLX', 'HBCP', 'HOMB', 'HFBL', 'HMST', 'HMTA', 'HTBI', 'FIXX', 'HOFT', 'HOPE', 'HFBC', 'HBNC', 'HZNP', 'HRZN', 'HDP', 'HPT', 'TWNK', 'TWNKW', 'HMHC', 'HWCC', 'HOVNP', 'HBMD', 'HTGM', 'HTHT', 'HUBG', 'HSON', 'HDSN', 'HUNT', 'HUNTU', 'HUNTW', 'HBAN', 'HBANN', 'HBANO', 'HURC', 'HURN', 'HCM', 'HBP', 'HVBC', 'HYGS', 'HYRE', 'IDSY', 'IIIV', 'IAC', 'IBKC', 'IBKCO', 'IBKCP', 'IBEX', 'ICAD', 'IEP', 'ICCH', 'ICFI', 'ICHR', 'ICLK', 'ICLR', 'ICON', 'ICUI', 'IPWR', 'IDEX', 'INVE', 'IDRA', 'IDXX', 'IESC', 'IROQ', 'IFMK', 'INFO', 'IIVI', 'KANG', 'IKNX', 'ILMN', 'ISNS', 'IMMR', 'ICCC', 'IMDZ', 'IMGN', 'IMMU', 'IMRN', 'IMRNW', 'IMMP', 'IMPV', 'PI', 'IMV', 'INCY', 'INDB', 'IBCP', 'IBTX', 'ILPT', 'IDSA', 'INFN', 'INFI', 'IFRX', 'III', 'IEA', 'IEAWW', 'IMKTA', 'INWK', 'INOD', 'IPHS', 'IOSP', 'INNT', 'ISSC', 'INVA', 'INGN', 'INOV', 'INO', 'INPX', 'INSG', 'NSIT', 'ISIG', 'INSM', 'INSE', 'IIIN', 'PODD', 'INSY', 'NTEC', 'IART', 'IDTI', 'IMTE', 'INTC', 'NTLA', 'IPCI', 'IPAR', 'ICPT', 'IDCC', 'TILE', 'LINK', 'IMI', 'INAP', 'IBOC', 'IMXI', 'ISCA', 'IGLD', 'IIJI', 'IDXG', 'XENT', 'INTX', 'IPLDP', 'IVAC', 'INTL', 'ITCI', 'XON', 'IIN', 'INTU', 'ISRG', 'PLW', 'ADRA', 'ADRD', 'ADRE', 'ADRU', 'PKW', 'PFM', 'PYZ', 'PEZ', 'PSL', 'PIZ', 'PIE', 'PXI', 'PFI', 'PTH', 'PRN', 'DWLV', 'PDP', 'DWAQ', 'DWAS', 'DWIN', 'DWTR', 'PTF', 'PUI', 'IDLB', 'PRFZ', 'PAGG', 'PSAU', 'PIO', 'PGJ', 'PEY', 'IPKW', 'PID', 'KBWB', 'KBWD', 'KBWY', 'KBWP', 'KBWR', 'LDRI', 'LALT', 'PNQI', 'PDBC', 'QQQ', 'USLB', 'PSCD', 'PSCC', 'PSCE', 'PSCF', 'PSCH', 'PSCI', 'PSCT', 'PSCM', 'PSCU', 'ISDX', 'ISDS', 'ISEM', 'IUS', 'IUSS', 'VRIG', 'PHO', 'ISTR', 'ISBC', 'ITIC', 'NVIV', 'IONS', 'IOVA', 'IPAS', 'IPGP', 'IPIC', 'CLRG', 'CSML', 'IQ', 'IRMD', 'IRTC', 'IRIX', 'IRDM', 'IRDMB', 'IRBT', 'IRWD', 'IRCP', 'SLQD', 'ISHG', 'SHY', 'TLT', 'IEI', 'IEF', 'AIA', 'USIG', 'COMT', 'ISTB', 'IXUS', 'IUSG', 'IUSV', 'IUSB', 'HEWG', 'SUSB', 'ESGD', 'ESGE', 'ESGU', 'SUSC', 'XT', 'FALN', 'IFEU', 'IFGL', 'BGRN', 'IGF', 'GNMA', 'HYXE', 'IGIB', 'IGOV', 'EMB', 'MBB', 'JKI', 'ACWX', 'ACWI', 'AAXJ', 'EWZS', 'MCHI', 'SCZ', 'EEMA', 'EMXC', 'EUFN', 'IEUS', 'RING', 'SDG', 'ENZL', 'QAT', 'TUR', 'UAE', 'IBB', 'SOXX', 'AMCA', 'EMIF', 'ICLN', 'WOOD', 'INDY', 'IJT', 'DVY', 'SHV', 'IGSB', 'PFF', 'ISRL', 'ITI', 'ITRM', 'ITRI', 'ITRN', 'IVENC', 'IVFGC', 'IVFVC', 'IZEA', 'JJSF', 'MAYS', 'JBHT', 'JCOM', 'JKHY', 'JACK', 'JAGX', 'JAKK', 'JRVR', 'JSML', 'JSMD', 'JASN', 'JASNW', 'JAZZ', 'JD', 'JSYN', 'JSYNR', 'JSYNU', 'JSYNW', 'JRSH', 'JBLU', 'JCTCF', 'JMU', 'JBSS', 'JOUT', 'JNCE', 'KALU', 'KALA', 'KALV', 'KMDA', 'KNDI', 'KPTI', 'KZIA', 'KBLM', 'KBLMR', 'KBLMU', 'KBLMW', 'KBSF', 'KCAP', 'KCAPL', 'KRNY', 'KELYA', 'KELYB', 'KMPH', 'KFFB', 'KEQU', 'KTCC', 'KZR', 'KFRC', 'KE', 'KBAL', 'KIN', 'KGJI', 'KINS', 'KNSA', 'KNSL', 'KIRK', 'KTOV', 'KTOVW', 'KLAC', 'KLXE', 'KOD', 'KONA', 'KOPN', 'KRNT', 'KOSS', 'KWEB', 'KTOS', 'KRYS', 'KLIC', 'KURA', 'KVHI', 'FSTR', 'LJPC', 'LSBK', 'LBAI', 'LKFN', 'LAKE', 'LRCX', 'LAMR', 'LANC', 'LNDC', 'LARK', 'LMRK', 'LMRKN', 'LMRKO', 'LMRKP', 'LE', 'LSTR', 'LNTH', 'LTRX', 'LSCC', 'LAUR', 'LAWS', 'LAZY', 'LCNB', 'LPTX', 'LEGH', 'LGCY', 'LTXB', 'DDBI', 'EDBI', 'INFR', 'LVHD', 'SQLV', 'UDBI', 'LACQ', 'LACQU', 'LACQW', 'LMAT', 'TREE', 'LEVL', 'LXRX', 'LX', 'LFAC', 'LFACU', 'LFACW', 'LGIH', 'LHCG', 'LLIT', 'LBRDA', 'LBRDK', 'LEXEA', 'LEXEB', 'LBTYA', 'LBTYB', 'LBTYK', 'LILA', 'LILAK', 'BATRA', 'BATRK', 'FWONA', 'FWONK', 'LSXMA', 'LSXMB', 'LSXMK', 'LTRPA', 'LTRPB', 'LCUT', 'LFVN', 'LWAY', 'LGND', 'LTBR', 'LPTH', 'LLEX', 'LMB', 'LLNW', 'LMST', 'LMNR', 'LINC', 'LECO', 'LIND', 'LINDW', 'LPCN', 'YVR', 'LQDA', 'LQDT', 'LFUS', 'LIVN', 'LOB', 'LIVE', 'LPSN', 'LIVX', 'LKQ', 'LMFA', 'LMFAW', 'LOGC', 'LOGI', 'LOGM', 'CNCR', 'CHNA', 'LONE', 'LOAC', 'LOACR', 'LOACU', 'LOACW', 'LOOP', 'LORL', 'LOXO', 'LPLA', 'LRAD', 'LYTS', 'LULU', 'LITE', 'LMNX', 'LUNA', 'LBC', 'MBTF', 'MCBC', 'MFNC', 'MTSI', 'MGNX', 'MDGL', 'MAGS', 'MGLN', 'MGTA', 'MGIC', 'MNGA', 'MGYR', 'MHLD', 'MMYT', 'MBUU', 'MLVF', 'MAMS', 'TUSK', 'RPIBC', 'MANH', 'LOAN', 'MNTX', 'MTEX', 'MNKD', 'MANT', 'MAPI', 'MARA', 'MCHX', 'MRIN', 'MARPS', 'MRNS', 'MRKR', 'MKTX', 'MRLN', 'MAR', 'MBII', 'MRTN', 'MMLP', 'MRVL', 'MASI', 'MCFT', 'MTCH', 'MTLS', 'MTRX', 'MAT', 'MATW', 'MXIM', 'MXWL', 'MBFI', 'MBFIO', 'MGRC', 'MDCA', 'MDRR', 'MFIN', 'MFINL', 'MTBC', 'MTBCP', 'MNOV', 'MDSO', 'MDGS', 'MDGSW', 'MDWD', 'MEDP', 'MEIP', 'MGTX', 'MLCO', 'MLNT', 'MLNX', 'MELR', 'MNLO', 'MTSL', 'MELI', 'AMTB', 'AMTBB', 'MBWM', 'MERC', 'MBIN', 'MRCY', 'MREO', 'EBSB', 'VIVO', 'MRBK', 'MMSI', 'MACK', 'MRSN', 'MRUS', 'MESA', 'MLAB', 'MESO', 'CASH', 'MEOH', 'MGEE', 'MGPI', 'MBOT', 'MCHP', 'MU', 'MSFT', 'MSTR', 'MVIS', 'MICT', 'MPB', 'MTP', 'MCEP', 'MBCN', 'MSEX', 'MSBI', 'MSVB', 'MOFG', 'MLND', 'MIME', 'MNDO', 'MB', 'NERV', 'MGEN', 'MRTX', 'MSON', 'MIND', 'MINDP', 'MITK', 'MKSI', 'MMAC', 'MTC', 'MINI', 'MOBL', 'MMDM', 'MMDMR', 'MMDMU', 'MMDMW', 'MRNA', 'MOGO', 'MTEM', 'MBRX', 'MNTA', 'MOMO', 'MKGI', 'MCRI', 'MDLZ', 'MGI', 'MDB', 'MPWR', 'TYPE', 'MNRO', 'MRCC', 'MRCCL', 'MNST', 'MORN', 'MOR', 'MOSY', 'MOTA', 'MTFB', 'MTFBW', 'MPAA', 'MOTS', 'MPVD', 'MOXC', 'COOP', 'MRIC', 'MSBF', 'MTEC', 'MTECU', 'MTECW', 'MTSC', 'MUDS', 'MUDSU', 'MUDSW', 'LABL', 'MBIO', 'MFSF', 'MVBF', 'MYSZ', 'MYL', 'MYND', 'MYNDW', 'MYOK', 'MYOS', 'MYRG', 'MYGN', 'NBRV', 'NAKD', 'NNDM', 'NANO', 'NSTG', 'NAOV', 'NH', 'NK', 'NSSC', 'NDAQ', 'NTRA', 'NATH', 'NAUH', 'NKSH', 'FIZZ', 'NCMI', 'NCOM', 'NESR', 'NESRW', 'NGHC', 'NGHCN', 'NGHCO', 'NGHCP', 'NGHCZ', 'NHLD', 'NHLDW', 'NATI', 'NRC', 'NSEC', 'EYE', 'NWLI', 'NAII', 'NHTC', 'NATR', 'BABY', 'JSM', 'NAVI', 'NMCI', 'NBCP', 'NBTB', 'NCSM', 'NEBU', 'NEBUU', 'NEBUW', 'NKTR', 'NMRD', 'NEOG', 'NEO', 'NTGN', 'NEON', 'NEOS', 'NVCN', 'NEPT', 'UEPS', 'NETE', 'NTAP', 'NTES', 'NFLX', 'NTGR', 'NTCT', 'NTWK', 'CUR', 'NBIX', 'NURO', 'NUROW', 'STIM', 'NTRP', 'NBEV', 'NYMT', 'NYMTN', 'NYMTO', 'NYMTP', 'NEWA', 'NWL', 'NLNK', 'NMRK', 'NWS', 'NWSA', 'NEWT', 'NEWTI', 'NEWTZ', 'NXEO', 'NXEOU', 'NXEOW', 'NXMD', 'NXST', 'NEXT', 'NXGN', 'NFEC', 'NODK', 'EGOV', 'NICE', 'NICK', 'NCBS', 'NITE', 'NIHD', 'NIU', 'LASR', 'NMIH', 'NNBR', 'NDLS', 'NDSN', 'NSYS', 'NBN', 'NTIC', 'NTRS', 'NTRSP', 'NFBK', 'NRIM', 'NWBI', 'NWPX', 'NCLH', 'NWFL', 'NVFY', 'NVMI', 'NOVN', 'NOVT', 'NVAX', 'NVLN', 'NVCR', 'NVMM', 'NVUS', 'NUAN', 'NCNA', 'NTNX', 'NTRI', 'NUVA', 'NVTR', 'QQQX', 'NVEE', 'NVEC', 'NVDA', 'NXPI', 'NXTM', 'NXTD', 'NXTDW', 'NYMX', 'OIIM', 'OVLY', 'OCSL', 'OCSLL', 'OCSI', 'OASM', 'OBLN', 'OBSV', 'OBCI', 'OPTT', 'OCFC', 'OFED', 'OCUL', 'ODT', 'OMEX', 'ODP', 'OFS', 'OFSSL', 'OFSSZ', 'OCCI', 'OHAI', 'OVBC', 'OHRP', 'OKTA', 'ODFL', 'OLBK', 'ONB', 'OPOF', 'OSBC', 'OSBCP', 'OLLI', 'ZEUS', 'OFLX', 'OMER', 'OMCL', 'ON', 'OTIV', 'ONCY', 'OMED', 'ONTX', 'ONTXW', 'ONCS', 'OHGI', 'OSS', 'OSPN', 'OPBK', 'OTEX', 'OPRA', 'OPES', 'OPESU', 'OPESW', 'OPGN', 'OPGNW', 'OPHT', 'OPNT', 'OPK', 'OBAS', 'OCC', 'OPRX', 'OPHC', 'OPTN', 'OPB', 'ORMP', 'OSUR', 'ORBC', 'ORBK', 'ORTX', 'ORLY', 'ORGO', 'ORGOW', 'ONVO', 'ORGS', 'SEED', 'OBNK', 'OESX', 'ORIT', 'ORRF', 'OFIX', 'KIDS', 'OSIS', 'OSIR', 'OSMT', 'OSN', 'OTEL', 'OTG', 'OTIC', 'OTTW', 'OTTR', 'OTLK', 'OTLKW', 'OSTK', 'OVID', 'OXBR', 'OXBRW', 'OXFD', 'OXLC', 'OXLCM', 'OXLCO', 'OXSQ', 'OXSQL', 'PFIN', 'PTSI', 'PCAR', 'VETS', 'PACB', 'PCB', 'PEIX', 'PMBC', 'PPBI', 'PCRX', 'PACW', 'PTIE', 'PAAS', 'PANL', 'PZZA', 'FRSH', 'PRTK', 'TEUM', 'PNRL', 'PCYG', 'PKBK', 'PKOH', 'PTNR', 'PBHC', 'PATK', 'PNBK', 'PATI', 'PEGI', 'PDCO', 'PTEN', 'PAVM', 'PAVMW', 'PAVMZ', 'PAYX', 'PCTY', 'PYDS', 'PYPL', 'PBBI', 'CNXN', 'PCMI', 'PCSB', 'PCTI', 'PDCE', 'PDFS', 'PDLI', 'PDLB', 'PDVW', 'SKIS', 'PGC', 'PEER', 'PEGA', 'PENN', 'PVAC', 'PFLT', 'PNNT', 'PWOD', 'WRLS', 'WRLSR', 'WRLSU', 'WRLSW', 'PEBO', 'PEBK', 'PFIS', 'PBCT', 'PBCTP', 'PUB', 'KPFS', 'PEP', 'PRCP', 'PRFT', 'PFMT', 'PERI', 'PESI', 'PPIH', 'PTX', 'PGLC', 'PETQ', 'PETS', 'PFSW', 'PGTI', 'PHAS', 'PHII', 'PHIIK', 'PAHC', 'PHIO', 'PHIOW', 'PLAB', 'PHUN', 'PHUNW', 'PICO', 'PLL', 'PIRS', 'PPC', 'PDD', 'PME', 'PNFP', 'PT', 'PPSI', 'PXLW', 'EAGL', 'EAGLU', 'EAGLW', 'PLYA', 'PLXS', 'PLUG', 'PLBC', 'PS', 'PSTI', 'PLXP', 'PNTR', 'PCOM', 'POLA', 'PTE', 'POLY', 'POOL', 'POPE', 'BPOP', 'BPOPM', 'BPOPN', 'PTLA', 'PBPB', 'PCH', 'POWL', 'POWI', 'PRAA', 'PRAH', 'PRAN', 'PRPO', 'AIPT', 'PFBC', 'PLPC', 'PFBI', 'PINC', 'LENS', 'PSDO', 'PBIO', 'PRGX', 'PSMT', 'PNRG', 'PRMW', 'PRIM', 'PVAL', 'PFG', 'BTEC', 'PXUS', 'GENY', 'PSET', 'PY', 'PMOM', 'USMC', 'PSC', 'PRNB', 'PRTH', 'PRTHU', 'PRTHW', 'PDEX', 'IPDN', 'PFIE', 'PGNX', 'PRGS', 'LUNG', 'PFPT', 'PRPH', 'PRQR', 'EQRR', 'BIB', 'UBIO', 'TQQQ', 'ZBIO', 'SQQQ', 'BIS', 'PSEC', 'PTGX', 'PTVCA', 'PTVCB', 'PRTO', 'PTI', 'PRTA', 'PRVB', 'PVBC', 'PROV', 'PBIP', 'PMD', 'PTC', 'PTCT', 'PHCF', 'PULM', 'PLSE', 'PBYI', 'PACQ', 'PACQU', 'PACQW', 'PCYO', 'PRPL', 'PXS', 'QADA', 'QADB', 'QCRH', 'QGEN', 'QIWI', 'QRVO', 'QCOM', 'QBAK', 'QLYS', 'QTNA', 'QTRX', 'QTRH', 'QRHC', 'QUIK', 'QDEL', 'QNST', 'QUMU', 'QTNT', 'QRTEA', 'QRTEB', 'QTT', 'RRD', 'RCM', 'RARX', 'RADA', 'RDCM', 'RDUS', 'RDNT', 'RDWR', 'METC', 'RMBS', 'RAND', 'RNDB', 'RPD', 'RAVE', 'RAVN', 'RBB', 'ROLL', 'RICK', 'RCMT', 'RDI', 'RDIB', 'RGSE', 'BCNA', 'BLCN', 'RLM', 'RNWK', 'RP', 'RETA', 'RCON', 'REPH', 'RRGB', 'RRR', 'RDVT', 'RDFN', 'RDHL', 'RBZ', 'RBZAW', 'REG', 'REGN', 'RGNX', 'RGLS', 'RBNC', 'RELV', 'MARK', 'RRI', 'RNST', 'REGI', 'ABAC', 'RCII', 'RGEN', 'REPL', 'RBCAA', 'FRBK', 'REFR', 'RESN', 'RECN', 'HAIR', 'TORC', 'ROIC', 'RETO', 'RTRX', 'RVNC', 'RVEN', 'RVLT', 'RWLK', 'RFIL', 'RGCO', 'RYTM', 'RBBN', 'RIBT', 'RELL', 'RIGL', 'RNET', 'RMNI', 'RIOT', 'REDU', 'RTTR', 'RVSB', 'RIVE', 'RCKT', 'RMTI', 'RCKY', 'RMCF', 'ROKU', 'ROSE', 'ROSEU', 'ROSEW', 'ROST', 'RGLD', 'RTIX', 'RBCN', 'RUBY', 'RMBL', 'RUSHA', 'RUSHB', 'RUTH', 'RYAAY', 'STBA', 'SANW', 'SCAC', 'SCACU', 'SCACW', 'SBRA', 'SABR', 'SAEX', 'SFET', 'SAFT', 'SGA', 'SAGE', 'SAIA', 'SALM', 'SAL', 'SAFM', 'SASR', 'SGMO', 'SANM', 'GCVRZ', 'SNY', 'SPNS', 'SRPT', 'SVRA', 'SBFG', 'SBFGP', 'SBBX', 'SBAC', 'SCSC', 'SMIT', 'SCHN', 'SRRK', 'SCHL', 'SAMAU', 'SGMS', 'SCPH', 'SCYX', 'SEAC', 'SBCF', 'STX', 'SHIP', 'SHIPW', 'SHOS', 'SPNE', 'SGEN', 'EYES', 'EYESW', 'SECO', 'SCWX', 'SNFCA', 'SEIC', 'SLCT', 'SIC', 'SELB', 'SIGI', 'SLS', 'LEDS', 'SMTC', 'SENEA', 'SENEB', 'SNES', 'SNH', 'SNHNI', 'SNHNL', 'AIHS', 'SRTS', 'SRTSW', 'STNL', 'STNLU', 'STNLW', 'SQBG', 'MCRB', 'SREV', 'SFBS', 'SESN', 'SVBI', 'SGBX', 'SGOC', 'SMED', 'SHSP', 'SHEN', 'PIXY', 'SHLO', 'SCCI', 'TYHT', 'SHPG', 'SCVL', 'SHBI', 'SSTI', 'SFLY', 'SIFI', 'SIBN', 'SIEB', 'SNNA', 'SIEN', 'BSRR', 'SRRA', 'SWIR', 'SIFY', 'SIGA', 'SGLB', 'SGLBW', 'SGMA', 'SBNY', 'SLGN', 'SILC', 'SLAB', 'SIMO', 'SAMG', 'SSNT', 'SFNC', 'SLP', 'SINA', 'SBGI', 'SINO', 'SVA', 'SINT', 'SG', 'SIRI', 'SRVA', 'SITO', 'SKYS', 'SKYW', 'SWKS', 'SNBR', 'SLM', 'SLMBP', 'SMSH', 'SMSHW', 'SGH', 'SND', 'SMBK', 'SMSI', 'SMTX', 'SRAX', 'SCKT', 'SOHU', 'SLRC', 'SUNS', 'SEDG', 'SLNO', 'SLNOW', 'SLGL', 'SLDB', 'SNGX', 'SNGXW', 'SNOA', 'SNOAW', 'SONO', 'SPHS', 'SORL', 'SRNE', 'SOHO', 'SOHOB', 'SOHOO', 'SOHOK', 'SFBC', 'SSB', 'SFST', 'SMBC', 'SONA', 'SBSI', 'SP', 'SGRP', 'SPKE', 'SPKEP', 'ONCE', 'SPAR', 'SPTN', 'DWFI', 'SPPI', 'SPRO', 'ANY', 'SPEX', 'SPI', 'SAVE', 'STXB', 'SPLK', 'SPOK', 'SPWH', 'SBPH', 'FUND', 'SFM', 'SPSC', 'SSNC', 'SSLJ', 'SSRM', 'STAA', 'STAF', 'STMP', 'STND', 'SBLK', 'SBLKZ', 'SBUX', 'STFC', 'GASS', 'STCN', 'STLD', 'SMRT', 'SBOT', 'STML', 'SRCL', 'SBT', 'STRL', 'SHOO', 'SSFN', 'SFIX', 'SYBT', 'BANX', 'STNE', 'SSKN', 'SSYS', 'STRA', 'HNDL', 'STRT', 'STRS', 'STRM', 'SBBP', 'SUMR', 'SMMF', 'SSBI', 'SMMT', 'WISA', 'SNHY', 'SNDE', 'SNSS', 'STKL', 'SPWR', 'RUN', 'SUNW', 'SPCB', 'SCON', 'SGC', 'SUPN', 'SPRT', 'SURF', 'SGRY', 'SRDX', 'STRO', 'SIVB', 'SVMK', 'SYKE', 'SYMC', 'SYNC', 'SYNL', 'SYNA', 'SNCR', 'SNDX', 'SYNH', 'SGYP', 'SYBX', 'SNPS', 'SES', 'THOR', 'SYPR', 'SYRS', 'TROW', 'TTOO', 'TRHC', 'TCMD', 'TAIT', 'TLC', 'TTWO', 'TLND', 'TNDM', 'TLF', 'TANH', 'TAOP', 'TEDU', 'TATT', 'TAYD', 'CGBD', 'AMTD', 'PETZ', 'TECD', 'TCCO', 'TTGT', 'TGLS', 'TGEN', 'TNAV', 'TLGT', 'TELL', 'TENB', 'TENX', 'TZAC', 'TZACU', 'TZACW', 'TER', 'TERP', 'TBNK', 'TSRO', 'TSLA', 'TESS', 'TTEK', 'TTPH', 'TCBI', 'TCBIL', 'TCBIP', 'TCBIW', 'TXN', 'TXRH', 'TFIG', 'TFSL', 'TGTX', 'WTER', 'ANDE', 'TBBK', 'BPRN', 'CG', 'TCGP', 'CAKE', 'CHEF', 'TCFC', 'DSGX', 'DXYN', 'ENSG', 'XONE', 'FBMS', 'FLIC', 'GT', 'HABT', 'HCKT', 'HAIN', 'CUBA', 'INTG', 'JYNT', 'KEYW', 'KHC', 'OLD', 'LOVE', 'MSG', 'MDCO', 'MEET', 'MIK', 'MIDD', 'NAVG', 'SLIM', 'STKS', 'ORG', 'PRSC', 'RMR', 'SMPL', 'TSG', 'TTD', 'ULTI', 'YORW', 'NCTY', 'TXMD', 'TRPX', 'TBPH', 'TST', 'TCRD', 'TBRG', 'TBRGU', 'TBRGW', 'TIBR', 'TIBRU', 'TIBRW', 'TTTN', 'TTS', 'TLRY', 'TSBK', 'TIPT', 'TITN', 'TMDI', 'TTNP', 'TVTY', 'TIVO', 'TLSA', 'TKKS', 'TKKSR', 'TKKSU', 'TKKSW', 'TMUS', 'TMSR', 'TOCA', 'TNXP', 'TISA', 'TOPS', 'TRCH', 'TRMD', 'TOTA', 'TOTAR', 'TOTAU', 'TOTAW', 'TBLT', 'TBLTU', 'TBLTW', 'TSEM', 'CLUB', 'TOWN', 'TPIC', 'TCON', 'TSCO', 'TWMC', 'TACT', 'TRNS', 'TGA', 'TBIO', 'TA', 'TANNI', 'TANNL', 'TANNZ', 'TZOO', 'TRMT', 'TRVN', 'TPCO', 'TCDA', 'TCBK', 'TDAC', 'TDACU', 'TDACW', 'TRIL', 'TRS', 'TRMB', 'TRIB', 'TMCX', 'TMCXU', 'TMCXW', 'TRIP', 'TSC', 'TSCAP', 'TBK', 'TRVG', 'TROV', 'TRUE', 'THST', 'TRUP', 'TRST', 'TRMK', 'TSRI', 'TTEC', 'TTMI', 'TC', 'TCX', 'TUES', 'TOUR', 'HEAR', 'TWLV', 'TWLVR', 'TWLVU', 'TWLVW', 'FOX', 'FOXA', 'TWIN', 'TWST', 'TRCB', 'TYME', 'USCR', 'PRTS', 'USEG', 'GROW', 'USAU', 'USWS', 'USWSW', 'UBNT', 'UFPT', 'ULTA', 'UCTT', 'UPL', 'RARE', 'ULBI', 'UMBF', 'UMPQ', 'UNAM', 'UBSH', 'UNB', 'QURE', 'UBCP', 'UBOH', 'UBSI', 'UCBI', 'UCFC', 'UAL', 'UBNK', 'UFCS', 'UIHC', 'UNFI', 'UBFO', 'USLM', 'UTHR', 'UG', 'UNIT', 'UNTY', 'UBX', 'OLED', 'UEIC', 'UFPI', 'ULH', 'USAP', 'UVSP', 'UMRX', 'UPLD', 'UPWK', 'UONE', 'UONEK', 'URBN', 'URGN', 'UROV', 'ECOL', 'USAT', 'USATP', 'USAK', 'UTMD', 'UTSI', 'UXIN', 'VCNX', 'VLRX', 'VALX', 'VLY', 'VLYPO', 'VLYPP', 'VTEC', 'VALU', 'VNDA', 'BBH', 'GNRX', 'PPH', 'VWOB', 'VNQI', 'VCIT', 'VGIT', 'VIGI', 'VYMI', 'VCLT', 'VGLT', 'VMBS', 'VONE', 'VONG', 'VONV', 'VTWO', 'VTWG', 'VTWV', 'VTHR', 'VCSH', 'VTIP', 'VGSH', 'BND', 'VTC', 'BNDX', 'VXUS', 'BNDW', 'VEAC', 'VEACU', 'VEACW', 'VREX', 'VRNS', 'VBLT', 'VXRT', 'VBIV', 'VTIQ', 'VTIQU', 'VTIQW', 'VECO', 'VEON', 'VRA', 'VCYT', 'VSTM', 'VCEL', 'VRNT', 'VRSN', 'VRSK', 'VBTX', 'VERI', 'VRML', 'VRNA', 'VRRM', 'VRCA', 'VTNR', 'VRTX', 'VERU', 'VIA', 'VIAB', 'VMET', 'VSAT', 'VIAV', 'VICL', 'VICR', 'VCTR', 'CIZ', 'VSDA', 'CEY', 'CEZ', 'CID', 'CIL', 'CFO', 'CFA', 'CSF', 'CDC', 'CDL', 'VSMV', 'CSB', 'CSA', 'VRAY', 'VKTX', 'VKTXW', 'VBFC', 'VLGEA', 'VIOT', 'VNOM', 'VIRC', 'VTSI', 'VIRT', 'VRTS', 'VRTSP', 'BBC', 'BBP', 'VRTU', 'VTGN', 'VC', 'VIST', 'VTL', 'VIVE', 'VVPR', 'VVUS', 'VOD', 'VOXX', 'VYGR', 'VSEC', 'VTVT', 'VUZI', 'WTRH', 'WBA', 'WAFD', 'WASH', 'WSBF', 'WVE', 'WNFM', 'WSTG', 'WCFB', 'WDFC', 'WB', 'WTW', 'WEBK', 'WEN', 'WERN', 'WSBC', 'WTBA', 'WABC', 'WSTL', 'WBND', 'WDC', 'WNEB', 'WPRT', 'WWR', 'WEYS', 'WHLR', 'WHLRD', 'WHLRP', 'WHLRW', 'WHF', 'WHFBZ', 'WHLM', 'WVVI', 'WVVIP', 'WLDN', 'WLFC', 'WLTW', 'WSC', 'WIN', 'WING', 'WINA', 'WINS', 'WTFC', 'WTFCM', 'AGND', 'CXSE', 'EMCG', 'EMCB', 'DGRE', 'DXGE', 'HYZD', 'AGZD', 'WETF', 'DXJS', 'GULF', 'HYND', 'DGRW', 'DGRS', 'WIX', 'WWD', 'WDAY', 'WKHS', 'WRLD', 'WRTC', 'WMGI', 'WMGIZ', 'WSFS', 'WVFC', 'WYNN', 'XBIT', 'XELB', 'XEL', 'XNCR', 'XBIO', 'XENE', 'XERS', 'XGTI', 'XLNX', 'XOMA', 'XPER', 'XSPA', 'XTLB', 'XNET', 'YNDX', 'YRIV', 'YTRA', 'YTEN', 'YIN', 'YMAB', 'YOGA', 'YGYI', 'YRCW', 'YY', 'ZFGN', 'ZAGG', 'ZLAB', 'ZEAL', 'ZBRA', 'Z', 'ZG', 'ZN', 'ZNWAA', 'ZION', 'ZIONW', 'ZIOP', 'ZIXI', 'ZKIN', 'ZGNX', 'ZSAN', 'ZS', 'ZUMZ', 'ZYNE', 'ZNGA'] -------------------------------------------------------------------------------- /v2/backend/assets/symbols.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": ["YI", "PIH", "PIHPP", "TURN", "FLWS", "FCCY", "SRCE", "VNET", "TWOU", "QFIN", "TPNL", "JOBS", "EGHT", "AAON", "ABEO", "ABEOW", "ABIL", "ABMD", "ABP", "AXAS", "ACIU", "ACIA", "ACTG", "ACHC", "ACAD", "ACST", "AXDX", "ACCP", "XLRN", "ANCX", "ARAY", "ACRX", "ACER", "ACET", "AKAO", "ACHV", "ACHN", "ACIW", "ACRS", "ACMR", "ACNB", "ACOR", "ATVI", "ADMS", "ADMP", "ADAP", "ADUS", "AEY", "IOTS", "ADIL", "ADILW", "ADMA", "ADBE", "ADOM", "ADTN", "ADRO", "ADES", "AEIS", "AMD", "ADXS", "ADVM", "DWMC", "DWSH", "ACT", "AEGN", "AGLE", "AEHR", "AMTX", "AERI", "AVAV", "ARPO", "AEZS", "AEMD", "GNMX", "AFMD", "AGEN", "AGRX", "AGYS", "AGIO", "AGMH", "AGNC", "AGNCB", "AGNCN", "AGFS", "AGFSW", "ALRN", "AIMT", "AIRT", "ATSG", "AIRG", "AMCN", "AKAM", "AKTX", "AKCA", "AKBA", "AKER", "AKRX", "AKTS", "ALRM", "ALSK", "ALAC", "ALACR", "ALACU", "ALACW", "ALBO", "ABDC", "ALDR", "ALDX", "ALXN", "ALCO", "ALGN", "ALIM", "ALYA", "ALJJ", "ALKS", "ALLK", "ABTX", "ALGT", "ALGR", "ALGRR", "ALGRU", "ALGRW", "ALNA", "AMMA", "ARLP", "LNT", "AHPI", "AMOT", "ALQA", "ALLO", "ALLT", "MDRX", "ALNY", "AOSL", "GOOG", "GOOGL", "SMCP", "ATEC", "ALPN", "AMR", "AMRWW", "AABA", "ALTR", "ALT", "ASPS", "AIMC", "ALTM", "ALZH", "AMAG", "AMAL", "AMRN", "AMRK", "AMZN", "AMBC", "AMBCW", "AMBA", "AMCX", "AMCI", "AMCIU", "AMCIW", "DOX", "AMED", "UHAL", "AMRH", "AMRHW", "ATAX", "AMOV", "AAL", "AETI", "AFIN", "AMNB", "ANAT", "AOBC", "APEI", "AMRB", "AMSWA", "AMSC", "AMWD", "CRMT", "ABCB", "AMSF", "ASRV", "ASRVP", "ATLO", "AMGN", "FOLD", "AMKR", "AMPH", "IBUY", "ASYS", "AMRS", "ADI", "ANAB", "AVXL", "ANGI", "ANGO", "ANIP", "ANIK", "ANIX", "ANSS", "ATRS", "APLS", "APOG", "APEN", "AINV", "AMEH", "APPF", "APPN", "AAPL", "ARCI", "APDN", "APDNW", "AGTC", "AMAT", "AAOI", "AREX", "APTI", "APRI", "APVO", "APTX", "APM", "APTO", "AQMS", "AQB", "AQST", "AQXP", "ARDM", "PETX", "ARAV", "ABUS", "ARCW", "ABIO", "RKDA", "ARCB", "ACGL", "ACGLO", "ACGLP", "FUV", "ARCE", "ARCT", "ARDX", "ARNA", "ARCC", "ARGX", "ARDS", "ARKR", "ARTX", "ARQL", "ARRY", "ARRS", "DWCR", "DWAT", "AROW", "ARWR", "ASNS", "ARTNA", "ARTW", "ARVN", "ARYA", "ARYAU", "ARYAW", "ASNA", "ASND", "ASCMA", "APWC", "ASLN", "ASML", "ASPU", "AZPN", "ASMB", "ASRT", "ASFI", "ASTE", "ATRO", "ALOT", "ASTC", "ASUR", "ASV", "ATAI", "ATRA", "ATHN", "ATNX", "ATHX", "AAME", "ACBI", "AY", "ATLC", "AAWW", "AFH", "AFHBL", "TEAM", "ATNI", "ATOM", "ATOS", "ATRC", "ATRI", "ATIS", "ATISW", "ATTU", "LIFE", "AUBN", "BOLD", "AUDC", "AEYE", "AUPH", "EARS", "JG", "ADSK", "AUTL", "ADP", "AUTO", "AVDL", "AVCO", "ATXI", "AVEO", "AVNW", "CDMO", "CDMOP", "AVID", "AVGR", "CAR", "AVT", "AVRO", "AWRE", "ACLS", "AXGN", "AAXN", "AXNX", "AXON", "AXSM", "AXTI", "AYTU", "AZRX", "BCOM", "RILY", "RILYG", "RILYH", "RILYI", "RILYL", "RILYZ", "BOSC", "BIDU", "BCPC", "BLDP", "BANF", "BANFP", "BCTF", "BAND", "BFC", "BOCH", "BMRC", "BMLP", "BKSC", "BOTJ", "OZK", "BSVN", "BFIN", "BWFG", "BANR", "BZUN", "DFVL", "DFVS", "DLBS", "DTUL", "DTUS", "DTYL", "DTYS", "FLAT", "STPP", "TAPR", "BBSI", "GOLD", "BSET", "ZTEST", "BCML", "BCBP", "BECN", "BBGI", "BBBY", "BGNE", "BELFA", "BELFB", "BLPH", "BLCM", "BNCL", "BNFT", "BNTC", "BNTCW", "BRY", "BYSI", "BGCP", "BGFV", "BRPA", "BRPAR", "BRPAU", "BRPAW", "BILI", "BASI", "ORPN", "BIOC", "BCRX", "BDSI", "BFRA", "BIIB", "BHTG", "BKYI", "BIOL", "BLFS", "BLRX", "BMRN", "BMRA", "BNGO", "BNGOW", "BVXV", "BVXVW", "BPTH", "BIOS", "BSGM", "BSTC", "TECH", "BEAT", "BTAI", "BCAC", "BCACR", "BCACU", "BCACW", "BJRI", "BBOX", "BRAC", "BRACR", "BRACU", "BRACW", "BLKB", "BL", "BKCC", "TCPC", "BLNK", "BLNKW", "BLMN", "BCOR", "BLBD", "BHBK", "BLUE", "BKEP", "BKEPP", "BPMC", "ITEQ", "BMCH", "WIFI", "BOJA", "BOKF", "BOKFL", "BNSO", "BKNG", "BRQS", "BOMN", "BPFH", "EPAY", "BOXL", "BWMCU", "BBRX", "BCLI", "BVNSC", "BDGE", "BLIN", "BWB", "BRID", "BCOV", "BHF", "BHFAL", "AVGO", "BVSN", "BYFC", "BWEN", "BPY", "BPR", "BPRAP", "BRKL", "BRKS", "DOOO", "BRKR", "BMTC", "BLMT", "BSQR", "BLDR", "BFST", "CFFI", "CHRW", "CCMP", "CDNS", "CDZI", "CZR", "CSTE", "CLBS", "CHY", "CHI", "CCD", "CHW", "CGO", "CSQ", "CAMP", "CVGW", "CALA", "CALM", "CLMT", "CRUSC", "CLXT", "CATC", "CAC", "CAMT", "CSIQ", "CGIX", "CPHC", "CBNK", "CCBG", "CPLP", "CSWC", "CSWCL", "CPTA", "CPTAG", "CPTAL", "CFFN", "CAPR", "CSTR", "CPST", "CARA", "CBLK", "CARB", "CSII", "CDLX", "CATM", "CDNA", "CECO", "CTRE", "CARG", "CARO", "CART", "CRZO", "TAST", "CARV", "CASM", "CASA", "CWST", "CASY", "CASI", "CASS", "CATB", "CBIO", "CPRX", "CATS", "CATY", "CGVIC", "CIVEC", "CVCO", "CBFV", "CBAT", "CBMB", "CBOE", "CBTX", "CDK", "CDW", "CECE", "CELC", "CELG", "CELGZ", "CLDX", "APOP", "APOPW", "CLRB", "CLRBW", "CLRBZ", "CLLS", "CBMG", "CLSN", "CELH", "CYAD", "CETX", "CETXP", "CETXW", "CDEV", "CSFL", "CETV", "CFBK", "CENT", "CENTA", "CVCY", "CNTX", "CTRC", "CENX", "CNBKA", "CNTY", "CRNT", "CERC", "CERN", "CERS", "KOOL", "CEVA", "CFFAU", "CSBR", "CYOU", "BURG", "CTHR", "GTLS", "CHTR", "CTAC", "CTACU", "CTACW", "CHKP", "CHEK", "CHEKW", "CHEKZ", "CKPT", "CEMI", "CHFC", "CCXI", "CHMG", "CHKE", "CHFS", "CHMA", "CSSE", "CSSEP", "PLCE", "CMRX", "CADC", "CAAS", "CBPO", "CCCL", "GLG", "CCRC", "JRJC", "HGSH", "CIFS", "CJJD", "CLDC", "CHNR", "CREG", "CNTF", "CXDC", "CCIH", "CNET", "IMOS", "CDXC", "CHSCL", "CHSCM", "CHSCN", "CHSCO", "CHSCP", "CHDN", "CHUY", "CDTX", "CMCT", "CMCTP", "CMPR", "CINF", "CIDM", "CTAS", "CRUS", "CSCO", "CTRN", "CTXR", "CTXRW", "CZNC", "CZWI", "CZFC", "CIZN", "CTXS", "CHCO", "CIVB", "CIVBP", "CLAR", "CLNE", "CACG", "YLDE", "LRGE", "CLFD", "CLRO", "CLSD", "CLIR", "CLIRW", "CMTA", "CBLI", "CLVS", "CLPS", "CMFN", "CMFNL", "CMSS", "CMSSR", "CMSSU", "CMSSW", "CME", "CCNE", "CCB", "COKE", "COCP", "CODA", "CDXS", "CODX", "CVLY", "JVA", "CCOI", "CGNX", "CTSH", "CWBR", "COHR", "CHRS", "COHU", "CLCT", "COLL", "CIGI", "CLGN", "CBAN", "COLB", "CLBK", "COLM", "CMCO", "CMCSA", "CCNI", "CBSH", "CBSHP", "CVGI", "COMM", "JCS", "ESXB", "CFBI", "CYHHZ", "CTBI", "CWBC", "CVLT", "CGEN", "CPSI", "CTG", "SCOR", "CHCI", "CMTL", "CNAT", "CNCE", "BBCP", "BBCPW", "CDOR", "CFMS", "CNFR", "CNFRL", "CNMD", "CTWS", "CNOB", "CONN", "CNSL", "CWCO", "CNAC", "CNACR", "CNACU", "CNACW", "CNST", "ROAD", "CPSS", "CFRX", "CTRV", "CTRL", "CVON", "AWSM", "CPRT", "CRBP", "CORT", "CORE", "CSOD", "CORV", "CRVL", "CRVS", "CSGP", "COST", "CPAH", "ICBK", "COUP", "CVTI", "COWN", "COWNL", "COWNZ", "PMTS", "CPSH", "CRAI", "CBRL", "BREW", "CRAY", "CREX", "CREXW", "CACC", "DGLD", "DSLV", "GLDI", "SLVO", "TVIX", "UGLD", "USLV", "USOI", "VIIX", "ZIV", "CREE", "CRESY", "CRNX", "CRSP", "CRTO", "CROX", "CRON", "CCRN", "CRWS", "CYRX", "CYRXW", "CSGS", "CCLP", "CSPI", "CSWI", "CSX", "CTIC", "CTIB", "CTRP", "CUE", "CUI", "CPIX", "CMLS", "CRIS", "CUTR", "CVBF", "CVV", "CYAN", "CYBR", "CYBE", "CYCC", "CYCCP", "CBAY", "CY", "CYRN", "CONE", "CYTK", "CTMX", "CYTX", "CYTXZ", "CTSO", "CYTR", "DJCO", "DAKT", "DARE", "DRIO", "DRIOW", "DZSI", "DSKE", "DSKEW", "DAIO", "DTSS", "PLAY", "DTEA", "DFNL", "DINT", "DUSA", "DWLD", "DWSN", "DBVT", "DDMX", "DDMXU", "DDMXW", "DCPH", "DFRG", "TACO", "TACOW", "DMPI", "DELT", "DNLI", "DENN", "XRAY", "DDOC", "DERM", "DEST", "DXLG", "DSWL", "DXCM", "DFBH", "DFBHU", "DFBHW", "DHXM", "DMAC", "DHIL", "FANG", "DCIX", "DRNA", "DFFN", "DGII", "DMRC", "DRAD", "DGLY", "APPS", "DCOM", "DIOD", "DISCA", "DISCB", "DISCK", "DISH", "DVCR", "SAUC", "DLHC", "BOOM", "DNBF", "DOCU", "DOGZ", "DLTR", "DLPN", "DLPNW", "DOMO", "DGICA", "DGICB", "DMLP", "DORM", "DOVA", "LYL", "DBX", "DCAR", "DRYS", "DSPG", "DLTH", "DNKN", "DRRX", "DXPE", "DYSL", "DYNT", "DVAX", "ETFC", "SSP", "EBMT", "EGBN", "EGLE", "EFBI", "EGRX", "IGLE", "EWBC", "EML", "EAST", "EVGBC", "EVSTC", "EVFTC", "EVLMC", "OKDCC", "EBAY", "EBAYL", "EBIX", "ECHO", "SATS", "EEI", "EDAP", "EDGE", "EDNT", "EDIT", "EDTX", "EDTXU", "EDTXW", "EDUC", "EGAN", "EHTH", "EIDX", "EIGR", "EKSO", "LOCO", "EMITF", "ESLT", "ERI", "SOLO", "SOLOW", "ESIO", "ECOR", "EA", "EFII", "ELSE", "ESBK", "ELOX", "ELTK", "EMCI", "EMCF", "EMKR", "EMMS", "NYNY", "ENTA", "ECPG", "WIRE", "ENDP", "ELGX", "NDRA", "NDRAW", "EIGI", "WATT", "EFOI", "EHR", "ERII", "ENG", "ENOB", "ENPH", "ESGR", "ESGRO", "ESGRP", "ETTX", "ENFC", "ENTG", "ENTX", "ENTXW", "EBTC", "EFSC", "EPZM", "PLUS", "EQ", "EQIX", "EQBK", "ERIC", "ERIE", "ERYP", "ESCA", "ESPR", "ESQ", "ESSA", "EPIX", "ESND", "ESTA", "ESTR", "ESTRW", "VBND", "VUSE", "VIDI", "ETON", "ETSY", "CLWT", "EDRY", "EEFT", "ESEA", "EVLO", "EVBG", "EVK", "EVER", "MRAM", "EVLV", "EVOP", "EVFM", "EVGN", "EVOK", "EOLS", "EVOL", "EXAS", "FLAG", "ROBO", "XELA", "EXEL", "EXFO", "EXLS", "EXPI", "EXPE", "EXPD", "EXPO", "STAY", "XOG", "EXTR", "EYEG", "EYEGW", "EYEN", "EYPT", "EZPW", "FFIV", "FB", "FLMN", "FLMNW", "DAVE", "FANH", "FARM", "FMAO", "FMNB", "FAMI", "FARO", "FAST", "FAT", "FATE", "FBSS", "FLF", "FSAC", "FSACU", "FSACW", "FNHC", "FENC", "GSM", "FFBW", "FCSC", "FGEN", "FDBC", "ONEQ", "LION", "FDUS", "FDUSL", "FRGI", "FITB", "FITBI", "FISI", "FNSR", "FNJN", "FTACU", "FEYE", "FBNC", "FNLC", "FRBA", "BUSE", "FBIZ", "FCAP", "FCBP", "FCNCA", "FCBC", "FCCO", "FDEF", "FFBC", "FFIN", "THFF", "FFNW", "FFWM", "FGBI", "FHB", "INBK", "INBKL", "FIBK", "FRME", "FMBH", "FMBI", "FNWB", "FSFG", "FSLR", "FAAR", "FPA", "BICK", "FBZ", "FTHI", "FCAL", "FCAN", "FTCS", "FCEF", "FCA", "SKYY", "RNDM", "FDT", "FDTS", "FVC", "FV", "IFV", "DDIV", "DVOL", "DVLU", "DWPP", "DALI", "FDNI", "FEM", "RNEM", "FEMB", "FEMS", "FTSM", "FEP", "FEUZ", "FGM", "FTGC", "FTLB", "HYLS", "FHK", "NFTY", "FTAG", "FTRI", "LEGR", "FPXI", "FPXE", "FJP", "FEX", "FTC", "RNLC", "FTA", "FLN", "LMBS", "FMB", "FMK", "FNX", "FNY", "RNMC", "FNK", "FAD", "FAB", "MDIV", "MCEF", "FMHI", "QABA", "ROBT", "FTXO", "QCLN", "GRID", "CIBR", "FTXG", "CARZ", "FTXN", "FTXH", "FTXD", "FTXL", "FONE", "TDIV", "FTXR", "QQEW", "QQXT", "QTEC", "AIRR", "RDVY", "RFAP", "RFDI", "RFEM", "RFEU", "FID", "FTSL", "FYX", "FYC", "RNSC", "FYT", "SDVY", "FKO", "FCVT", "FDIV", "FSZ", "FIXD", "TUSA", "FKU", "RNDV", "FUNC", "FUSB", "MYFW", "FCFS", "SVVC", "FSV", "FISV", "FIVE", "FPRX", "FVE", "FIVN", "FLEX", "FLKS", "FLXN", "SKOR", "LKOR", "MBSD", "ASET", "ESGG", "ESG", "QLC", "FPAY", "FPAYW", "FLXS", "FLIR", "FLNT", "FLDM", "FFIC", "FNCB", "FOMX", "FOCS", "FONR", "FSCT", "FRSX", "FORM", "FORTY", "FORR", "FRTA", "FTNT", "FBIO", "FBIOP", "FTSV", "FMCI", "FMCIU", "FMCIW", "FWRD", "FORD", "FWP", "FOSL", "FOXF", "FRAN", "FELE", "FKLY", "FRED", "RAIL", "FEIM", "FRPT", "FTDR", "FTEO", "FTR", "FRPH", "FSBW", "FSBC", "FTD", "FTEK", "FCEL", "FLGT", "FORK", "FLL", "FMAX", "FULT", "FNKO", "FSNN", "FTFT", "FFHL", "FVCB", "WILC", "GTHX", "FOANC", "GRBIC", "MOGLC", "PETZC", "GAIA", "GLPG", "GALT", "GLMD", "GMDA", "GLPI", "GPIC", "GRMN", "GARS", "GLIBA", "GLIBP", "GDS", "GEMP", "GENC", "GFN", "GFNCP", "GFNSL", "GENE", "GNUS", "GNMK", "GNCA", "GHDX", "GNPX", "GNST", "GNTX", "THRM", "GEOS", "GABC", "GERN", "GEVO", "ROCK", "GIGM", "GIII", "GILT", "GILD", "GBCI", "GLAD", "GLADD", "GLADN", "GOOD", "GOODM", "GOODO", "GOODP", "GAIN", "GAINL", "GAINM", "LAND", "LANDP", "GLBZ", "GBT", "ENT", "GBLI", "GBLIL", "GBLIZ", "SELF", "GWRS", "DRIV", "KRMA", "DAX", "EBIZ", "FINX", "AIQ", "BFIT", "SNSR", "LNGR", "MILN", "CHIC", "EFAS", "QYLD", "BOTZ", "CATH", "SOCL", "ALTY", "SRET", "YLCO", "GLBS", "GLUU", "GLYC", "GOGO", "GLNG", "GMLP", "GMLPP", "DNJR", "GDEN", "GOGL", "GBDC", "GTIM", "GBLK", "GSHD", "GPRO", "GPAQ", "GPAQU", "GPAQW", "GRSH", "GRSHU", "GRSHW", "LOPE", "GRVY", "GECC", "GECCL", "GECCM", "GEC", "GLDD", "GSBC", "GRBK", "GPP", "GPRE", "GCBC", "GLAC", "GLACR", "GLACU", "GLACW", "GLRE", "GRNQ", "GSKY", "GSUM", "GRIF", "GRFS", "GRIN", "GRTS", "GRPN", "OMAB", "GGAL", "GVP", "GSIT", "GSVC", "GTXI", "GTYH", "GTYHU", "GTYHW", "GNTY", "GFED", "GH", "GIFI", "GURE", "GPOR", "GWPH", "GWGH", "GYRO", "HEES", "HLG", "HNRG", "HALL", "HALO", "HBK", "HLNE", "HJLI", "HJLIW", "HWC", "HWCPL", "HAFC", "HQCL", "HONE", "HLIT", "HFGIC", "HBIO", "HCAP", "HCAPZ", "HAS", "HA", "HWKN", "HWBK", "HYAC", "HYACU", "HYACW", "HAYN", "HDS", "HIIQ", "HCSG", "HQY", "HSTM", "HTLD", "HTLF", "HTBX", "HEBT", "HSII", "HELE", "HMNY", "HSDT", "HMTV", "HNNA", "HSIC", "HTBK", "HFWA", "HCCI", "MLHR", "HRTX", "HSKA", "HX", "HFFG", "HIBB", "SNLN", "HPJ", "HIHO", "HIMX", "HIFS", "HSGX", "HCCH", "HCCHR", "HCCHU", "HCCHW", "HMNF", "HMSY", "HOLI", "HOLX", "HBCP", "HOMB", "HFBL", "HMST", "HMTA", "HTBI", "FIXX", "HOFT", "HOPE", "HFBC", "HBNC", "HZNP", "HRZN", "HDP", "HPT", "TWNK", "TWNKW", "HMHC", "HWCC", "HOVNP", "HBMD", "HTGM", "HTHT", "HUBG", "HSON", "HDSN", "HUNT", "HUNTU", "HUNTW", "HBAN", "HBANN", "HBANO", "HURC", "HURN", "HCM", "HBP", "HVBC", "HYGS", "HYRE", "IDSY", "IIIV", "IAC", "IBKC", "IBKCO", "IBKCP", "IBEX", "ICAD", "IEP", "ICCH", "ICFI", "ICHR", "ICLK", "ICLR", "ICON", "ICUI", "IPWR", "IDEX", "INVE", "IDRA", "IDXX", "IESC", "IROQ", "IFMK", "INFO", "IIVI", "KANG", "IKNX", "ILMN", "ISNS", "IMMR", "ICCC", "IMDZ", "IMGN", "IMMU", "IMRN", "IMRNW", "IMMP", "IMPV", "PI", "IMV", "INCY", "INDB", "IBCP", "IBTX", "ILPT", "IDSA", "INFN", "INFI", "IFRX", "III", "IEA", "IEAWW", "IMKTA", "INWK", "INOD", "IPHS", "IOSP", "INNT", "ISSC", "INVA", "INGN", "INOV", "INO", "INPX", "INSG", "NSIT", "ISIG", "INSM", "INSE", "IIIN", "PODD", "INSY", "NTEC", "IART", "IDTI", "IMTE", "INTC", "NTLA", "IPCI", "IPAR", "ICPT", "IDCC", "TILE", "LINK", "IMI", "INAP", "IBOC", "IMXI", "ISCA", "IGLD", "IIJI", "IDXG", "XENT", "INTX", "IPLDP", "IVAC", "INTL", "ITCI", "XON", "IIN", "INTU", "ISRG", "PLW", "ADRA", "ADRD", "ADRE", "ADRU", "PKW", "PFM", "PYZ", "PEZ", "PSL", "PIZ", "PIE", "PXI", "PFI", "PTH", "PRN", "DWLV", "PDP", "DWAQ", "DWAS", "DWIN", "DWTR", "PTF", "PUI", "IDLB", "PRFZ", "PAGG", "PSAU", "PIO", "PGJ", "PEY", "IPKW", "PID", "KBWB", "KBWD", "KBWY", "KBWP", "KBWR", "LDRI", "LALT", "PNQI", "PDBC", "QQQ", "USLB", "PSCD", "PSCC", "PSCE", "PSCF", "PSCH", "PSCI", "PSCT", "PSCM", "PSCU", "ISDX", "ISDS", "ISEM", "IUS", "IUSS", "VRIG", "PHO", "ISTR", "ISBC", "ITIC", "NVIV", "IONS", "IOVA", "IPAS", "IPGP", "IPIC", "CLRG", "CSML", "IQ", "IRMD", "IRTC", "IRIX", "IRDM", "IRDMB", "IRBT", "IRWD", "IRCP", "SLQD", "ISHG", "SHY", "TLT", "IEI", "IEF", "AIA", "USIG", "COMT", "ISTB", "IXUS", "IUSG", "IUSV", "IUSB", "HEWG", "SUSB", "ESGD", "ESGE", "ESGU", "SUSC", "XT", "FALN", "IFEU", "IFGL", "BGRN", "IGF", "GNMA", "HYXE", "IGIB", "IGOV", "EMB", "MBB", "JKI", "ACWX", "ACWI", "AAXJ", "EWZS", "MCHI", "SCZ", "EEMA", "EMXC", "EUFN", "IEUS", "RING", "SDG", "ENZL", "QAT", "TUR", "UAE", "IBB", "SOXX", "AMCA", "EMIF", "ICLN", "WOOD", "INDY", "IJT", "DVY", "SHV", "IGSB", "PFF", "ISRL", "ITI", "ITRM", "ITRI", "ITRN", "IVENC", "IVFGC", "IVFVC", "IZEA", "JJSF", "MAYS", "JBHT", "JCOM", "JKHY", "JACK", "JAGX", "JAKK", "JRVR", "JSML", "JSMD", "JASN", "JASNW", "JAZZ", "JD", "JSYN", "JSYNR", "JSYNU", "JSYNW", "JRSH", "JBLU", "JCTCF", "JMU", "JBSS", "JOUT", "JNCE", "KALU", "KALA", "KALV", "KMDA", "KNDI", "KPTI", "KZIA", "KBLM", "KBLMR", "KBLMU", "KBLMW", "KBSF", "KCAP", "KCAPL", "KRNY", "KELYA", "KELYB", "KMPH", "KFFB", "KEQU", "KTCC", "KZR", "KFRC", "KE", "KBAL", "KIN", "KGJI", "KINS", "KNSA", "KNSL", "KIRK", "KTOV", "KTOVW", "KLAC", "KLXE", "KOD", "KONA", "KOPN", "KRNT", "KOSS", "KWEB", "KTOS", "KRYS", "KLIC", "KURA", "KVHI", "FSTR", "LJPC", "LSBK", "LBAI", "LKFN", "LAKE", "LRCX", "LAMR", "LANC", "LNDC", "LARK", "LMRK", "LMRKN", "LMRKO", "LMRKP", "LE", "LSTR", "LNTH", "LTRX", "LSCC", "LAUR", "LAWS", "LAZY", "LCNB", "LPTX", "LEGH", "LGCY", "LTXB", "DDBI", "EDBI", "INFR", "LVHD", "SQLV", "UDBI", "LACQ", "LACQU", "LACQW", "LMAT", "TREE", "LEVL", "LXRX", "LX", "LFAC", "LFACU", "LFACW", "LGIH", "LHCG", "LLIT", "LBRDA", "LBRDK", "LEXEA", "LEXEB", "LBTYA", "LBTYB", "LBTYK", "LILA", "LILAK", "BATRA", "BATRK", "FWONA", "FWONK", "LSXMA", "LSXMB", "LSXMK", "LTRPA", "LTRPB", "LCUT", "LFVN", "LWAY", "LGND", "LTBR", "LPTH", "LLEX", "LMB", "LLNW", "LMST", "LMNR", "LINC", "LECO", "LIND", "LINDW", "LPCN", "YVR", "LQDA", "LQDT", "LFUS", "LIVN", "LOB", "LIVE", "LPSN", "LIVX", "LKQ", "LMFA", "LMFAW", "LOGC", "LOGI", "LOGM", "CNCR", "CHNA", "LONE", "LOAC", "LOACR", "LOACU", "LOACW", "LOOP", "LORL", "LOXO", "LPLA", "LRAD", "LYTS", "LULU", "LITE", "LMNX", "LUNA", "LBC", "MBTF", "MCBC", "MFNC", "MTSI", "MGNX", "MDGL", "MAGS", "MGLN", "MGTA", "MGIC", "MNGA", "MGYR", "MHLD", "MMYT", "MBUU", "MLVF", "MAMS", "TUSK", "RPIBC", "MANH", "LOAN", "MNTX", "MTEX", "MNKD", "MANT", "MAPI", "MARA", "MCHX", "MRIN", "MARPS", "MRNS", "MRKR", "MKTX", "MRLN", "MAR", "MBII", "MRTN", "MMLP", "MRVL", "MASI", "MCFT", "MTCH", "MTLS", "MTRX", "MAT", "MATW", "MXIM", "MXWL", "MBFI", "MBFIO", "MGRC", "MDCA", "MDRR", "MFIN", "MFINL", "MTBC", "MTBCP", "MNOV", "MDSO", "MDGS", "MDGSW", "MDWD", "MEDP", "MEIP", "MGTX", "MLCO", "MLNT", "MLNX", "MELR", "MNLO", "MTSL", "MELI", "AMTB", "AMTBB", "MBWM", "MERC", "MBIN", "MRCY", "MREO", "EBSB", "VIVO", "MRBK", "MMSI", "MACK", "MRSN", "MRUS", "MESA", "MLAB", "MESO", "CASH", "MEOH", "MGEE", "MGPI", "MBOT", "MCHP", "MU", "MSFT", "MSTR", "MVIS", "MICT", "MPB", "MTP", "MCEP", "MBCN", "MSEX", "MSBI", "MSVB", "MOFG", "MLND", "MIME", "MNDO", "MB", "NERV", "MGEN", "MRTX", "MSON", "MIND", "MINDP", "MITK", "MKSI", "MMAC", "MTC", "MINI", "MOBL", "MMDM", "MMDMR", "MMDMU", "MMDMW", "MRNA", "MOGO", "MTEM", "MBRX", "MNTA", "MOMO", "MKGI", "MCRI", "MDLZ", "MGI", "MDB", "MPWR", "TYPE", "MNRO", "MRCC", "MRCCL", "MNST", "MORN", "MOR", "MOSY", "MOTA", "MTFB", "MTFBW", "MPAA", "MOTS", "MPVD", "MOXC", "COOP", "MRIC", "MSBF", "MTEC", "MTECU", "MTECW", "MTSC", "MUDS", "MUDSU", "MUDSW", "LABL", "MBIO", "MFSF", "MVBF", "MYSZ", "MYL", "MYND", "MYNDW", "MYOK", "MYOS", "MYRG", "MYGN", "NBRV", "NAKD", "NNDM", "NANO", "NSTG", "NAOV", "NH", "NK", "NSSC", "NDAQ", "NTRA", "NATH", "NAUH", "NKSH", "FIZZ", "NCMI", "NCOM", "NESR", "NESRW", "NGHC", "NGHCN", "NGHCO", "NGHCP", "NGHCZ", "NHLD", "NHLDW", "NATI", "NRC", "NSEC", "EYE", "NWLI", "NAII", "NHTC", "NATR", "BABY", "JSM", "NAVI", "NMCI", "NBCP", "NBTB", "NCSM", "NEBU", "NEBUU", "NEBUW", "NKTR", "NMRD", "NEOG", "NEO", "NTGN", "NEON", "NEOS", "NVCN", "NEPT", "UEPS", "NETE", "NTAP", "NTES", "NFLX", "NTGR", "NTCT", "NTWK", "CUR", "NBIX", "NURO", "NUROW", "STIM", "NTRP", "NBEV", "NYMT", "NYMTN", "NYMTO", "NYMTP", "NEWA", "NWL", "NLNK", "NMRK", "NWS", "NWSA", "NEWT", "NEWTI", "NEWTZ", "NXEO", "NXEOU", "NXEOW", "NXMD", "NXST", "NEXT", "NXGN", "NFEC", "NODK", "EGOV", "NICE", "NICK", "NCBS", "NITE", "NIHD", "NIU", "LASR", "NMIH", "NNBR", "NDLS", "NDSN", "NSYS", "NBN", "NTIC", "NTRS", "NTRSP", "NFBK", "NRIM", "NWBI", "NWPX", "NCLH", "NWFL", "NVFY", "NVMI", "NOVN", "NOVT", "NVAX", "NVLN", "NVCR", "NVMM", "NVUS", "NUAN", "NCNA", "NTNX", "NTRI", "NUVA", "NVTR", "QQQX", "NVEE", "NVEC", "NVDA", "NXPI", "NXTM", "NXTD", "NXTDW", "NYMX", "OIIM", "OVLY", "OCSL", "OCSLL", "OCSI", "OASM", "OBLN", "OBSV", "OBCI", "OPTT", "OCFC", "OFED", "OCUL", "ODT", "OMEX", "ODP", "OFS", "OFSSL", "OFSSZ", "OCCI", "OHAI", "OVBC", "OHRP", "OKTA", "ODFL", "OLBK", "ONB", "OPOF", "OSBC", "OSBCP", "OLLI", "ZEUS", "OFLX", "OMER", "OMCL", "ON", "OTIV", "ONCY", "OMED", "ONTX", "ONTXW", "ONCS", "OHGI", "OSS", "OSPN", "OPBK", "OTEX", "OPRA", "OPES", "OPESU", "OPESW", "OPGN", "OPGNW", "OPHT", "OPNT", "OPK", "OBAS", "OCC", "OPRX", "OPHC", "OPTN", "OPB", "ORMP", "OSUR", "ORBC", "ORBK", "ORTX", "ORLY", "ORGO", "ORGOW", "ONVO", "ORGS", "SEED", "OBNK", "OESX", "ORIT", "ORRF", "OFIX", "KIDS", "OSIS", "OSIR", "OSMT", "OSN", "OTEL", "OTG", "OTIC", "OTTW", "OTTR", "OTLK", "OTLKW", "OSTK", "OVID", "OXBR", "OXBRW", "OXFD", "OXLC", "OXLCM", "OXLCO", "OXSQ", "OXSQL", "PFIN", "PTSI", "PCAR", "VETS", "PACB", "PCB", "PEIX", "PMBC", "PPBI", "PCRX", "PACW", "PTIE", "PAAS", "PANL", "PZZA", "FRSH", "PRTK", "TEUM", "PNRL", "PCYG", "PKBK", "PKOH", "PTNR", "PBHC", "PATK", "PNBK", "PATI", "PEGI", "PDCO", "PTEN", "PAVM", "PAVMW", "PAVMZ", "PAYX", "PCTY", "PYDS", "PYPL", "PBBI", "CNXN", "PCMI", "PCSB", "PCTI", "PDCE", "PDFS", "PDLI", "PDLB", "PDVW", "SKIS", "PGC", "PEER", "PEGA", "PENN", "PVAC", "PFLT", "PNNT", "PWOD", "WRLS", "WRLSR", "WRLSU", "WRLSW", "PEBO", "PEBK", "PFIS", "PBCT", "PBCTP", "PUB", "KPFS", "PEP", "PRCP", "PRFT", "PFMT", "PERI", "PESI", "PPIH", "PTX", "PGLC", "PETQ", "PETS", "PFSW", "PGTI", "PHAS", "PHII", "PHIIK", "PAHC", "PHIO", "PHIOW", "PLAB", "PHUN", "PHUNW", "PICO", "PLL", "PIRS", "PPC", "PDD", "PME", "PNFP", "PT", "PPSI", "PXLW", "EAGL", "EAGLU", "EAGLW", "PLYA", "PLXS", "PLUG", "PLBC", "PS", "PSTI", "PLXP", "PNTR", "PCOM", "POLA", "PTE", "POLY", "POOL", "POPE", "BPOP", "BPOPM", "BPOPN", "PTLA", "PBPB", "PCH", "POWL", "POWI", "PRAA", "PRAH", "PRAN", "PRPO", "AIPT", "PFBC", "PLPC", "PFBI", "PINC", "LENS", "PSDO", "PBIO", "PRGX", "PSMT", "PNRG", "PRMW", "PRIM", "PVAL", "PFG", "BTEC", "PXUS", "GENY", "PSET", "PY", "PMOM", "USMC", "PSC", "PRNB", "PRTH", "PRTHU", "PRTHW", "PDEX", "IPDN", "PFIE", "PGNX", "PRGS", "LUNG", "PFPT", "PRPH", "PRQR", "EQRR", "BIB", "UBIO", "TQQQ", "ZBIO", "SQQQ", "BIS", "PSEC", "PTGX", "PTVCA", "PTVCB", "PRTO", "PTI", "PRTA", "PRVB", "PVBC", "PROV", "PBIP", "PMD", "PTC", "PTCT", "PHCF", "PULM", "PLSE", "PBYI", "PACQ", "PACQU", "PACQW", "PCYO", "PRPL", "PXS", "QADA", "QADB", "QCRH", "QGEN", "QIWI", "QRVO", "QCOM", "QBAK", "QLYS", "QTNA", "QTRX", "QTRH", "QRHC", "QUIK", "QDEL", "QNST", "QUMU", "QTNT", "QRTEA", "QRTEB", "QTT", "RRD", "RCM", "RARX", "RADA", "RDCM", "RDUS", "RDNT", "RDWR", "METC", "RMBS", "RAND", "RNDB", "RPD", "RAVE", "RAVN", "RBB", "ROLL", "RICK", "RCMT", "RDI", "RDIB", "RGSE", "BCNA", "BLCN", "RLM", "RNWK", "RP", "RETA", "RCON", "REPH", "RRGB", "RRR", "RDVT", "RDFN", "RDHL", "RBZ", "RBZAW", "REG", "REGN", "RGNX", "RGLS", "RBNC", "RELV", "MARK", "RRI", "RNST", "REGI", "ABAC", "RCII", "RGEN", "REPL", "RBCAA", "FRBK", "REFR", "RESN", "RECN", "HAIR", "TORC", "ROIC", "RETO", "RTRX", "RVNC", "RVEN", "RVLT", "RWLK", "RFIL", "RGCO", "RYTM", "RBBN", "RIBT", "RELL", "RIGL", "RNET", "RMNI", "RIOT", "REDU", "RTTR", "RVSB", "RIVE", "RCKT", "RMTI", "RCKY", "RMCF", "ROKU", "ROSE", "ROSEU", "ROSEW", "ROST", "RGLD", "RTIX", "RBCN", "RUBY", "RMBL", "RUSHA", "RUSHB", "RUTH", "RYAAY", "STBA", "SANW", "SCAC", "SCACU", "SCACW", "SBRA", "SABR", "SAEX", "SFET", "SAFT", "SGA", "SAGE", "SAIA", "SALM", "SAL", "SAFM", "SASR", "SGMO", "SANM", "GCVRZ", "SNY", "SPNS", "SRPT", "SVRA", "SBFG", "SBFGP", "SBBX", "SBAC", "SCSC", "SMIT", "SCHN", "SRRK", "SCHL", "SAMAU", "SGMS", "SCPH", "SCYX", "SEAC", "SBCF", "STX", "SHIP", "SHIPW", "SHOS", "SPNE", "SGEN", "EYES", "EYESW", "SECO", "SCWX", "SNFCA", "SEIC", "SLCT", "SIC", "SELB", "SIGI", "SLS", "LEDS", "SMTC", "SENEA", "SENEB", "SNES", "SNH", "SNHNI", "SNHNL", "AIHS", "SRTS", "SRTSW", "STNL", "STNLU", "STNLW", "SQBG", "MCRB", "SREV", "SFBS", "SESN", "SVBI", "SGBX", "SGOC", "SMED", "SHSP", "SHEN", "PIXY", "SHLO", "SCCI", "TYHT", "SHPG", "SCVL", "SHBI", "SSTI", "SFLY", "SIFI", "SIBN", "SIEB", "SNNA", "SIEN", "BSRR", "SRRA", "SWIR", "SIFY", "SIGA", "SGLB", "SGLBW", "SGMA", "SBNY", "SLGN", "SILC", "SLAB", "SIMO", "SAMG", "SSNT", "SFNC", "SLP", "SINA", "SBGI", "SINO", "SVA", "SINT", "SG", "SIRI", "SRVA", "SITO", "SKYS", "SKYW", "SWKS", "SNBR", "SLM", "SLMBP", "SMSH", "SMSHW", "SGH", "SND", "SMBK", "SMSI", "SMTX", "SRAX", "SCKT", "SOHU", "SLRC", "SUNS", "SEDG", "SLNO", "SLNOW", "SLGL", "SLDB", "SNGX", "SNGXW", "SNOA", "SNOAW", "SONO", "SPHS", "SORL", "SRNE", "SOHO", "SOHOB", "SOHOO", "SOHOK", "SFBC", "SSB", "SFST", "SMBC", "SONA", "SBSI", "SP", "SGRP", "SPKE", "SPKEP", "ONCE", "SPAR", "SPTN", "DWFI", "SPPI", "SPRO", "ANY", "SPEX", "SPI", "SAVE", "STXB", "SPLK", "SPOK", "SPWH", "SBPH", "FUND", "SFM", "SPSC", "SSNC", "SSLJ", "SSRM", "STAA", "STAF", "STMP", "STND", "SBLK", "SBLKZ", "SBUX", "STFC", "GASS", "STCN", "STLD", "SMRT", "SBOT", "STML", "SRCL", "SBT", "STRL", "SHOO", "SSFN", "SFIX", "SYBT", "BANX", "STNE", "SSKN", "SSYS", "STRA", "HNDL", "STRT", "STRS", "STRM", "SBBP", "SUMR", "SMMF", "SSBI", "SMMT", "WISA", "SNHY", "SNDE", "SNSS", "STKL", "SPWR", "RUN", "SUNW", "SPCB", "SCON", "SGC", "SUPN", "SPRT", "SURF", "SGRY", "SRDX", "STRO", "SIVB", "SVMK", "SYKE", "SYMC", "SYNC", "SYNL", "SYNA", "SNCR", "SNDX", "SYNH", "SGYP", "SYBX", "SNPS", "SES", "THOR", "SYPR", "SYRS", "TROW", "TTOO", "TRHC", "TCMD", "TAIT", "TLC", "TTWO", "TLND", "TNDM", "TLF", "TANH", "TAOP", "TEDU", "TATT", "TAYD", "CGBD", "AMTD", "PETZ", "TECD", "TCCO", "TTGT", "TGLS", "TGEN", "TNAV", "TLGT", "TELL", "TENB", "TENX", "TZAC", "TZACU", "TZACW", "TER", "TERP", "TBNK", "TSRO", "TSLA", "TESS", "TTEK", "TTPH", "TCBI", "TCBIL", "TCBIP", "TCBIW", "TXN", "TXRH", "TFIG", "TFSL", "TGTX", "WTER", "ANDE", "TBBK", "BPRN", "CG", "TCGP", "CAKE", "CHEF", "TCFC", "DSGX", "DXYN", "ENSG", "XONE", "FBMS", "FLIC", "GT", "HABT", "HCKT", "HAIN", "CUBA", "INTG", "JYNT", "KEYW", "KHC", "OLD", "LOVE", "MSG", "MDCO", "MEET", "MIK", "MIDD", "NAVG", "SLIM", "STKS", "ORG", "PRSC", "RMR", "SMPL", "TSG", "TTD", "ULTI", "YORW", "NCTY", "TXMD", "TRPX", "TBPH", "TST", "TCRD", "TBRG", "TBRGU", "TBRGW", "TIBR", "TIBRU", "TIBRW", "TTTN", "TTS", "TLRY", "TSBK", "TIPT", "TITN", "TMDI", "TTNP", "TVTY", "TIVO", "TLSA", "TKKS", "TKKSR", "TKKSU", "TKKSW", "TMUS", "TMSR", "TOCA", "TNXP", "TISA", "TOPS", "TRCH", "TRMD", "TOTA", "TOTAR", "TOTAU", "TOTAW", "TBLT", "TBLTU", "TBLTW", "TSEM", "CLUB", "TOWN", "TPIC", "TCON", "TSCO", "TWMC", "TACT", "TRNS", "TGA", "TBIO", "TA", "TANNI", "TANNL", "TANNZ", "TZOO", "TRMT", "TRVN", "TPCO", "TCDA", "TCBK", "TDAC", "TDACU", "TDACW", "TRIL", "TRS", "TRMB", "TRIB", "TMCX", "TMCXU", "TMCXW", "TRIP", "TSC", "TSCAP", "TBK", "TRVG", "TROV", "TRUE", "THST", "TRUP", "TRST", "TRMK", "TSRI", "TTEC", "TTMI", "TC", "TCX", "TUES", "TOUR", "HEAR", "TWLV", "TWLVR", "TWLVU", "TWLVW", "FOX", "FOXA", "TWIN", "TWST", "TRCB", "TYME", "USCR", "PRTS", "USEG", "GROW", "USAU", "USWS", "USWSW", "UBNT", "UFPT", "ULTA", "UCTT", "UPL", "RARE", "ULBI", "UMBF", "UMPQ", "UNAM", "UBSH", "UNB", "QURE", "UBCP", "UBOH", "UBSI", "UCBI", "UCFC", "UAL", "UBNK", "UFCS", "UIHC", "UNFI", "UBFO", "USLM", "UTHR", "UG", "UNIT", "UNTY", "UBX", "OLED", "UEIC", "UFPI", "ULH", "USAP", "UVSP", "UMRX", "UPLD", "UPWK", "UONE", "UONEK", "URBN", "URGN", "UROV", "ECOL", "USAT", "USATP", "USAK", "UTMD", "UTSI", "UXIN", "VCNX", "VLRX", "VALX", "VLY", "VLYPO", "VLYPP", "VTEC", "VALU", "VNDA", "BBH", "GNRX", "PPH", "VWOB", "VNQI", "VCIT", "VGIT", "VIGI", "VYMI", "VCLT", "VGLT", "VMBS", "VONE", "VONG", "VONV", "VTWO", "VTWG", "VTWV", "VTHR", "VCSH", "VTIP", "VGSH", "BND", "VTC", "BNDX", "VXUS", "BNDW", "VEAC", "VEACU", "VEACW", "VREX", "VRNS", "VBLT", "VXRT", "VBIV", "VTIQ", "VTIQU", "VTIQW", "VECO", "VEON", "VRA", "VCYT", "VSTM", "VCEL", "VRNT", "VRSN", "VRSK", "VBTX", "VERI", "VRML", "VRNA", "VRRM", "VRCA", "VTNR", "VRTX", "VERU", "VIA", "VIAB", "VMET", "VSAT", "VIAV", "VICL", "VICR", "VCTR", "CIZ", "VSDA", "CEY", "CEZ", "CID", "CIL", "CFO", "CFA", "CSF", "CDC", "CDL", "VSMV", "CSB", "CSA", "VRAY", "VKTX", "VKTXW", "VBFC", "VLGEA", "VIOT", "VNOM", "VIRC", "VTSI", "VIRT", "VRTS", "VRTSP", "BBC", "BBP", "VRTU", "VTGN", "VC", "VIST", "VTL", "VIVE", "VVPR", "VVUS", "VOD", "VOXX", "VYGR", "VSEC", "VTVT", "VUZI", "WTRH", "WBA", "WAFD", "WASH", "WSBF", "WVE", "WNFM", "WSTG", "WCFB", "WDFC", "WB", "WTW", "WEBK", "WEN", "WERN", "WSBC", "WTBA", "WABC", "WSTL", "WBND", "WDC", "WNEB", "WPRT", "WWR", "WEYS", "WHLR", "WHLRD", "WHLRP", "WHLRW", "WHF", "WHFBZ", "WHLM", "WVVI", "WVVIP", "WLDN", "WLFC", "WLTW", "WSC", "WIN", "WING", "WINA", "WINS", "WTFC", "WTFCM", "AGND", "CXSE", "EMCG", "EMCB", "DGRE", "DXGE", "HYZD", "AGZD", "WETF", "DXJS", "GULF", "HYND", "DGRW", "DGRS", "WIX", "WWD", "WDAY", "WKHS", "WRLD", "WRTC", "WMGI", "WMGIZ", "WSFS", "WVFC", "WYNN", "XBIT", "XELB", "XEL", "XNCR", "XBIO", "XENE", "XERS", "XGTI", "XLNX", "XOMA", "XPER", "XSPA", "XTLB", "XNET", "YNDX", "YRIV", "YTRA", "YTEN", "YIN", "YMAB", "YOGA", "YGYI", "YRCW", "YY", "ZFGN", "ZAGG", "ZLAB", "ZEAL", "ZBRA", "Z", "ZG", "ZN", "ZNWAA", "ZION", "ZIONW", "ZIOP", "ZIXI", "ZKIN", "ZGNX", "ZSAN", "ZS", "ZUMZ", "ZYNE", "ZNGA"] 3 | } -------------------------------------------------------------------------------- /v2/backend/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@types/node@*": 6 | version "10.12.18" 7 | resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.18.tgz#1d3ca764718915584fcd9f6344621b7672665c67" 8 | integrity sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ== 9 | 10 | accepts@~1.3.5: 11 | version "1.3.5" 12 | resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2" 13 | integrity sha1-63d99gEXI6OxTopywIBcjoZ0a9I= 14 | dependencies: 15 | mime-types "~2.1.18" 16 | negotiator "0.6.1" 17 | 18 | array-flatten@1.1.1: 19 | version "1.1.1" 20 | resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" 21 | integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= 22 | 23 | async@2.6.1: 24 | version "2.6.1" 25 | resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" 26 | integrity sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ== 27 | dependencies: 28 | lodash "^4.17.10" 29 | 30 | axios@^0.18.0: 31 | version "0.18.0" 32 | resolved "https://registry.yarnpkg.com/axios/-/axios-0.18.0.tgz#32d53e4851efdc0a11993b6cd000789d70c05102" 33 | integrity sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI= 34 | dependencies: 35 | follow-redirects "^1.3.0" 36 | is-buffer "^1.1.5" 37 | 38 | bcryptjs@^2.4.3: 39 | version "2.4.3" 40 | resolved "https://registry.yarnpkg.com/bcryptjs/-/bcryptjs-2.4.3.tgz#9ab5627b93e60621ff7cdac5da9733027df1d0cb" 41 | integrity sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms= 42 | 43 | bluebird@3.5.1: 44 | version "3.5.1" 45 | resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" 46 | integrity sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA== 47 | 48 | body-parser@1.18.3, body-parser@^1.18.3: 49 | version "1.18.3" 50 | resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.3.tgz#5b292198ffdd553b3a0f20ded0592b956955c8b4" 51 | integrity sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ= 52 | dependencies: 53 | bytes "3.0.0" 54 | content-type "~1.0.4" 55 | debug "2.6.9" 56 | depd "~1.1.2" 57 | http-errors "~1.6.3" 58 | iconv-lite "0.4.23" 59 | on-finished "~2.3.0" 60 | qs "6.5.2" 61 | raw-body "2.3.3" 62 | type-is "~1.6.16" 63 | 64 | boolbase@~1.0.0: 65 | version "1.0.0" 66 | resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" 67 | integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= 68 | 69 | bson@^1.1.0, bson@~1.1.0: 70 | version "1.1.0" 71 | resolved "https://registry.yarnpkg.com/bson/-/bson-1.1.0.tgz#bee57d1fb6a87713471af4e32bcae36de814b5b0" 72 | integrity sha512-9Aeai9TacfNtWXOYarkFJRW2CWo+dRon+fuLZYJmvLV3+MiUp0bEI6IAZfXEIg7/Pl/7IWlLaDnhzTsD81etQA== 73 | 74 | buffer-equal-constant-time@1.0.1: 75 | version "1.0.1" 76 | resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" 77 | integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk= 78 | 79 | bytes@3.0.0: 80 | version "3.0.0" 81 | resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" 82 | integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= 83 | 84 | cheerio@^1.0.0-rc.2: 85 | version "1.0.0-rc.2" 86 | resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.2.tgz#4b9f53a81b27e4d5dac31c0ffd0cfa03cc6830db" 87 | integrity sha1-S59TqBsn5NXawxwP/Qz6A8xoMNs= 88 | dependencies: 89 | css-select "~1.2.0" 90 | dom-serializer "~0.1.0" 91 | entities "~1.1.1" 92 | htmlparser2 "^3.9.1" 93 | lodash "^4.15.0" 94 | parse5 "^3.0.1" 95 | 96 | content-disposition@0.5.2: 97 | version "0.5.2" 98 | resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" 99 | integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ= 100 | 101 | content-type@~1.0.4: 102 | version "1.0.4" 103 | resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" 104 | integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== 105 | 106 | cookie-signature@1.0.6: 107 | version "1.0.6" 108 | resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" 109 | integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= 110 | 111 | cookie@0.3.1: 112 | version "0.3.1" 113 | resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" 114 | integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s= 115 | 116 | css-select@~1.2.0: 117 | version "1.2.0" 118 | resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" 119 | integrity sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg= 120 | dependencies: 121 | boolbase "~1.0.0" 122 | css-what "2.1" 123 | domutils "1.5.1" 124 | nth-check "~1.0.1" 125 | 126 | css-what@2.1: 127 | version "2.1.2" 128 | resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.2.tgz#c0876d9d0480927d7d4920dcd72af3595649554d" 129 | integrity sha512-wan8dMWQ0GUeF7DGEPVjhHemVW/vy6xUYmFzRY8RYqgA0JtXC9rJmbScBjqSu6dg9q0lwPQy6ZAmJVr3PPTvqQ== 130 | 131 | debug@2.6.9: 132 | version "2.6.9" 133 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" 134 | integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== 135 | dependencies: 136 | ms "2.0.0" 137 | 138 | debug@3.1.0, debug@=3.1.0: 139 | version "3.1.0" 140 | resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" 141 | integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== 142 | dependencies: 143 | ms "2.0.0" 144 | 145 | depd@~1.1.2: 146 | version "1.1.2" 147 | resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" 148 | integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= 149 | 150 | destroy@~1.0.4: 151 | version "1.0.4" 152 | resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" 153 | integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= 154 | 155 | dom-serializer@0, dom-serializer@~0.1.0: 156 | version "0.1.0" 157 | resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" 158 | integrity sha1-BzxpdUbOB4DOI75KKOKT5AvDDII= 159 | dependencies: 160 | domelementtype "~1.1.1" 161 | entities "~1.1.1" 162 | 163 | domelementtype@1, domelementtype@^1.3.0: 164 | version "1.3.1" 165 | resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" 166 | integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== 167 | 168 | domelementtype@~1.1.1: 169 | version "1.1.3" 170 | resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" 171 | integrity sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs= 172 | 173 | domhandler@^2.3.0: 174 | version "2.4.2" 175 | resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" 176 | integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== 177 | dependencies: 178 | domelementtype "1" 179 | 180 | domutils@1.5.1: 181 | version "1.5.1" 182 | resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" 183 | integrity sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8= 184 | dependencies: 185 | dom-serializer "0" 186 | domelementtype "1" 187 | 188 | domutils@^1.5.1: 189 | version "1.7.0" 190 | resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" 191 | integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== 192 | dependencies: 193 | dom-serializer "0" 194 | domelementtype "1" 195 | 196 | dotenv@^6.2.0: 197 | version "6.2.0" 198 | resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-6.2.0.tgz#941c0410535d942c8becf28d3f357dbd9d476064" 199 | integrity sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w== 200 | 201 | ecdsa-sig-formatter@1.0.10: 202 | version "1.0.10" 203 | resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.10.tgz#1c595000f04a8897dfb85000892a0f4c33af86c3" 204 | integrity sha1-HFlQAPBKiJffuFAAiSoPTDOvhsM= 205 | dependencies: 206 | safe-buffer "^5.0.1" 207 | 208 | ee-first@1.1.1: 209 | version "1.1.1" 210 | resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" 211 | integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= 212 | 213 | encodeurl@~1.0.2: 214 | version "1.0.2" 215 | resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" 216 | integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= 217 | 218 | entities@^1.1.1, entities@~1.1.1: 219 | version "1.1.2" 220 | resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" 221 | integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== 222 | 223 | escape-html@~1.0.3: 224 | version "1.0.3" 225 | resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" 226 | integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= 227 | 228 | etag@~1.8.1: 229 | version "1.8.1" 230 | resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" 231 | integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= 232 | 233 | express@^4.16.4: 234 | version "4.16.4" 235 | resolved "https://registry.yarnpkg.com/express/-/express-4.16.4.tgz#fddef61926109e24c515ea97fd2f1bdbf62df12e" 236 | integrity sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg== 237 | dependencies: 238 | accepts "~1.3.5" 239 | array-flatten "1.1.1" 240 | body-parser "1.18.3" 241 | content-disposition "0.5.2" 242 | content-type "~1.0.4" 243 | cookie "0.3.1" 244 | cookie-signature "1.0.6" 245 | debug "2.6.9" 246 | depd "~1.1.2" 247 | encodeurl "~1.0.2" 248 | escape-html "~1.0.3" 249 | etag "~1.8.1" 250 | finalhandler "1.1.1" 251 | fresh "0.5.2" 252 | merge-descriptors "1.0.1" 253 | methods "~1.1.2" 254 | on-finished "~2.3.0" 255 | parseurl "~1.3.2" 256 | path-to-regexp "0.1.7" 257 | proxy-addr "~2.0.4" 258 | qs "6.5.2" 259 | range-parser "~1.2.0" 260 | safe-buffer "5.1.2" 261 | send "0.16.2" 262 | serve-static "1.13.2" 263 | setprototypeof "1.1.0" 264 | statuses "~1.4.0" 265 | type-is "~1.6.16" 266 | utils-merge "1.0.1" 267 | vary "~1.1.2" 268 | 269 | finalhandler@1.1.1: 270 | version "1.1.1" 271 | resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105" 272 | integrity sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg== 273 | dependencies: 274 | debug "2.6.9" 275 | encodeurl "~1.0.2" 276 | escape-html "~1.0.3" 277 | on-finished "~2.3.0" 278 | parseurl "~1.3.2" 279 | statuses "~1.4.0" 280 | unpipe "~1.0.0" 281 | 282 | follow-redirects@^1.3.0: 283 | version "1.6.0" 284 | resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.6.0.tgz#d12452c031e8c67eb6637d861bfc7a8090167933" 285 | integrity sha512-4Oh4eI3S9OueVV41AgJ1oLjpaJUhbJ7JDGOMhe0AFqoSejl5Q2nn3eGglAzRUKVKZE8jG5MNn66TjCJMAnpsWA== 286 | dependencies: 287 | debug "=3.1.0" 288 | 289 | forwarded@~0.1.2: 290 | version "0.1.2" 291 | resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" 292 | integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= 293 | 294 | fresh@0.5.2: 295 | version "0.5.2" 296 | resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" 297 | integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= 298 | 299 | htmlparser2@^3.9.1: 300 | version "3.10.0" 301 | resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.0.tgz#5f5e422dcf6119c0d983ed36260ce9ded0bee464" 302 | integrity sha512-J1nEUGv+MkXS0weHNWVKJJ+UrLfePxRWpN3C9bEi9fLxL2+ggW94DQvgYVXsaT30PGwYRIZKNZXuyMhp3Di4bQ== 303 | dependencies: 304 | domelementtype "^1.3.0" 305 | domhandler "^2.3.0" 306 | domutils "^1.5.1" 307 | entities "^1.1.1" 308 | inherits "^2.0.1" 309 | readable-stream "^3.0.6" 310 | 311 | http-errors@1.6.3, http-errors@~1.6.2, http-errors@~1.6.3: 312 | version "1.6.3" 313 | resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" 314 | integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= 315 | dependencies: 316 | depd "~1.1.2" 317 | inherits "2.0.3" 318 | setprototypeof "1.1.0" 319 | statuses ">= 1.4.0 < 2" 320 | 321 | iconv-lite@0.4.23: 322 | version "0.4.23" 323 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" 324 | integrity sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA== 325 | dependencies: 326 | safer-buffer ">= 2.1.2 < 3" 327 | 328 | inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3: 329 | version "2.0.3" 330 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" 331 | integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= 332 | 333 | ipaddr.js@1.8.0: 334 | version "1.8.0" 335 | resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.0.tgz#eaa33d6ddd7ace8f7f6fe0c9ca0440e706738b1e" 336 | integrity sha1-6qM9bd16zo9/b+DJygRA5wZzix4= 337 | 338 | is-buffer@^1.1.5: 339 | version "1.1.6" 340 | resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" 341 | integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== 342 | 343 | jsonwebtoken@^8.4.0: 344 | version "8.4.0" 345 | resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.4.0.tgz#8757f7b4cb7440d86d5e2f3becefa70536c8e46a" 346 | integrity sha512-coyXjRTCy0pw5WYBpMvWOMN+Kjaik2MwTUIq9cna/W7NpO9E+iYbumZONAz3hcr+tXFJECoQVrtmIoC3Oz0gvg== 347 | dependencies: 348 | jws "^3.1.5" 349 | lodash.includes "^4.3.0" 350 | lodash.isboolean "^3.0.3" 351 | lodash.isinteger "^4.0.4" 352 | lodash.isnumber "^3.0.3" 353 | lodash.isplainobject "^4.0.6" 354 | lodash.isstring "^4.0.1" 355 | lodash.once "^4.0.0" 356 | ms "^2.1.1" 357 | 358 | jwa@^1.1.5: 359 | version "1.1.6" 360 | resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.1.6.tgz#87240e76c9808dbde18783cf2264ef4929ee50e6" 361 | integrity sha512-tBO/cf++BUsJkYql/kBbJroKOgHWEigTKBAjjBEmrMGYd1QMBC74Hr4Wo2zCZw6ZrVhlJPvoMrkcOnlWR/DJfw== 362 | dependencies: 363 | buffer-equal-constant-time "1.0.1" 364 | ecdsa-sig-formatter "1.0.10" 365 | safe-buffer "^5.0.1" 366 | 367 | jws@^3.1.5: 368 | version "3.1.5" 369 | resolved "https://registry.yarnpkg.com/jws/-/jws-3.1.5.tgz#80d12d05b293d1e841e7cb8b4e69e561adcf834f" 370 | integrity sha512-GsCSexFADNQUr8T5HPJvayTjvPIfoyJPtLQBwn5a4WZQchcrPMPMAWcC1AzJVRDKyD6ZPROPAxgv6rfHViO4uQ== 371 | dependencies: 372 | jwa "^1.1.5" 373 | safe-buffer "^5.0.1" 374 | 375 | kareem@2.3.0: 376 | version "2.3.0" 377 | resolved "https://registry.yarnpkg.com/kareem/-/kareem-2.3.0.tgz#ef33c42e9024dce511eeaf440cd684f3af1fc769" 378 | integrity sha512-6hHxsp9e6zQU8nXsP+02HGWXwTkOEw6IROhF2ZA28cYbUk4eJ6QbtZvdqZOdD9YPKghG3apk5eOCvs+tLl3lRg== 379 | 380 | lodash.foreach@^4.1.0: 381 | version "4.5.0" 382 | resolved "https://registry.yarnpkg.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53" 383 | integrity sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM= 384 | 385 | lodash.get@4.4.2, lodash.get@^4.0.2: 386 | version "4.4.2" 387 | resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" 388 | integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= 389 | 390 | lodash.includes@^4.3.0: 391 | version "4.3.0" 392 | resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" 393 | integrity sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8= 394 | 395 | lodash.isboolean@^3.0.3: 396 | version "3.0.3" 397 | resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" 398 | integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY= 399 | 400 | lodash.isinteger@^4.0.4: 401 | version "4.0.4" 402 | resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" 403 | integrity sha1-YZwK89A/iwTDH1iChAt3sRzWg0M= 404 | 405 | lodash.isnumber@^3.0.3: 406 | version "3.0.3" 407 | resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" 408 | integrity sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w= 409 | 410 | lodash.isplainobject@^4.0.6: 411 | version "4.0.6" 412 | resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" 413 | integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs= 414 | 415 | lodash.isstring@^4.0.1: 416 | version "4.0.1" 417 | resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" 418 | integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE= 419 | 420 | lodash.once@^4.0.0: 421 | version "4.1.1" 422 | resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" 423 | integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= 424 | 425 | lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.11: 426 | version "4.17.11" 427 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" 428 | integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== 429 | 430 | media-typer@0.3.0: 431 | version "0.3.0" 432 | resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" 433 | integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= 434 | 435 | memory-pager@^1.0.2: 436 | version "1.4.0" 437 | resolved "https://registry.yarnpkg.com/memory-pager/-/memory-pager-1.4.0.tgz#8902c72ce2fa34319adc0dae586b7d83cec6d6ac" 438 | integrity sha512-ycuyV5gKpZln7HB/A11wCpAxEY9VQ2EhYU1F56pUAxvmj6OyOHtB9tkLLjAyFsPdghSP2S3Ujk3aYJCusgiMZg== 439 | 440 | merge-descriptors@1.0.1: 441 | version "1.0.1" 442 | resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" 443 | integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= 444 | 445 | methods@~1.1.2: 446 | version "1.1.2" 447 | resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" 448 | integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= 449 | 450 | mime-db@~1.37.0: 451 | version "1.37.0" 452 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.37.0.tgz#0b6a0ce6fdbe9576e25f1f2d2fde8830dc0ad0d8" 453 | integrity sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg== 454 | 455 | mime-types@~2.1.18: 456 | version "2.1.21" 457 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.21.tgz#28995aa1ecb770742fe6ae7e58f9181c744b3f96" 458 | integrity sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg== 459 | dependencies: 460 | mime-db "~1.37.0" 461 | 462 | mime@1.4.1: 463 | version "1.4.1" 464 | resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" 465 | integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ== 466 | 467 | mongodb-core@3.1.9: 468 | version "3.1.9" 469 | resolved "https://registry.yarnpkg.com/mongodb-core/-/mongodb-core-3.1.9.tgz#c31ee407bf932b0149eaed775c17ee09974e4ca3" 470 | integrity sha512-MJpciDABXMchrZphh3vMcqu8hkNf/Mi+Gk6btOimVg1XMxLXh87j6FAvRm+KmwD1A9fpu3qRQYcbQe4egj23og== 471 | dependencies: 472 | bson "^1.1.0" 473 | require_optional "^1.0.1" 474 | safe-buffer "^5.1.2" 475 | optionalDependencies: 476 | saslprep "^1.0.0" 477 | 478 | mongodb@3.1.10: 479 | version "3.1.10" 480 | resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-3.1.10.tgz#45ad9b74ea376f4122d0881b75e5489b9e504ed7" 481 | integrity sha512-Uml42GeFxhTGQVml1XQ4cD0o/rp7J2ROy0fdYUcVitoE7vFqEhKH4TYVqRDpQr/bXtCJVxJdNQC1ntRxNREkPQ== 482 | dependencies: 483 | mongodb-core "3.1.9" 484 | safe-buffer "^5.1.2" 485 | 486 | mongoose-legacy-pluralize@1.0.2: 487 | version "1.0.2" 488 | resolved "https://registry.yarnpkg.com/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz#3ba9f91fa507b5186d399fb40854bff18fb563e4" 489 | integrity sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ== 490 | 491 | mongoose-unique-validator@^2.0.2: 492 | version "2.0.2" 493 | resolved "https://registry.yarnpkg.com/mongoose-unique-validator/-/mongoose-unique-validator-2.0.2.tgz#a980e68638157cd8fcea86d754eeb2cf67e6bb76" 494 | integrity sha512-gbKFiEzWQi8wZvZFeeEkx4nCV1qWaeRoQBNm+672+h54/0u/Y8rSdNubScn/1H2ScCPO55asDow+OXq67RQDmg== 495 | dependencies: 496 | lodash.foreach "^4.1.0" 497 | lodash.get "^4.0.2" 498 | 499 | mongoose@^5.4.1: 500 | version "5.4.1" 501 | resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-5.4.1.tgz#0e1535bb2653426c9ee8fffbf4fa0ba57bb196e7" 502 | integrity sha512-9lST8rek83apkG+gv4exI56kJ8/aJ7nZP+zAL1ezOhgfDqQM/S4U1DcsF1hL0cOTSmcip8BdT1xby9ItCFmbvA== 503 | dependencies: 504 | async "2.6.1" 505 | bson "~1.1.0" 506 | kareem "2.3.0" 507 | lodash.get "4.4.2" 508 | mongodb "3.1.10" 509 | mongodb-core "3.1.9" 510 | mongoose-legacy-pluralize "1.0.2" 511 | mpath "0.5.1" 512 | mquery "3.2.0" 513 | ms "2.0.0" 514 | regexp-clone "0.0.1" 515 | safe-buffer "5.1.2" 516 | sliced "1.0.1" 517 | 518 | mpath@0.5.1: 519 | version "0.5.1" 520 | resolved "https://registry.yarnpkg.com/mpath/-/mpath-0.5.1.tgz#17131501f1ff9e6e4fbc8ffa875aa7065b5775ab" 521 | integrity sha512-H8OVQ+QEz82sch4wbODFOz+3YQ61FYz/z3eJ5pIdbMEaUzDqA268Wd+Vt4Paw9TJfvDgVKaayC0gBzMIw2jhsg== 522 | 523 | mquery@3.2.0: 524 | version "3.2.0" 525 | resolved "https://registry.yarnpkg.com/mquery/-/mquery-3.2.0.tgz#e276472abd5109686a15eb2a8e0761db813c81cc" 526 | integrity sha512-qPJcdK/yqcbQiKoemAt62Y0BAc0fTEKo1IThodBD+O5meQRJT/2HSe5QpBNwaa4CjskoGrYWsEyjkqgiE0qjhg== 527 | dependencies: 528 | bluebird "3.5.1" 529 | debug "3.1.0" 530 | regexp-clone "0.0.1" 531 | safe-buffer "5.1.2" 532 | sliced "1.0.1" 533 | 534 | ms@2.0.0: 535 | version "2.0.0" 536 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 537 | integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= 538 | 539 | ms@^2.1.1: 540 | version "2.1.1" 541 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" 542 | integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== 543 | 544 | negotiator@0.6.1: 545 | version "0.6.1" 546 | resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" 547 | integrity sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk= 548 | 549 | nth-check@~1.0.1: 550 | version "1.0.2" 551 | resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" 552 | integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== 553 | dependencies: 554 | boolbase "~1.0.0" 555 | 556 | on-finished@~2.3.0: 557 | version "2.3.0" 558 | resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" 559 | integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= 560 | dependencies: 561 | ee-first "1.1.1" 562 | 563 | parse5@^3.0.1: 564 | version "3.0.3" 565 | resolved "https://registry.yarnpkg.com/parse5/-/parse5-3.0.3.tgz#042f792ffdd36851551cf4e9e066b3874ab45b5c" 566 | integrity sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA== 567 | dependencies: 568 | "@types/node" "*" 569 | 570 | parseurl@~1.3.2: 571 | version "1.3.2" 572 | resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" 573 | integrity sha1-/CidTtiZMRlGDBViUyYs3I3mW/M= 574 | 575 | path-to-regexp@0.1.7: 576 | version "0.1.7" 577 | resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" 578 | integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= 579 | 580 | proxy-addr@~2.0.4: 581 | version "2.0.4" 582 | resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.4.tgz#ecfc733bf22ff8c6f407fa275327b9ab67e48b93" 583 | integrity sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA== 584 | dependencies: 585 | forwarded "~0.1.2" 586 | ipaddr.js "1.8.0" 587 | 588 | qs@6.5.2: 589 | version "6.5.2" 590 | resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" 591 | integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== 592 | 593 | range-parser@~1.2.0: 594 | version "1.2.0" 595 | resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" 596 | integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4= 597 | 598 | raw-body@2.3.3: 599 | version "2.3.3" 600 | resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.3.tgz#1b324ece6b5706e153855bc1148c65bb7f6ea0c3" 601 | integrity sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw== 602 | dependencies: 603 | bytes "3.0.0" 604 | http-errors "1.6.3" 605 | iconv-lite "0.4.23" 606 | unpipe "1.0.0" 607 | 608 | readable-stream@^3.0.6: 609 | version "3.1.1" 610 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.1.1.tgz#ed6bbc6c5ba58b090039ff18ce670515795aeb06" 611 | integrity sha512-DkN66hPyqDhnIQ6Jcsvx9bFjhw214O4poMBcIMgPVpQvNy9a0e0Uhg5SqySyDKAmUlwt8LonTBz1ezOnM8pUdA== 612 | dependencies: 613 | inherits "^2.0.3" 614 | string_decoder "^1.1.1" 615 | util-deprecate "^1.0.1" 616 | 617 | regexp-clone@0.0.1: 618 | version "0.0.1" 619 | resolved "https://registry.yarnpkg.com/regexp-clone/-/regexp-clone-0.0.1.tgz#a7c2e09891fdbf38fbb10d376fb73003e68ac589" 620 | integrity sha1-p8LgmJH9vzj7sQ03b7cwA+aKxYk= 621 | 622 | require_optional@^1.0.1: 623 | version "1.0.1" 624 | resolved "https://registry.yarnpkg.com/require_optional/-/require_optional-1.0.1.tgz#4cf35a4247f64ca3df8c2ef208cc494b1ca8fc2e" 625 | integrity sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g== 626 | dependencies: 627 | resolve-from "^2.0.0" 628 | semver "^5.1.0" 629 | 630 | resolve-from@^2.0.0: 631 | version "2.0.0" 632 | resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" 633 | integrity sha1-lICrIOlP+h2egKgEx+oUdhGWa1c= 634 | 635 | safe-buffer@5.1.2, safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0: 636 | version "5.1.2" 637 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" 638 | integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== 639 | 640 | "safer-buffer@>= 2.1.2 < 3": 641 | version "2.1.2" 642 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" 643 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== 644 | 645 | saslprep@^1.0.0: 646 | version "1.0.2" 647 | resolved "https://registry.yarnpkg.com/saslprep/-/saslprep-1.0.2.tgz#da5ab936e6ea0bbae911ffec77534be370c9f52d" 648 | integrity sha512-4cDsYuAjXssUSjxHKRe4DTZC0agDwsCqcMqtJAQPzC74nJ7LfAJflAtC1Zed5hMzEQKj82d3tuzqdGNRsLJ4Gw== 649 | dependencies: 650 | sparse-bitfield "^3.0.3" 651 | 652 | semver@^5.1.0: 653 | version "5.6.0" 654 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" 655 | integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== 656 | 657 | send@0.16.2: 658 | version "0.16.2" 659 | resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" 660 | integrity sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw== 661 | dependencies: 662 | debug "2.6.9" 663 | depd "~1.1.2" 664 | destroy "~1.0.4" 665 | encodeurl "~1.0.2" 666 | escape-html "~1.0.3" 667 | etag "~1.8.1" 668 | fresh "0.5.2" 669 | http-errors "~1.6.2" 670 | mime "1.4.1" 671 | ms "2.0.0" 672 | on-finished "~2.3.0" 673 | range-parser "~1.2.0" 674 | statuses "~1.4.0" 675 | 676 | serve-static@1.13.2: 677 | version "1.13.2" 678 | resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1" 679 | integrity sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw== 680 | dependencies: 681 | encodeurl "~1.0.2" 682 | escape-html "~1.0.3" 683 | parseurl "~1.3.2" 684 | send "0.16.2" 685 | 686 | setprototypeof@1.1.0: 687 | version "1.1.0" 688 | resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" 689 | integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== 690 | 691 | sliced@1.0.1: 692 | version "1.0.1" 693 | resolved "https://registry.yarnpkg.com/sliced/-/sliced-1.0.1.tgz#0b3a662b5d04c3177b1926bea82b03f837a2ef41" 694 | integrity sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E= 695 | 696 | sparse-bitfield@^3.0.3: 697 | version "3.0.3" 698 | resolved "https://registry.yarnpkg.com/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz#ff4ae6e68656056ba4b3e792ab3334d38273ca11" 699 | integrity sha1-/0rm5oZWBWuks+eSqzM004JzyhE= 700 | dependencies: 701 | memory-pager "^1.0.2" 702 | 703 | "statuses@>= 1.4.0 < 2": 704 | version "1.5.0" 705 | resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" 706 | integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= 707 | 708 | statuses@~1.4.0: 709 | version "1.4.0" 710 | resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" 711 | integrity sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew== 712 | 713 | string_decoder@^1.1.1: 714 | version "1.2.0" 715 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d" 716 | integrity sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w== 717 | dependencies: 718 | safe-buffer "~5.1.0" 719 | 720 | type-is@~1.6.16: 721 | version "1.6.16" 722 | resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194" 723 | integrity sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q== 724 | dependencies: 725 | media-typer "0.3.0" 726 | mime-types "~2.1.18" 727 | 728 | unpipe@1.0.0, unpipe@~1.0.0: 729 | version "1.0.0" 730 | resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" 731 | integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= 732 | 733 | util-deprecate@^1.0.1: 734 | version "1.0.2" 735 | resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" 736 | integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= 737 | 738 | utils-merge@1.0.1: 739 | version "1.0.1" 740 | resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" 741 | integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= 742 | 743 | validator@^10.10.0: 744 | version "10.10.0" 745 | resolved "https://registry.yarnpkg.com/validator/-/validator-10.10.0.tgz#a69ac298149f063a44361cb52182edb52dab59a4" 746 | integrity sha512-DyZyLJlMXM3CGdVaVHE/EDzCagMRoPI3mmGdxxNQbqkGqh56+M3d1i0ZAWd69En8U21DHbPTn12aOdhO+hfm5w== 747 | 748 | vary@~1.1.2: 749 | version "1.1.2" 750 | resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" 751 | integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= 752 | --------------------------------------------------------------------------------