A paper-trading system for use in studying controls applied to finance.
A VirtualBox image of TDF can be downloaded and installed with a few clicks. See idealabs/byu.edu/Features/TDF.php for step-by-step instructions on how to do this.
Note that this installation has only been tested using Ubuntu 13.10.
Follow the instructions here. For Ubuntu (recommended):
sudo apt-get update
sudo apt-get install python-software-properties python g++ make
sudo add-apt-repository ppa:chris-lea/node.js
sudo apt-get update
sudo apt-get install nodejs
Install both grunt, the grunt client, and bower globally by:
sudo npm install -g grunt grunt-cli bower
Follow the instructions here. In brief:
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10
echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | sudo tee /etc/apt/sources.list.d/mongodb.list
sudo apt-get update
sudo apt-get install mongodb-10gen
Once MongoDB is installed, start it by:
sudo service mongodb start
You can stop MongoDB by:
sudo service mongodb stop
You can also restart MongoDB by:
sudo service mongodb restart
Note that occasionally a lock on MongoDB will prevent TDF from accessing its data. This will manifest as an error when running grunt indicating that a port (the number may vary depending on the installation and configuration of MongoDB) is unavailable. To fix this error:
sudo rm /var/lib/mongodb/mongod.lock
sudo service mongodb restart
Follow the directions here to enable npm to install packages locally. In brief:
sudo chown -fR myusername:myusername ~/.npm ~/tmp
Navigate to the tdf directory and execute the following commands:
npm install
Note, you should never need to do a sudo npm install
.
If you get a git error 128, you may need to switch the url protocol to https:// (instead of git://). To do this:
git config --global url."https://".insteadOf git://
TDF must make repetitive calls to Yahoo Finance in order to collect and store
temporal pricing information as well as the value of the agents' portfolios
over time. Such calls can be performed manually by opening the URL
<host>:<port>/maketick
. However, we recommend that this be performed
automatically on the host machine using a scheduled chronjob. Further, we
recommend that this be performed every hour on the hour while the markets are
open (any more frequent than this and TDF stops performing well, and even
at this tick rate, TDF slows down and becomes almost unusable with 30
agents after about a month).
To aid in creating this crontab entry, we have provided two scripts,
tickercron3000
and tickercron80
, the former of which assumes that TDF
is being run on port 3000 of the local machine and the later assumes that TDF
is being run on port 80 of the local machine. Add the crontab entry with
crontab tickercron3000
and verify that the entry has been added by viewing the crontab with
crontab -e
For testing, in the tdf directory, start the grunt server by:
grunt
If everything is installed properly, you will get a message stating that the server is running on port 3000. Navigate to localhost:3000 to access TDF.
If the TDF app is ready to deploy, we recommend running a pm2 server instead of a grunt server as pm2 will parallelize TDF across all available cores of the machine and will restart TDF automatically if it happens to crash for any reason. To start the pm2 server:
npm run pm2-start
Once running, the server usage can be seen with
npm run pm2-monit
The server can be stopped with
npm run pm2-stop
The server can also be manually restarted with
npm run pm2-restart
(note, the stop and the restart scripts can take some time to execute).
Finally, the pm2 instance can be destroyed with
npm run pm2-delete
Once you have installed TDF, you will need to begin by creating a league. To do this, you will need an admin account. For now, an admin account is created by registering an account with the username admin
(this will be changed in the future for greater security and flexibility of admins).
After loging in with the admin account, click on Leagues
in the top navigation bar, and then click the button to add a league. Enter a name of the league and then, if you wish, modify the rest of the league parameters.
Now that you have a league, you and other users can register agents to trade and compete within this league.
See idealabs/byu.edu/Features/TDF.php for more information.
To make a trade on the backend, you must first create an agent through the web client. To do this:
- Login or register with the site
- Click on the 'My Agents' link in the top navigation bar
- Above the desired league, click on the 'Create an Agent' button
Once you have created the agent, navigate to the agent's view if you are not there already (after creating an agent, the site automatically redirects to the agent view). To do this:
- Click on the 'My Agents' link in the top navigation bar
- Locate the agent in your list of agents, and click on the view button to the right of the agent's name
In the agent view, note the following:
- The agent's id
- The agent's api key (you will need to click on the show button to the right of the key to display it)
To trade in any language, create an HTTP post. The url will be <host>/agents/trade/<agent-id>
, where host
is the url pointing to the TDF server and <agent-id>
is the id noted from the agent view.
The data for the post will consist of key-value pairs where each key represents a ticker symbol in the list of ticker symbols allowed by the league (currently only and all symbols in the S&P500), and the value is the number of trades of that security to sell, where negative quantities signify a sell and positive signify a buy.
Further, the data must also pass the key apikey
with the value of the api key noted from the agent's view.
Each <symbol i>=<quantity i>
refers to a trade for the security represented by the Yahoo Finance ticker simbol <symbol i>
. Positive quantities <quantity i>
refer to a buy, where negative quantities refer to a sell.
If the trade is successfull, the server will respond with a JSON object representing the agent's info and current status. Otherwise, it will return a JSON object describing the error encountered.
The historical data for any symbol tracked by the system can be queried through the following url:
<host>/history/<symbol>
where <host>
is the location of TDF and <symbol>
is the ticker symbol for the desired security.
The response is a JSON object of the following form:
{
"current": {
"ask": <real-time ask price>,
"bid": <real-time bid price>,
"last": <real-time last price>
},
"ask": {
<JavaScript date of most recently scraped data>: <ask at date>,
...
<JavaScript date of first scraped data>: <ask at date>
},
"bid": {
<JavaScript date of most recently scraped data>: <bid at date>,
...
<JavaScript date of first scraped data>: <bid at date>
},
"last": {
<JavaScript date of most recently scraped data>: <last at date>,
...
<JavaScript date of first scraped data>: <last at date>
}
}
A user can query to receive the current composition of an agent's portfolio and the values of all securities in the portfolio through the following URL:
<host>/agents/<agent-id>/composition?apikey=<apikey>
where <host>
is the location of TDF, <agent-id>
is the agent's public id, and <apikey>
is the agent's private api key.
The response is a JSON object of the following form:
{
"uninvested_cash": <Total Uninvested Cash>,
"<Symbol 1>": {
"quantity": <Number of shares invested in <Symbol 1>>,
"price": <Price of one share of <Symbol 1>>,
"value": <Value of investment in <Symbol 1>, quantity * price>
},
...
"<Symbol n>": {
"quantity": <Number of shares invested in <Symbol n>>,
"price": <Price of one share of <Symbol n>>,
"value": <Value of investment in <Symbol n>, quantity * price>
},
"total_value": <Total value of portfolio = uninvested_cash + sum_{i = 1 to n} value(<symbol i>)>
}
Other queries that can be made are described in detail at idealabs/byu.edu/Features/TDF.php.