Skip to content

Commit 94f20a5

Browse files
authored
Add (Project) Stock-Prediction-Algorithms
1 parent aec2015 commit 94f20a5

File tree

6 files changed

+310
-0
lines changed

6 files changed

+310
-0
lines changed

stock-algorithm-js-sandbox/README.md

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Stock Algorithm JS Sandbox
2+
3+
To host the website, serve the files in the root project directory, like so:
4+
```
5+
# You can pick python, apache, or anything really
6+
python3.7 http.server 8080 # Use python 3.7 as this version fixes the socket issue with chrome
7+
```
8+
If you have any really cool algorithms, I encourage you to open an issue and post it there.
9+
10+
The website's CSS making your eyeballs bleed? Open a pull request and comment how lazy I am on styling the website properly while sharing your awesome CSS!
11+
12+
Have fun!<br>
+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
async function getData(stockSymbol, limit){
2+
if(!stockSymbol){
3+
alert('Please enter in a value');
4+
return;
5+
}
6+
7+
var flag = true;
8+
if(!limit){
9+
flag = false;
10+
}
11+
var rawData = await (await window.fetch('https://www.alphavantage.co/query?function=TIME_SERIES_DAILY_ADJUSTED&outputsize=full&symbol='+encodeURIComponent(stockSymbol)+'&apikey=VFKNX13I1KQF3WRZ')).json();
12+
13+
var errMsg = rawData['Error Message'];
14+
if(errMsg){
15+
if(errMsg.includes('Invalid API call')){
16+
alert('Stock symbol not found');
17+
}else if(errMsg.includes('if you would like to target a higher API call frequency')){
18+
alert('Oops, looks like you spammed too much. Wait a couple minutes before trying again');
19+
}else{
20+
alert('Weird error from alpha vantage:'+errMsg);
21+
}
22+
return;
23+
}
24+
25+
var labels = [];
26+
var prices = [];
27+
var count = 0;
28+
for(var label in rawData['Time Series (Daily)']){
29+
if(flag && count >= limit) break;
30+
labels.push(label);
31+
prices.push(parseFloat(rawData['Time Series (Daily)'][label]['4. close']));
32+
count++;
33+
}
34+
return [labels.reverse(), prices.reverse()];
35+
}

stock-algorithm-js-sandbox/index.html

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<html>
2+
<head>
3+
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
4+
<script src="https://cdn.jsdelivr.net/npm/[email protected]/src-min-noconflict/ace.js"></script>
5+
6+
<script src="showChart.js"></script>
7+
<script src="getStockData.js"></script>
8+
<script src="main.js"></script>
9+
<link rel='stylesheet' type='text/css' href='main.css'>
10+
<title>Stock Algorithm JS Sandbox</title>
11+
</head>
12+
<body style="margin: 0;">
13+
<div id="header-wrapper">
14+
<h2>Stock Algorithm JS Sandbox</h2>
15+
</div>
16+
<div id='result-wrapper'>
17+
<canvas id="chart"></canvas>
18+
</div>
19+
<div id='setting-wrapper'>
20+
<div id='stock-selection'>
21+
<input id='stock-symbol-input' type='text' placeholder='Stock symbol'><br>
22+
<input id='limit-input' type='text' placeholder='Data limit (leave blank for all)'>
23+
<button onclick='getDataClick(document.getElementById("stock-symbol-input").value, document.getElementById("limit-input").value)'>Get Data</button><br>
24+
</div>
25+
<div id='stats-wrapper'>
26+
<span class='info-before'>Amount of money earned:</span> <span class='info-after'></span><br>
27+
<span class='info-before'>Amount of buy decisions:</span> <span class='info-after'></span><br>
28+
<span class='info-before'>Amount of sell decisions:</span> <span class='info-after'></span><br>
29+
<span class='info-before'>Amount of cheating sells:</span> <span class='info-after'></span><br>
30+
<span class='info-before'>Amount of stock left:</span> <span class='info-after'></span><br><br>
31+
<button onclick='run()'>Run simulation</button><button onclick='if(window.confirm("Are you sure you want to clear everything?")){window.localStorage.removeItem("savedProgram");window.location.reload()}'>Clear saved program and reload</button>
32+
</div>
33+
<div id='main-code'>/*
34+
This is the space that you need to program in javascript, to create your own stock algorithm.
35+
There should be a "main" function, so that parameters can be passed in.
36+
Also, the main function should return either true for buy, false for sell, and undefined (no return) for no action.
37+
Like so:
38+
this.main = function(previousData, amountOfStock){
39+
// Code here
40+
// Something magical happens
41+
return true; // true for buy, false for sell, undefined for no action
42+
}
43+
The amount of previous data can also be set using:
44+
this.previousDataAmt = 10; // Default 10
45+
Note that previousData will always have a length of previousDataAmt, which means it will start at previousDataAmt from the beginning
46+
47+
FINAL NOTE: A cheater would be like this.main=function(){return false} and get huge profits. Well... not happening here.
48+
If the program tries to sell, but doesn't have any stock to sell, it will do nothing.
49+
50+
Good luck
51+
Simon Cheng
52+
*/
53+
this.previousDataAmt = 10;
54+
this.main = function(previousData, amountOfStock){
55+
56+
};</div>
57+
</div>
58+
<script>
59+
if(window.localStorage.getItem('savedProgram')){
60+
document.getElementById('main-code').innerHTML = window.localStorage.getItem('savedProgram');
61+
}
62+
window.editor = ace.edit("main-code");
63+
window.editor.setTheme("ace/theme/dawn");
64+
window.editor.session.setMode("ace/mode/javascript");
65+
window.editor.session.on('change', function(){
66+
window.localStorage.setItem('savedProgram', window.editor.session.getValue());
67+
});
68+
</script>
69+
</body>
70+
</html>

