A stock market site simulator for collecting data on stocks carried out by the trader.
This simulation takes stock market data for a given period and presents it in an interface that evolves with time and the user's actions.
The interface allows you to make buy or sell requests on a company's shares, view the company's share price and earnings per year via graphs, know your stock portfolio and consult the news. It's currently available in English and French, and we'd be delighted to extend it to more languages (see the contributing section).
The user's actions are recorded throughout the simulation in a data file in .csv format, enabling you to study the trader's behavior during the simulation.
- Requirements
- Installing
- Usage
- Handling the application
- The Setup toolbox
- Structure of data
- Why was this project created?
- Contributing
- Python == 3.10 (Has not been tested for more recent versions)
- dash >= 2.10.2 : Low-code framework for rapidly building data apps in Python.
- Pandas >= 2.0.2 : Fast, powerful, flexible and easy to use open source data analysis and manipulation tool
- yahooquery >= 2.3.1 : Python wrapper for an unofficial Yahoo Finance API
The complete list is in requirements.txt
Download the latest version of the repository and install the package locally with pip:
# Clone the repository or download the latest version on the corresponding page
cd trading_simulator # Move to project root
pip install setuptools . # Don't forget the dot at the end to install tradesim from local files
If you need the Setup
toolkit, also install the additional dependencies:
pip install setuptools .[extra]
Simply use the command line tool.
tradesim <data_directory>
For more information on the command line :
tradesim -h
If you want to integrate it into your program, here's a simple example:
# main.py
from tradesim import app
from tradesim.Setup import download_market_data
download_market_data() # Prepare the minimum necessary for interface operation
# [Your program...]
app.set_layout() # Import the layout before starting the server
app.run_server() # Server startup blocks the next instruction until the user presses ctrl-c in the terminal.
For a more realistic example, have a look at the main.py
file in this repository.
For more complex use, with other instructions during server operation, it's best to put your program in a different thread. Like this:
# main.py
from threading import Thread
from tradesim import app
download_market_data() # Prepare the minimum necessary for interface operation
# [A few instructions before getting started...]
th = Thread(target=your_program)
th.start()
app.set_layout() # Import the layout
app.run_server() # Starts the server and blocks the following instructions.
The application can be fully manipulated using the app
object available from tradesim
.
The default values are available from app.defaults
or its abbreviated version app.d
. It is strongly recommended not to modify them after calling app.set_layout()
and/or app.run_server()
.
Here is a description of the default values used:
# Period of time used to update data on the dashboard
app.d.update_time = 60*1000 # in milliseconds
# Maximum number of requests the user can make on the dashboard
app.d.max_requests = 10
# Initial money the user has
app.d.initial_money = 100000
# Path to the data folder
app.d.data_path = "Data"
# Stocks used in the interface
# They are also used to download data with the download_market_data setup tool
# The key is the ticker and the value is the name of the company
# So the data provided in the Data folder must have the same name as the symbol
app.d.companies = {
"MC.PA" : "LVMH MOËT HENNESSY LOUIS VUITTON SE (MC)",
"OR.PA" : "L'ORÉAL (OR)",
"RMS.PA" : "HERMÈS INTERNATIONAL (RMS)",
"TTE.PA" : "TOTALENERGIES SE (TTE)",
"SAN.PA" : "SANOFI (SAN)",
"AIR.PA" : "AIRBUS SE (AIR)",
"SU.PA" : "SCHNEIDER ELECTRIC SE (SU)",
"AI.PA" : "AIR LIQUIDE (AI)",
"EL.PA" : "ESSILORLUXOTTICA (EL)",
"BNP.PA" : "BNP PARIBAS (BNP)",
"KER.PA" : "KERING (KER)",
"DG.PA" : "VINCI (DG)",
"CS.PA" : "AXA (CS)",
"SAF.PA" : "SAFRAN (SAF)",
"RI.PA" : "PERNOD RICARD (RI)",
"DSY.PA" : "DASSAULT SYSTÈMES SE (DSY)",
"STLAM.MI" : "STELLANTIS N.V. (STLAM)",
"BN.PA" : "DANONE (BN)",
"STMPA.PA" : "STMICROELECTRONICS N.V. (STMPA)",
"ACA.PA": "CRÉDIT AGRICOLE S.A. (ACA)"
}
# Indexes used in the interface
# Same use as the companies variable
app.d.indexes = {
"^GSPC" : "S&P 500",
"^DJI" : "Dow Jones Industrial Average",
"^FCHI" : "CAC 40",
"^SPGSGC" : "S&P GSCI Gold Index",
}
The app
object also provides variables for manipulating the interface and/or finding out the state of an element while the interface is running.
These variables and their default values are described below:
# Enables or disables the start button on the home page.
# Takes a Boolean as input
app.home_start_button_disabled = false
# Describe the state of the application,
# i.e. whether the dashboard is displayed or not.
# This variable is set when the user arrives on a page.
# It is therefore undefined until this happens.
app.dashboardIsRunning
The app
object we provide is actually a Dash
object, taken from the dash
library, to which we have added our own functionalities, and therefore contains all the features of this object. Please refer to the corresponding documentation for more information on all the features of this object.
The tradesim.Setup
toolbox provides additional functions for creating an interface environment.
Here's a list:
def download_market_data():
""" Download daily stock market data for companies and indexes
defined respectively by `app.d.companies` and `app.d.indexes`
over the last two years, then save them in the folder defined
by `app.d.data_path`.
"""
pass
def analyse_news_data(data_path='Data'):
""" Opens a jupyter notebook at the location
defined by the data_path argument
to analyze the data it contains in the form of graphs.
"""
pass
For legal reasons, we do not provide a way to generate the news.csv file. It is up to you to obtain this file and place it in the folder defined by app.d.data_path
. It must contain the columns title;content;ticker;date
with the separator ";".
All the data used and generated is stored in a specific folder defined by the app.d.data_path
variable. This data has a constant structure, as explained below.
Once launched, the interface generates an interface-logs.csv
file in the same folder as the other data (by default: Data
), containing all the activity on the dashboard page. This file is structured so that there is only one item of data per column, with :
- the
host-timestamp
column gives the timestamp of the host machine, which allows this data to be synchronised with other data. - the
market-timestamp
column gives the timestamp of the data displayed on the interface. - the
<TICKER>-shares
columns contain the shares owned by the user. - the
<TICKER>-total
columns contain the value of all the shares owned at a given time. - the
cashflow
column corresponds to the money that the user can use. - the
selected-company
column indicates the ticker of the share displayed on the charts at a given time. - the
request <N>
columns contain the Nth request in the list of requests waiting to be completed. - the
nbr-news-displayed
andlast-news
columns respectively designate the number of news items displayed in the news table and the most recent news item displayed. - the
news-mode
andselected-graph
columns respectively designate what is displayed in the news part and the graph part. - the
selected-news
column is empty whennews-mode
is equal tonews-table
and gives the title of the news displayed whennews-mode
is equal tonews-description
.
To display news in the news table, the interface needs a news.csv
file containing at least these three columns separated by a semicolon:
title
orarticle
which contains the title of the article to be displayed, and which is used in the news table when displaying the list or at the top when displaying the article description.content
contains the article content, which will be displayed when the user clicks on the article title.date
which contains the date and time (optional) of the news item. The date must be formalized with the day first, i.e. {day}/{month}/{year}.
If you'd like to use your own market data instead of that generated by the download_market_data
setup tool, or if you'd like to understand the structure of the market_data.csv
file, this file has two header lines, the first of which contains the ticker and the second the data type, for each of the companies and indexes you wish to display. This file uses a date column as index and a comma separator.
The data types required are Open
, High
, Low
, Close
, long_MA
and short_MA
.
Here's an example to help you understand:
symbol,MC.PA,MC.PA,MC.PA,MC.PA,MC.PA,MC.PA,^SPGSGC,^SPGSGC,^SPGSGC,^SPGSGC,^SPGSGC,^SPGSGC,^SPGSGC
,Open,High,Low,Close,long_MA,short_MA,Open,High,Low,Close,long_MA,short_MA [...]
date,,,,,,,,,,,,
[...]
If this still isn't clear to you. Use the download_market_data
setup tool to generate a complete file. I hope this helps.
If you wish to use your own revenue data instead of that generated by the download_market_data
setup tool, or if you want to understand the structure of the revenue.csv
file, this file contains a line for:
asOfDate
which contains the data date- the
symbol
contains the company identifier or index and must be identical to that supplied by theapp.d.companies
andapp.d.indexes
variables respectively. NetIncome
andTotal revenue
each contain the value associated with it for each ticker and date. Here's an example to help you understand:
symbol,ACA.PA,ACA.PA,ACA.PA,ACA.PA [...]
asOfDate,2019-12-31 00:00:00,2020-12-31 00:00:00,2021-12-31 00:00:00,2022-12-31 00:00:00 [...]
NetIncome,4844000000.0,2692000000.0,5844000000.0,5437000000.0 [...]
TotalRevenue,19123000000.0,18061000000.0,21397000000.0,21955000000.0 [...]
If this still isn't clear to you. Use the download_market_data
setup tool to generate a complete file. I hope this helps.
In the financial laboratories of the University of Mons, a study has been launched to analyse the reactions of traders to the stock markets. To better understand which factors are most important in their choices, what is the "human" part of this equation, and many other questions. To improve their results, the researchers needed to create a controlled, automated data-gathering environment. tradesim
is an independent part of this environment, to which several sensors have been added. To find out more, have a look at the corresponding repository here.
Feel free to create an issue/PR if you want to see anything else implemented.
tradesim is distributed under the Apache License 2.0. See the LICENSE file in the release for details.