Mercurial > mercurial > hgweb_golang.cgi
diff src/fx/fx.go @ 31:a55c5a0cbd04
add fx.
author | pyon@macmini |
---|---|
date | Sun, 12 May 2019 20:51:18 +0900 |
parents | |
children | 90659c7171ed |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/fx/fx.go Sun May 12 20:51:18 2019 +0900 @@ -0,0 +1,203 @@ +package main + +import ( + "bytes" + "encoding/csv" + "fmt" + "io" + "io/ioutil" + "log" + "math" + "strconv" + "strings" +) + +const debug = false + +func main() { + n, m := 20, 14 + var x, xl, xh []float64 + var date []string + + // Read Exchange-data + content, err := ioutil.ReadFile("/Users/takayuki/Downloads/USDJPY.csv") + if err != nil { + log.Fatal(err) + } + + r := csv.NewReader(bytes.NewReader(content)) + for { + record, err := r.Read() + if err == io.EOF { + break + } + if err != nil { + log.Fatal(err) + } + + f, err := strconv.ParseFloat(record[4], 64) + if err != nil { + continue + } + x = append(x, f) + + f, err = strconv.ParseFloat(record[3], 64) + xl = append(xl, f) + + f, err = strconv.ParseFloat(record[2], 64) + xh = append(xh, f) + + date = append(date, strings.ReplaceAll(record[0], "/", "-")) + } + + // Calc Moving-Average + xa := make([]float64, len(x)) + for i := n; i < len(x); i++ { + for j := 0; j < n; j++ { + xa[i] += x[i-j] + } + xa[i] /= float64(n) + } + + // Calc Variance & SD + v := make([]float64, len(x)) + sd := make([]float64, len(x)) + for i := n; i < len(x); i++ { + // variance + for j := 0; j < n; j++ { + v[i] += (x[i-j] - xa[i-j]) * (x[i-j] - xa[i-j]) + } + v[i] /= float64(n) + + // standard deviation + sd[i] = math.Sqrt(v[i]) + } + + // Calc Bollinger-Bands + bb1 := make([]float64, len(x)) + bb2 := make([]float64, len(x)) + for i := n * 2; i < len(x); i++ { + bb1[i], bb2[i] = x[i] - sd[i], x[i] + sd[i] + } + + // Calc RSI + rsi := make([]float64, len(x)) + for i := m; i < len(x); i++ { + var ru, rd float64 + for j := 0; j < m; j++ { + z := x[i-j-1] - x[i-j] + if z > 0 { + ru += z + } else { + rd += -z + } + } + rsi[i] = rd / (rd + ru) * 100 + } + + // Make Graph + // [chart.svg] + w, h := 800, 600 + + term := 200 + min, max := 200.0, 1.0 + for i := len(x) - term; i < len(x); i++ { + min = math.Min(min, x[i]) + max = math.Max(max, x[i]) + min = math.Min(min, bb1[i]) + max = math.Max(max, bb2[i]) + } + sx := float64(w) / float64(term) + sy := float64(h) / (max - min) + + svg := fmt.Sprintf("<svg xmlns='http://www.w3.org/2000/svg' width='%d' height='%d'>\n", w, h) + for y := int(min); y < int(max) + 1; y++ { + svg += make_line(h, 0, float64(y), w, float64(y), min, 1.0, sy, "gray", 0.2) + svg += make_label(h, 10, y, min, 1.0, sy, fmt.Sprintf("%d", y)) + } + for i, j, lm := len(x) - term, 0, ""; i < len(x); i, j = i + 1, j + 1 { + if !strings.EqualFold(lm, date[i][5:7]) { + svg += make_line(h, j, 0.0, j, float64(h), 0, sx, 1.0, "gray", 0.2) + svg += make_label(h, j, 20, 0, sx, 1.0, date[i][0:7]) + lm = date[i][5:7] + } + } + + for i, j := len(x) - term, 1; i < len(x); i, j = i + 1, j + 1 { + svg += make_line(h, j-1, x[i-1], j, x[i], min, sx, sy, "black", 1.5) + svg += make_line(h, j-1, xa[i-1], j, xa[i], min, sx, sy, "green", 0.7) + svg += make_line(h, j-1, bb1[i-1], j, bb1[i], min, sx, sy, "red", 0.2) + svg += make_line(h, j-1, bb2[i-1], j, bb2[i], min, sx, sy, "blue", 0.2) + } + svg += fmt.Sprint("</svg>\n") + if err := ioutil.WriteFile("chart.svg", []byte(svg), 0644); err != nil { + log.Fatal(err) + } + + // [rsi.svg] + w, h = w, 150 + sy = float64(h) / 100 + svg = fmt.Sprintf("<svg xmlns='http://www.w3.org/2000/svg' width='%d' height='%d'>\n", w, h) + svg += make_line(h, 0, 30.0, w, 30.0, 0, 1.0, sy, "gray", 0.2) + svg += make_label(h, 10, 30, 0, 1.0, sy, fmt.Sprintf("30%%")) + svg += make_line(h, 0, 50.0, w, 50.0, 0, 1.0, sy, "gray", 0.2) + svg += make_label(h, 10, 50, 0, 1.0, sy, fmt.Sprintf("50%%")) + svg += make_line(h, 0, 70.0, w, 70.0, 0, 1.0, sy, "gray", 0.2) + svg += make_label(h, 10, 70, 0, 1.0, sy, fmt.Sprintf("70%%")) + + for i, j, lm := len(x) - term, 0, ""; i < len(x); i, j = i + 1, j + 1 { + if !strings.EqualFold(lm, date[i][5:7]) { + svg += make_line(h, j, 0.0, j, float64(h), 0, sx, 1.0, "gray", 0.2) + svg += make_label(h, j, 20, 0, sx, 1.0, date[i][0:7]) + lm = date[i][5:7] + } + } + + for i, j := len(x) - term, 1; i < len(x); i, j = i + 1, j + 1 { + svg += make_line(h, j-1, rsi[i-1], j, rsi[i], 0, sx, sy, "black", 1.5) + } + svg += fmt.Sprint("</svg>\n") + if err := ioutil.WriteFile("rsi.svg", []byte(svg), 0644); err != nil { + log.Fatal(err) + } + + // Make Html + html := "<html><body>" + html += "<h2>Daily Chart</h2>" + html += "<img src='chart.svg' />" + html += "<h2>RSI</h2>" + html += "<img src='rsi.svg' />" + html += "</body><html>" + if err := ioutil.WriteFile("fx.html", []byte(html), 0644); err != nil { + log.Fatal(err) + } + + // Print Data + if false { + fmt.Println("[j] n x bb1 bb2 rsi | n x bb1 bb2") + fmt.Println("---") + for i, j := len(x) - term, 0; i < len(x); i++ { + fmt.Printf("[%04d] %04d %5.2f %5.2f %5.2f %3.1f | ", j, i, x[i], bb1[i], bb2[i], rsi[i]) + fmt.Printf("%04.0f %5.2f %5.2f %5.2f ", float64(i) * sx, (x[i] - min) * sy, (bb1[i] - min) * sy, (bb2[i] - min) * sy) + fmt.Println() + j++ + } + fmt.Println("---") + fmt.Printf("min=%5.2f max=%5.2f\n", min, max) + } +} + +func make_line(h, x1 int, y1 float64, x2 int, y2 float64, os, sx, sy float64, c string, sw float64) string { + x1, y1 = int(float64(x1) * sx), (y1 - os) * sy + x2, y2 = int(float64(x2) * sx), (y2 - os) * sy + y1, y2 = float64(h) - y1, float64(h) - y2 + return fmt.Sprintf("<line x1='%d' y1='%d' x2='%d' y2='%d' stroke='%s' stroke-width='%0.1f' />\n", x1, int(y1), x2, int(y2), c, sw) +} + +func make_label(h, x, y int, os, sx, sy float64, label string) string { + x = int(float64(x) * sx) + y = int((float64(y) - os) * sy) + y = h - y + return fmt.Sprintf("<text x='%d' y='%d'>%s</text>", x, y, label) +} +