stock-algorithm-js-sandbox/main.css

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#header-wrapper{
2+
text-align: center;
3+
height: 40px;
4+
}
5+
#header-wrapper h2{
6+
margin: 0;
7+
}
8+
#header-wrapper h4{
9+
margin: 0;
10+
}
11+
12+
#result-wrapper{
13+
width: 50%;
14+
height: calc(100% - 50px);
15+
margin-top: 10px;
16+
17+
float: left;
18+
}
19+
#setting-wrapper{
20+
width: 50%;
21+
height: calc(100% - 50px);
22+
margin-top: 10px;
23+
24+
float: left;
25+
}
26+
27+
#stock-selection{
28+
height: 50px;
29+
width: 100%;
30+
}
31+
#stats-wrapper{
32+
height: 145px;
33+
width: 100%;
34+
}
35+
#main-code{
36+
height: calc(100% - 50px - 145px);
37+
width: 100%;
38+
}
39+
40+
.info-before{
41+
display: inline-block;
42+
width: 175px;
43+
}

stock-algorithm-js-sandbox/main.js

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
async function getDataClick(...args){
2+
var stockData = await getData(...args);
3+
if(stockData){
4+
window.labels = stockData[0];
5+
window.stockPrices = stockData[1];
6+
generateChart(document.getElementById('chart'), window.labels, window.stockPrices, [], []);
7+
}
8+
}
9+
function run(){
10+
if(!window.stockPrices){
11+
alert('That chart to the left is just for show. Now get some data!');
12+
return;
13+
}
14+
15+
var userProgram = window.editor.session.getValue();
16+
try{
17+
eval(userProgram);
18+
}catch(e){
19+
console.error(e);
20+
alert('An error occurred while running your script. Check the console for more details.\n'+e);
21+
return;
22+
}
23+
if(!this.previousDataAmt){
24+
this.previousDataAmt = 10;
25+
}
26+
if(this.previousDataAmt >= window.stockPrices.length){
27+
alert('previousDataAmt is greater or equal to the amount of stock prices. Adjust to a lower value');
28+
return;
29+
}
30+
31+
var wallet = 0;
32+
var buyDecisionCount = 0;
33+
var sellDecisionCount = 0;
34+
var numberOfCheatingSells = 0;
35+
var stocks = 0;
36+
37+
var buyPosition = [];
38+
var sellPosition = [];
39+
for(var count = this.previousDataAmt; count < window.stockPrices.length; count++){
40+
try{
41+
var result = this.main(window.stockPrices.slice(count-this.previousDataAmt, count), stocks);
42+
if(result === true){
43+
buyDecisionCount += 1;
44+
stocks += 1;
45+
wallet -= window.stockPrices[count];
46+
47+
buyPosition.push(window.labels[count]);
48+
}else if(result === false){
49+
if(stocks <= 0){
50+
numberOfCheatingSells += 1;
51+
}else{
52+
sellDecisionCount += 1;
53+
stocks -= 1;
54+
wallet += window.stockPrices[count];
55+
56+
sellPosition.push(window.labels[count]);
57+
}
58+
}else if(result === undefined){
59+
// Do nothing
60+
}else{
61+
alert('Your main function returned something other than a boolean or "undefined"!');
62+
return;
63+
}
64+
}catch(e){
65+
console.error(e);
66+
alert('An error occurred while running your script. Check the console for more details.\n'+e);
67+
return;
68+
}
69+
}
70+
71+
generateChart(document.getElementById('chart'), window.labels, window.stockPrices, buyPosition, sellPosition);
72+
73+
document.getElementsByClassName('info-after')[0].innerHTML = wallet.toFixed(2);
74+
document.getElementsByClassName('info-after')[1].innerHTML = buyDecisionCount;
75+
document.getElementsByClassName('info-after')[2].innerHTML = sellDecisionCount;
76+
document.getElementsByClassName('info-after')[3].innerHTML = numberOfCheatingSells;
77+
document.getElementsByClassName('info-after')[4].innerHTML = stocks;
78+
}
+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/**
2+
* Arguments:
3+
* canvas: element of canvas
4+
* labels: [January, feburary, ....] or [1,2,3,4]
5+
* stockData: [1,5,2,1,0,4,2,23]
6+
* buyDecision: The x positions of buying [January, feburary, 20, December]
7+
* sellDecision: Same thing above but for buying
8+
*
9+
* Note: stockData.length MUST equal labels.length
10+
*/
11+
function generateChart(canvas, labels, stockData, buyDecision, sellDecision){
12+
function gen(decisions){
13+
var data = [];
14+
for(var eachLabel of decisions){
15+
data.push({
16+
x: eachLabel,
17+
y: stockData[labels.indexOf(eachLabel)],
18+
r: 5
19+
});
20+
}
21+
return data;
22+
}
23+
if(window.chartInstance){
24+
window.chartInstance.destroy();
25+
}
26+
window.chartInstance = new Chart(canvas.getContext('2d'), {
27+
type: 'line',
28+
data: {
29+
labels,
30+
datasets: [{
31+
label: 'Stock data',
32+
borderColor: 'rgb(0,0,0)',
33+
data: stockData,
34+
lineTension: 0,
35+
fill: false,
36+
radius: 0,
37+
borderWidth: 1
38+
},{
39+
label: 'Buy decision',
40+
borderColor: 'rgb(255,0,0)',
41+
data: gen(buyDecision),
42+
fill: false,
43+
type: 'bubble',
44+
backgroundColor: 'rgb(255,0,0)',
45+
pointStyle: 'triangle',
46+
rotation: 0
47+
},{
48+
label: 'Sell decision',
49+
borderColor: 'rgb(0,0,255)',
50+
data: gen(sellDecision),
51+
fill: false,
52+
type: 'bubble',
53+
backgroundColor: 'rgb(0,0,255)',
54+
pointStyle: 'triangle',
55+
rotation: 180
56+
}]
57+
},
58+
options: {
59+
title: {
60+
display: true,
61+
text: 'Results'
62+
},
63+
maintainAspectRatio: false
64+
}
65+
});
66+
}
67+
window.onload = function(){
68+
var chartDom = document.getElementById('chart');
69+
70+
// Dummy data for show
71+
window.mainChart = generateChart(chartDom, [1,2,3,4,5], [20, 60, 50, 99, 100], [2,3], [5]);
72+
};

0 commit comments

Comments
 (0)