var color_list = ['#c23531','#2f4554', '#61a0a8', '#d48265', '#91c7ae','#749f83', '#ca8622', '#bda29a','#6e7074', '#546570', '#c4ccd3'];
var colors = ['#5793f3', '#d14a61', '#675bba','#b62f46'];
var close = GOOGLE['data'].map(function(el, idx) {
return el[1];
})
var stocks = GOOGLE['data'].map(function(el, idx) {
return [el[0],el[1],el[3],el[2]];
})
var stock_date = GOOGLE['date'];
var volume = GOOGLE['volume'];
var csv;
var indeces = {};
var dataMA5, dataMA10, dataMA20, dataMA30;
var total_investment, total_gain, stock_changes, stock_changes_percent
function smoothing_line(scalars,weight){
last = scalars[0]
smoothed = []
for(var i = 0; i < scalars.length;i++){
smoothed_val = last * weight + (1 - weight) * scalars[i]
smoothed.push(smoothed_val)
last = smoothed_val
}
return smoothed
}
function generate_investment(strings,values){
colors = "";
for(var i = 0; i < strings.length;i++){
if(values[i]>=0) colors += "
";
else colors += "";
}
$('#color-investment').html(colors);
}
function buildConfig() {
return {
delimiter: $('#delimiter').val(),
header: $('#header').prop('checked'),
dynamicTyping: $('#dynamicTyping').prop('checked'),
skipEmptyLines: $('#skipEmptyLines').prop('checked'),
preview: parseInt($('#preview').val() || 0),
step: $('#stream').prop('checked') ? stepFn : undefined,
encoding: $('#encoding').val(),
worker: $('#worker').prop('checked'),
comments: $('#comments').val(),
complete: completeFn,
error: errorFn
}
}
function errorFn(err, file) {
Materialize.toast("ERROR: " + err + file,3000)
}
function completeFn(results) {
if (results && results.errors) {
if (results.errors) {
errorCount = results.errors.length;
firstError = results.errors[0]
}
if (results.data && results.data.length > 0)
rowCount = results.data.length
}
csv = results['data'];
for(var i = 0;i1){
Materialize.toast('input dropout must bigger than 0 and less than 1', 4000)
return
}
if(parseFloat($('#smooth').val())<0 || parseFloat($('#smooth').val())>1){
Materialize.toast('smoothing weights must bigger than 0 and less than 1', 4000)
return
}
if(parseFloat($('#outputdropoutrate').val())<0 || parseFloat($('#outputdropoutrate').val())>1){
Materialize.toast('output dropout must bigger than 0 and less than 1', 4000)
return
}
setTimeout(function(){
minmax_scaled = minmax_1d(close);
timestamp = parseInt($('#timestamp').val())
epoch = parseInt($('#epoch').val())
future = parseInt($('#future').val())
X_scaled = minmax_scaled.scaled.slice([0],[Math.floor(minmax_scaled.scaled.shape[0]/timestamp)*timestamp+1])
cells = [tf.layers.lstmCell({units: parseInt($('#sizelayer').val())})];
rnn = tf.layers.rnn({cell: cells, returnSequences: true,returnState:true});
dense_layer = tf.layers.dense({units: 1, activation: 'linear'});
function f(x,states){
x = dropout_nn(x,parseFloat($('#inputdropoutrate').val()))
forward = rnn.apply(x,{initialState:states});
last_sequences = dropout_nn(forward[0].reshape([x.shape[1],parseInt($('#sizelayer').val())]),parseFloat($('#outputdropoutrate').val()))
return {'forward':dense_layer.apply(last_sequences),'states_1':forward[1],'states_2':forward[2]}
}
cost = (label, pred) => tf.square(tf.sub(label,pred)).mean();
optimizer = tf.train.adam(parseFloat($('#learningrate').val()));
batch_states = [tf.zeros([1,parseInt($('#sizelayer').val())]),tf.zeros([1,parseInt($('#sizelayer').val())])];
arr_loss = [], arr_layer = []
function async_training_loop(callback) {
(function loop(i) {
var total_loss = 0
for(var k = 0; k < Math.floor(X_scaled.shape[0]/timestamp)*timestamp; k+=timestamp){
batch_x = X_scaled.slice([k],[timestamp]).reshape([1,-1,1])
batch_y = X_scaled.slice([k+1],[timestamp]).reshape([-1,1])
feed = f(batch_x,batch_states)
optimizer.minimize(() => cost(batch_y,f(batch_x,batch_states)['forward']));
total_loss += parseFloat(cost(batch_y,f(batch_x,batch_states)['forward']).toString().slice(7));
batch_states = [feed.states_1,feed.states_2]
}
total_loss /= Math.floor(X_scaled.shape[0]/timestamp);
arr_loss.push(total_loss)
output_predict = nj.zeros([X_scaled.shape[0]+future, 1])
output_predict.slice([0,1],null).assign(tf_str_tolist(X_scaled.slice(0,1))[0],false)
upper_b = Math.floor(X_scaled.shape[0]/timestamp)*timestamp
distance_upper_b = X_scaled.shape[0] - upper_b
batch_states = [tf.zeros([1,parseInt($('#sizelayer').val())]),tf.zeros([1,parseInt($('#sizelayer').val())])];
for(var k = 0; k < (Math.floor(X_scaled.shape[0]/timestamp)*timestamp); k+=timestamp){
batch_x = X_scaled.slice([k],[timestamp]).reshape([1,-1,1])
feed = f(batch_x,batch_states)
state_forward = tf_nj_list(feed.forward)
output_predict.slice([k+1,k+1+timestamp],null).assign(state_forward,false)
batch_states = [feed.states_1,feed.states_2]
}
batch_x = X_scaled.slice([upper_b],[distance_upper_b]).reshape([1,-1,1])
feed = f(batch_x,batch_states)
state_forward = tf_nj_list(feed.forward)
output_predict.slice([upper_b+1,X_scaled.shape[0]+1],null).assign(state_forward,false)
pointer = X_scaled.shape[0]+1
tensor_output_predict = output_predict.reshape([-1]).tolist()
batch_states = [feed.states_1,feed.states_2]
for(var k = 0; k < future-1; k+=1){
batch_x = tf.tensor(tensor_output_predict.slice(pointer-timestamp,pointer)).reshape([1,-1,1])
feed = f(batch_x,batch_states)
state_forward = tf_nj_list(feed.forward.transpose())
tensor_output_predict[pointer] = state_forward[0][4]
pointer += 1
batch_states = [feed.states_1,feed.states_2]
}
$('#log').append('Epoch: '+(i+1)+', avg loss: '+total_loss+'
');
predicted_val = tf_nj_list_flatten(reverse_minmax_1d(tf.tensor(tensor_output_predict),minmax_scaled['min'],minmax_scaled['max']))
predicted_val = smoothing_line(predicted_val,parseFloat($('#smooth').val()))
$('#div_output').attr('style','height:450px;');
new_date = stock_date.slice()
for(var k = 0; k < future; k+=1){
somedate = new Date(new_date[new_date.length-1])
somedate.setDate(somedate.getDate() + 1)
dd = somedate.getDate()
mm = somedate.getMonth() + 1
y = somedate.getFullYear()
new_date.push(y.toString()+'-'+mm.toString()+'-'+dd.toString())
}
option = {
animation: false,
color: color_list,
title: {
left: 'center'
},
legend: {
top: 30,
data: ['STOCK', 'MA5', 'MA10', 'MA20', 'MA30','predicted close']
},
tooltip: {
trigger: 'axis',
position: function (pt) {
return [pt[0], '10%'];
}
},
axisPointer: {
link: [{
xAxisIndex: [0, 1]
}]
},
dataZoom: [{
type: 'slider',
xAxisIndex: [0, 1],
realtime: false,
start: 0,
end: 100,
top: 65,
height: 20,
handleIcon: 'M10.7,11.9H9.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4h1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7V23h6.6V24.4z M13.3,19.6H6.7v-1.4h6.6V19.6z',
handleSize: '120%'
}, {
type: 'inside',
xAxisIndex: [0, 1],
start: 40,
end: 70,
top: 30,
height: 20
}],
xAxis: [{
type: 'category',
data: new_date,
boundaryGap : false,
axisLine: { lineStyle: { color: '#777' } },
axisLabel: {
formatter: function (value) {
return echarts.format.formatTime('MM-dd', value);
}
},
min: 'dataMin',
max: 'dataMax',
axisPointer: {
show: true
}
}, {
type: 'category',
gridIndex: 1,
data: stock_date,
scale: true,
boundaryGap : false,
splitLine: {show: false},
axisLabel: {show: false},
axisTick: {show: false},
axisLine: { lineStyle: { color: '#777' } },
splitNumber: 20,
min: 'dataMin',
max: 'dataMax',
axisPointer: {
type: 'shadow',
label: {show: false},
triggerTooltip: true,
handle: {
show: true,
margin: 30,
color: '#B80C00'
}
}
}],
yAxis: [{
scale: true,
splitNumber: 2,
axisLine: { lineStyle: { color: '#777' } },
splitLine: { show: true },
axisTick: { show: false },
axisLabel: {
inside: true,
formatter: '{value}\n'
}
}, {
scale: true,
gridIndex: 1,
splitNumber: 2,
axisLabel: {show: false},
axisLine: {show: false},
axisTick: {show: false},
splitLine: {show: false}
}],
grid: [{
left: 20,
right: 20,
top: 110,
}, {
left: 20,
right: 20,
top: 400
}],
graphic: [{
type: 'group',
left: 'center',
top: 70,
width: 300,
bounding: 'raw',
children: [{
id: 'MA5',
type: 'text',
style: {fill: color_list[1]},
left: 0
}, {
id: 'MA10',
type: 'text',
style: {fill: color_list[2]},
left: 'center'
}, {
id: 'MA20',
type: 'text',
style: {fill: color_list[3]},
right: 0
}]
}],
series: [{
name: 'Volume',
type: 'bar',
xAxisIndex: 1,
yAxisIndex: 1,
itemStyle: {
normal: {
color: '#7fbe9e'
},
emphasis: {
color: '#140'
}
},
data: volume
}, {
type: 'candlestick',
name: 'STOCK',
data: stocks,
itemStyle: {
normal: {
color: '#ef232a',
color0: '#14b143',
borderColor: '#ef232a',
borderColor0: '#14b143'
},
emphasis: {
color: 'black',
color0: '#444',
borderColor: 'black',
borderColor0: '#444'
}
}
}, {
name: 'MA5',
type: 'line',
data: dataMA5,
smooth: true,
showSymbol: false,
lineStyle: {
normal: {
width: 1
}
}
}, {
name: 'MA10',
type: 'line',
data: dataMA10,
smooth: true,
showSymbol: false,
lineStyle: {
normal: {
width: 1
}
}
}, {
name: 'MA20',
type: 'line',
data: dataMA20,
smooth: true,
showSymbol: false,
lineStyle: {
normal: {
width: 1
}
}
},
{
name: 'MA30',
type: 'line',
data: dataMA30,
smooth: true,
showSymbol: false,
lineStyle: {
normal: {
width: 1
}
}
},
{
name: 'predicted close',
type: 'line',
data: predicted_val,
smooth: false,
showSymbol: false,
lineStyle: {
normal: {
width: 2
}
}
}]
};
var chart_stock = echarts.init(document.getElementById('div_output'));
chart_stock.setOption(option,true);
calculate_distribution(close,predicted_val)
option = {
title:{
text:'loss graph'
},
xAxis: {
type: 'category',
data: arange(0,arr_loss.length,1)
},
yAxis: {
type: 'value'
},
grid:{
bottom:'10%'
},
series: [{
data: arr_loss,
type: 'line'
}]
};
var chart_line = echarts.init(document.getElementById('div_loss'));
chart_line.setOption(option,true);
if (i < (epoch-1)) {
setTimeout(function() {loop(++i)}, 2000);
} else {
callback();
}
}(0));
}
async_training_loop(function() {
$('#log').append('Done training!');
my_investment = simple_investor(close,predicted_val,parseInt($('#history').val()),
parseFloat($('#initialmoney').val()),parseInt($('#maxbuy').val()),parseInt($('#maxsell').val()),new_date)
$('#table-body').html('');
for(var i = 0; i < my_investment['output'].length; i++) $('#table-body').append(my_investment['output'][i]);
$('#log-invest').append("