A stock trading simulator built for beginners. Learn to trade without the risk.
Watch the demo video Β»
Features
Β·
Explore Docs
Β·
Request Bugs
Table of Contents
Soict Stock Trading Platform is a full-stack web application that simulates a real-world stock trading environment. Designed for beginners and educational purposes, it allows users to practice trading stocks, manage portfolios, and learn about market dynamics in a safe, risk-free setting. Due to the limitations of the project scope, certain real-world trading rules and mechanisms have been simplified, see Stock Fundamental Theory section.
For security concerns, we have implemented some measures to mitigate common vulnerabilities and attacks. For more details, refer to the Security Checklist section.
The project is built with the following technologies:
Backend:
Frontend:
Deployment:
Security Testing:
For more detailed explanations and implementations of the technologies used in this project, please refer to our Tech Stack.
Note
Be patient! It may take a while (~2 minutes) to load all the demo gif images in this Features section.
β‘ Quick look β‘:
Our application offers some key features:
-
User Authentication: Register or log in using email/username and password or using your Google account. Two-factor authentication (2FA) via OTP sent to your email is required on login. Optionally, you can select "Remember this device" to skip OTP next time. Includes "Forgot password" feature with OTP-based password reset.
Testing accounts:
user1@stockmarket.com/user1with passwordTest@123(for normal account) andadmin@stockmarket.com/adminwith passwordTest@123(for admin account). -
View Stock Board: Browse a real-time stock list with live price updates. Click on any stock to view detailed info, including price history shown in candlestick and line charts.
-
Tutorial: Step-by-step guide to help new users navigate the app and understand basic stock trading concepts.
-
Trading: Place buy/sell orders with support for both market and limit order types. You will get a notification on the home page when your order is matched.
-
Portfolio: Track your portfolio including available balance, estimated total value, the stocks you own, view transaction history, and add funds to your account.
-
Admin Page (for admin accounts only): Start or end a trading session.
For a live demo, you can watch our Demo Video.
Note
Some features of the website require third-party services such as Google SSO, Recaptcha with Cloudflare Turnstile, QR code banking payments via Sepay, and remote access through Cloudflare Tunnel. These services may become unavailable after the project is made public, as we plan to delete the associated accounts or projects for security and resource reasons. However, we provide detailed instructions 1 and detailed instructions 2 so you can reconfigure these services using your own keys or tokens.
If you just want to quickly try out the app without diving into the code, we've got you covered with a docker-compose setup. Follow these steps:
- Download the
docker-compose.prod.ymlfile only (no need to clone the project) - Create a
.envfile in the same directory as the docker-compose production file, following the template inenv.example, replace the values with your own credentials. - Start Docker on your machine.
- Run the following command in the directory containing
docker-compose.prod.yml:
docker-compose -f docker-compose.prod.yml upThis will pull the latest images for the backend, frontend, and database from Dockerhub then build and run them in containers.
The web will be available at:
-
Frontend: http://localhost:5173
-
Backend API: http://localhost:3000
-
pgAdmin (UI management tool for PostgreSQL): http://localhost:5050
Note
Prerequisites: We assume that you have Node.js (version >= 22.14) and Yarn installed on your system.
If you're interested in exploring the code and running the project manually, follow these steps:
-
Clone the repo and navigate to the project directory
git clone https://github.com/chutrunganh/Stock-Trading-Platform.git cd Stock-Trading-Platform -
Set up environment variables
Create a
.envfile in the project root by copying the template from.env.example, then fill in the required values by your own credentials. -
Set up the database
You have two options:
-
Option 1: Install PostgreSQL application manually via their official website.
-
Option 2: Use our Docker setup to run only the database. In this case, you need to comment out our backend and frontend services inside the docker-compose file to run the database only.
In both case, please recheck variables in the
.envto make sure that:DB_HOSTislocalhost, notpostgresBE_URLishttp://localhost:3000, not a domain nameFE_URLishttp://localhost:5173, not a domain name
Then run
docker-compose upto start the database.For detailed instructions on database setup, including configuration variables and solutions to common issues, we highly recommend taking a quick look at our Database Setup Guide and our Database Schemas
-
-
Start the backend
cd app/backend yarn install # Install dependencies yarn start
-
Start the frontend
cd app/frontend yarn install # Install dependencies yarn dev
-
Open your browser and navigate to
http://localhost:5173to see the web in action.
Tip
When you start the backend, it will automatically connect to the database and seed some initial data. However, for stock prices, it only seeds data for one day, so the chart may not display fully as shown in the demo due to insufficient historical data. To populate the database with realistic stock prices, we provide a Python script that fetches real-world stock data and inserts it into the database. You can find the script in app/backend/src/utils/seedStockPrice. Please refer to this guide for instructions on how to run it.
If you want to package the whole application (not just the database as above mentioned) with your source code changes to Docker images, use the docker-compose.yml file. First, check again the .env file, pay attention to these variables:
| Variable | Description | Example Value |
|---|---|---|
DB_HOST |
Must be set to postgres, not localhost |
postgres |
BE_URL |
Backend URL. Use: - http://localhost:3000 if running locally - YOUR_DOMAIN_NAME if exposing via Cloudflare Tunnel |
http://localhost:3000 or https://soictstock.io.vn |
FE_URL |
Frontend URL. Use: - http://localhost:5173 if running locally - YOUR_DOMAIN_NAME if exposing via Cloudflare Tunnel |
http://localhost:5173 or https://soictstock.io.vn |
Note
Make sure FE_URL and BE_URL are set correspondingly, depending on whether you're running locally or using a public domain.
This will build the Docker images directly from the source code in the ./app/backend and ./app/frontend directories, which already contains the Dockerfile. This will run 4 services:
- Backend
- Frontend + Nginx as a proxy
- Postgres SQL
- Pgadmin
Access the webpage at: http://localhost:5173.
You can take an additional step to securely expose your Docker services to the internet using Cloudflare Tunnel (formerly Argo Tunnel). To do this, register a tunnel and link it to the domain name you specify in the BE_URL and FE_URL variables in your .env file. Then, follow the official instructions on the Cloudflare website to run the tunnel and make your services publicly accessible. The webpage now can be accessed via https://soictstock.io.vn. See instructions setup here.
π¦ Stock-Trading-Platform/
βββ π app/
β βββ π backend/
β β βββ π src/ # Source code for the backend
β β βββ π package.json # Backend dependencies
β β βββ π Dockerfile # Dockerfile for backend
β β
β βββ π frontend/ # Source code for the frontend
β βββ π src/ # Source code for the frontend
β βββ π package.json # Frontend dependencies
β βββ π vite.config.js # Vite configuration file
β βββ π nginx.conf # Nginx configuration file
β βββ π Dockerfile # Dockerfile for frontend
β
βββ π docs/
β βββ π design/ # Detailed system design documents
β βββ π reports/ # Project reports
β βββ π setupInstructions/ # Setup instructions for the project
β βββ π techStack/ # Technologies used, configuration guides
β βββ π stockFundamentalTheory/ # Financial terminology, order matching, etc.
β
βββ π .env # Environment variables (not committed to GitHub)
βββ π .env.example # Example environment variables file (template)
βββ π docker-compose.yml # Run the whole app with Docker
For more details about the project structure, please refer to Project Architecture
ββββββββββββββββββββββββββββββ
β π Public Internet β
ββββββββββββββ¬ββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββ
β π©οΈ Cloudflare Proxy Edge β
ββββββββββββββ¬βββββββββββββββββ
β (Tunnel)
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββ
β π₯οΈ Local Machine (Docker Host) β
β (All services isolated inside Docker network) β
β β
β ββββββββββββββββββββββββββββββββββββββββββββ β
β β π‘οΈ cloudflared (Cloudflare Tunnel) β β
β β - Forwards to frontend:5173 (Nginx) β β
β ββββββββββββββ¬ββββββββββββββββββββββββββββββ β
β β β
β β β
β ββββββββββ΄ββββββββββββ β
β β frontend β β
β β (Nginx 5173:80) β β
β ββββββββββ¬ββββββββββββ β
β β β
β β β
β ββββββββ΄ββββββββββββ ββββββββββββββββββ β
β β backend βββββ€ postgres β β
β β(Node 3000:3000) β β (DB 5432:5432)β β
β ββββββββββββββββββββ ββββββββ¬ββββββββββ β
β β β
β βββββββ΄ββββββββ β
β β pgAdmin β β
β β (UI 5050:80)β β
β βββββββββββββββ β
ββββββββββββββββββββββββββββββββββββββββββββββββββββ
Format: $HOST_PORT:$CONTAINER_PORT
| Criteria | Requirements | Solution |
|---|---|---|
| 1. Password Authentication | π’ Enforce password policy |
Verified at both frontend and backend this policy:
passwordUtils.js for implementations. This password policy is a simplified version from VNDIRECT Securities JSC. |
| π’ Secure password storage | Use bcrypt for salting + slow hashing when storing passwords. Refer to userAuthService.js for implementations.
|
|
| π’ Prevention of password guessing | Use CAPTCHA provided by Cloudflare Turnstile service to block spam/automated logins. Validate on both frontend and backend. Refer to turnstileService.js for implementations. |
|
| π’ Password recovery |
Send OTPs to the user's email with expiration. For demo, we use Ethereal email. OTPs are 8 characters (mixed lower, upper case and numbers), expiry in 1 minute (testing only), generated with otp-generator dependency. Refer to otpService.js, userAuthService.js, AuthContext.jsx for implementations.
|
|
| 2. Session Authentication & Management | π’ Secure mechanisms for using access tokens: prevention of tampering and guessing, expiration control |
Use JWT with short-lived Access Tokens (expiry in1 minute for testing) and longer-lived Refresh Tokens (expiry in 7 days).
Tokens include a timestamp in the payload before signing to ensure uniqueness on every login.
Return tokens to the client via cookies with the following security attributes:
jwtUtil.js, setCookieUtil.js, authenticationMiddleware.js, AuthContext.jsx for implementations.
|
| π’ CSRF defense |
|
|
| π’ Session hijacking defense | Using tokens with cookies as mentioned above | |
| 3. Authorization | π’ Implement suitable access control: MAC, DAC, RBAC |
Implemented Role-Based Access Control (RBAC) with permission matrix: user and admin.
roleBasedAccessControlMiddleware.js for implementations.
|
| 4. Input Validation & Output Sanitization | π’ Input validation and sanitization |
User input is validated and sanitized using middleware located in
userValidationMiddleware.js
(used for login, registration, and password reset forms),
orderMiddleware.js,
and
tradingSessionMiddleware.js
(used for enforcing order constraints).
Response data is filtered using responseSanitizationMiddleware.js
and
errorHandlerMiddleware.js.
We use the joi and xss libraries for input and output sanitization.
In addition, a Content Security Policy (CSP) is configured to restrict the types of resources the browser can load.
|
| π’ Protection against injection attacks |
|
|
| π‘ Prevention of path traversal |
Prevent IDOR (Insecure Direct Object Reference) by :
|
|
| π’ File upload restriction | No file upload functionality in current app version so no need to implement this | |
| 5. Sensitive Information Leakage | π‘ Minimization of sensitive information leakage about servers, software, and applications | Check out our nginx.conf file for more details on security headers and configurations to minimize information leakage. |
| π’ Minimization of sensitive information leakage in response | Disable X-Powered-By in HTTP response header through using helmet dependency. This header is set by default in Express and some other frameworks to reveals which framework the server is using, which can aid attackers during reconnaissance |
|
| π’ Mitigate Clickjacking | Set X-Frame-Options: DENY in HTTP response header through using helmet dependency to prevent website to be embedded into other sites using iframe tag |
|
| 6. Compliance with Standards | π’ HTTPS implementation | Use Cloudflare Tunnels to public web service and get free SSL |
| π‘ Mitigation of DoS attacks | Requests pass through Cloudflare proxy when using Cloudflare Tunnel. Configure rate-limiting, geography-based IP rule, block specified user agents on Cloudflare WAF (Web Application Firewall), see WAF_1 and WAF_2. However, we just enable and use prebuild rules template without any research, customization or testing these settings yet. | |
| π’ Secure storage and management of sensitive values |
Use an environment variables file named .env to store secret values and keys.
All parts of the source code that need these values must load them from this file instead of hardcoding them.
The .env file is not committed to GitHub.
Instead, we provide a .env.example file as a template to help you recreate your own .env file with your credentials.
|
|
| 7. Security Testing | π’ Code review with automated tools | Scan with Qodana from Jetbrains. All Critical, High level warnings have been fixed, still some Moderate warnings left. |
| π’ Penetration testing with tools | Using ZAP Proxy. No High level alerts, only alerts at Medium, Low and Informational level left. |
|
| 8. Bonus | π’ Multi-factor authentication |
After entering correct username/email and password, OTP is sent to user's email. OTP must be valid and unexpired. We also have "Remember device in ... time" implemented to skip OTP next time login. Devices are identified by using fingerprintJS dependency (free version). See in otp service (for otp implementation) and LoginForm.jsx (for device fingerprint identification).
|
| π΄ Advanced session hijacking prevention | Track user IPs, detect unfamiliar devices/browsers. | |
| π‘ Advanced HTTP flood prevention | Configure the Cloudflare WAF for the domain. | |
| π’ Single Sign-On (SSO) | Implemented Google OAuth 2.0 using passport dependency, see in passportConfig.js and userAuthService.js.
|
Status Explanation:
-
π’ Done: Mitigation measures have been implemented to the best of our knowledge. (Note: This does not guarantee complete immunity from the attack.)
-
π‘ Partially Done / Not Applicable: The measures are either just proposed ideas, partially implemented, and have not been fully tested or validated yet.
-
π΄ Not Implemented: No mitigation has been applied yet.
All warnings at Critical, High level have been fixed. There are still some Medium level warnings left we cannot fix yet due to time constraints.
No alerts at High level, only alerts at Medium, Low and Informational level left.
Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.
If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!
- Fork the Project
- Create your Feature Branch (
git checkout -b feature/AmazingFeature) - Commit your Changes (
git commit -m 'Add some AmazingFeature') - Push to the Branch (
git push origin feature/AmazingFeature) - Open a Pull Request
For the success of this project, I want a special thanks to:
-
Project supervisor: MSc. BΓΉi Trα»ng TΓΉng, Dr. Δα» BΓ‘ LΓ’m
-
Team members:
Name Student ID Chu Trung Anh (team leader) 20225564 BΓΉi Duy Anh 20225563 PhαΊ‘m MαΊ‘nh TiαΊΏn 20225555
Distributed under the Apache-2.0 License License. See LICENSE for more information.
This project is maintained by: Chu Trung Anh - Email.
Feel free to contact me if you have any questions or suggestions.

















