Financial data and chart
This commit is contained in:
parent
7c66539bff
commit
ac32919034
1
.gitignore
vendored
1
.gitignore
vendored
@ -33,3 +33,4 @@ lower-1line/lower-1line
|
||||
upper-words/upper-words
|
||||
longest-word/longest-word
|
||||
statecsv/statecsv
|
||||
go-financial/go-financial
|
||||
|
22
GOOG.csv
Normal file
22
GOOG.csv
Normal file
@ -0,0 +1,22 @@
|
||||
Date,Open,High,Low,Close,Adj Close,Volume
|
||||
2017-06-08,982.349976,984.570007,977.200012,983.409973,983.409973,1481900
|
||||
2017-06-09,984.500000,984.500000,935.630005,949.830017,949.830017,3309400
|
||||
2017-06-12,939.559998,949.354980,915.232971,942.900024,942.900024,3763500
|
||||
2017-06-13,951.909973,959.979980,944.090027,953.400024,953.400024,2013300
|
||||
2017-06-14,959.919983,961.150024,942.250000,950.760010,950.760010,1489700
|
||||
2017-06-15,933.969971,943.338989,924.440002,942.309998,942.309998,2133100
|
||||
2017-06-16,940.000000,942.039978,931.594971,939.780029,939.780029,3094700
|
||||
2017-06-19,949.960022,959.989990,949.049988,957.369995,957.369995,1533300
|
||||
2017-06-20,957.520020,961.619995,950.010010,950.630005,950.630005,1126000
|
||||
2017-06-21,953.640015,960.099976,950.760010,959.450012,959.450012,1202200
|
||||
2017-06-22,958.700012,960.719971,954.549988,957.090027,957.090027,941400
|
||||
2017-06-23,956.830017,966.000000,954.200012,965.590027,965.590027,1527900
|
||||
2017-06-26,969.900024,973.309998,950.789978,952.270020,952.270020,1598400
|
||||
2017-06-27,942.460022,948.289978,926.849976,927.330017,927.330017,2579900
|
||||
2017-06-28,929.000000,942.750000,916.000000,940.489990,940.489990,2721400
|
||||
2017-06-29,929.919983,931.260010,910.619995,917.789978,917.789978,3299200
|
||||
2017-06-30,926.049988,926.049988,908.309998,908.729980,908.729980,2090200
|
||||
2017-07-03,912.179993,913.940002,894.789978,898.700012,898.700012,1709800
|
||||
2017-07-05,901.760010,914.510010,898.500000,911.710022,911.710022,1813900
|
||||
2017-07-06,904.119995,914.943970,899.700012,906.690002,906.690002,1415200
|
||||
2017-07-07,908.849976,921.539978,908.849976,918.590027,918.590027,1637785
|
|
222
go-financial/main.go
Normal file
222
go-financial/main.go
Normal file
@ -0,0 +1,222 @@
|
||||
package main
|
||||
|
||||
import "encoding/csv"
|
||||
import "fmt"
|
||||
import "io"
|
||||
import "log"
|
||||
import "os"
|
||||
import "strconv"
|
||||
|
||||
var COLUMNS []string
|
||||
|
||||
type FinancialData struct {
|
||||
Date string
|
||||
Open, High, Low, Close, Adj_Close, Volume float64
|
||||
}
|
||||
|
||||
func printHTML(data []FinancialData, out io.Writer) {
|
||||
io.WriteString(out, `<!DOCTYPE html>
|
||||
<html>
|
||||
<head><title>Financial</title></head>
|
||||
<body>
|
||||
<table border="1">
|
||||
<tr>
|
||||
`)
|
||||
for _, col := range COLUMNS {
|
||||
io.WriteString(out, " <th>")
|
||||
io.WriteString(out, col)
|
||||
io.WriteString(out, "</th>\n")
|
||||
}
|
||||
io.WriteString(out, " </tr>\n")
|
||||
|
||||
// data
|
||||
for _, row := range data {
|
||||
row.printHTMLRow(out)
|
||||
}
|
||||
|
||||
io.WriteString(out, ` </table>
|
||||
<div id="container"></div>
|
||||
<style>
|
||||
#container {
|
||||
min-width: 310px;
|
||||
max-width: 800px;
|
||||
height: 400px;
|
||||
margin: 0 auto
|
||||
}
|
||||
</style>
|
||||
<script
|
||||
src="https://code.jquery.com/jquery-3.2.1.min.js"
|
||||
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
|
||||
crossorigin="anonymous"></script>
|
||||
<script src="https://code.highcharts.com/highcharts.src.js"></script>
|
||||
<script>
|
||||
Highcharts.chart('container', {
|
||||
title: {
|
||||
text: 'Financial data'
|
||||
},
|
||||
|
||||
subtitle: {
|
||||
text: 'Source: yahoo.com'
|
||||
},
|
||||
|
||||
yAxis: {
|
||||
title: {
|
||||
text: 'Value'
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
layout: 'vertical',
|
||||
align: 'right',
|
||||
verticalAlign: 'middle'
|
||||
},
|
||||
|
||||
series: [{
|
||||
name: 'Open',
|
||||
data: [`+getDataOpen(data)+`]
|
||||
}, {
|
||||
name: 'Close',
|
||||
data: [`+getDataClose(data)+`]
|
||||
}]
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>`)
|
||||
}
|
||||
|
||||
func getDataOpen(data []FinancialData) string {
|
||||
str := ""
|
||||
for i, v := range data {
|
||||
str += fmt.Sprintf("%.4f", v.Open)
|
||||
if i < len(data)-1 {
|
||||
str += ","
|
||||
}
|
||||
}
|
||||
return str
|
||||
}
|
||||
func getDataClose(data []FinancialData) string {
|
||||
str := ""
|
||||
for i, v := range data {
|
||||
str += fmt.Sprintf("%.4f", v.Close)
|
||||
if i < len(data)-1 {
|
||||
str += ","
|
||||
}
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
func (data FinancialData) printHTMLRow(out io.Writer) {
|
||||
io.WriteString(out, " <tr>")
|
||||
printCellString(data.Date, out)
|
||||
printCellFloat(data.Open, out)
|
||||
printCellFloat(data.High, out)
|
||||
printCellFloat(data.Low, out)
|
||||
printCellFloat(data.Close, out)
|
||||
printCellFloat(data.Adj_Close, out)
|
||||
printCellFloatFmt(data.Volume, "%f", out)
|
||||
io.WriteString(out, "</tr>\n")
|
||||
}
|
||||
|
||||
func printCellString(val string, out io.Writer) {
|
||||
io.WriteString(out, "<td>"+val+"</td>")
|
||||
}
|
||||
|
||||
func printCellFloatFmt(val float64, format string, out io.Writer) {
|
||||
io.WriteString(out, fmt.Sprintf("<td>"+format+"</td>", val))
|
||||
}
|
||||
func printCellFloat(val float64, out io.Writer) {
|
||||
printCellFloatFmt(val, "%.2f", out)
|
||||
}
|
||||
|
||||
func printFooter() {
|
||||
fmt.Println(` </table>
|
||||
</body>
|
||||
</html> `)
|
||||
}
|
||||
|
||||
func readCsvLine(line []string) *FinancialData {
|
||||
data := new(FinancialData)
|
||||
for i, col := range line {
|
||||
switch COLUMNS[i] {
|
||||
case "Date":
|
||||
data.Date = col
|
||||
case "Open":
|
||||
data.Open = toFloat(col)
|
||||
case "High":
|
||||
data.High = toFloat(col)
|
||||
case "Low":
|
||||
data.Low = toFloat(col)
|
||||
case "Close":
|
||||
data.Close = toFloat(col)
|
||||
case "Adj Close":
|
||||
data.Adj_Close = toFloat(col)
|
||||
case "Volume":
|
||||
data.Volume = toFloat(col)
|
||||
}
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func toFloat(v string) float64 {
|
||||
f, err := strconv.ParseFloat(v, 64)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
func readCsvHeader(line []string) {
|
||||
for _, col := range line {
|
||||
COLUMNS = append(COLUMNS, col)
|
||||
}
|
||||
}
|
||||
|
||||
func readCsv(in io.Reader) []FinancialData {
|
||||
data := []FinancialData{}
|
||||
csvReader := csv.NewReader(in)
|
||||
for {
|
||||
line, err := csvReader.Read()
|
||||
if err == io.EOF {
|
||||
break
|
||||
} else if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if len(COLUMNS) == 0 {
|
||||
readCsvHeader(line)
|
||||
} else {
|
||||
data = append(data, *readCsvLine(line))
|
||||
}
|
||||
}
|
||||
return data
|
||||
|
||||
}
|
||||
|
||||
func main() {
|
||||
if len(os.Args) < 2 {
|
||||
log.Fatalln("Usage go-financial <file>")
|
||||
}
|
||||
|
||||
// read input
|
||||
csv, err := os.Open(os.Args[1])
|
||||
if err != nil {
|
||||
log.Fatalln("Error reading file", err)
|
||||
}
|
||||
defer csv.Close()
|
||||
|
||||
// output
|
||||
var out io.Writer
|
||||
if len(os.Args) > 2 {
|
||||
fout, err := os.Create(os.Args[2])
|
||||
if err != nil {
|
||||
log.Fatalln("Error creating output file", err)
|
||||
}
|
||||
defer fout.Close()
|
||||
out = fout
|
||||
} else {
|
||||
out = os.Stdout
|
||||
}
|
||||
|
||||
// parse data
|
||||
data := readCsv(csv)
|
||||
|
||||
printHTML(data, out)
|
||||
}
|
Loading…
Reference in New Issue
Block a user