Mercurial > mercurial > hgweb_golang.cgi
comparison src/fx/fx.go @ 31:a55c5a0cbd04
add fx.
| author | pyon@macmini |
|---|---|
| date | Sun, 12 May 2019 20:51:18 +0900 |
| parents | |
| children | 90659c7171ed |
comparison
equal
deleted
inserted
replaced
| 30:a273d4792e48 | 31:a55c5a0cbd04 |
|---|---|
| 1 package main | |
| 2 | |
| 3 import ( | |
| 4 "bytes" | |
| 5 "encoding/csv" | |
| 6 "fmt" | |
| 7 "io" | |
| 8 "io/ioutil" | |
| 9 "log" | |
| 10 "math" | |
| 11 "strconv" | |
| 12 "strings" | |
| 13 ) | |
| 14 | |
| 15 const debug = false | |
| 16 | |
| 17 func main() { | |
| 18 n, m := 20, 14 | |
| 19 var x, xl, xh []float64 | |
| 20 var date []string | |
| 21 | |
| 22 // Read Exchange-data | |
| 23 content, err := ioutil.ReadFile("/Users/takayuki/Downloads/USDJPY.csv") | |
| 24 if err != nil { | |
| 25 log.Fatal(err) | |
| 26 } | |
| 27 | |
| 28 r := csv.NewReader(bytes.NewReader(content)) | |
| 29 for { | |
| 30 record, err := r.Read() | |
| 31 if err == io.EOF { | |
| 32 break | |
| 33 } | |
| 34 if err != nil { | |
| 35 log.Fatal(err) | |
| 36 } | |
| 37 | |
| 38 f, err := strconv.ParseFloat(record[4], 64) | |
| 39 if err != nil { | |
| 40 continue | |
| 41 } | |
| 42 x = append(x, f) | |
| 43 | |
| 44 f, err = strconv.ParseFloat(record[3], 64) | |
| 45 xl = append(xl, f) | |
| 46 | |
| 47 f, err = strconv.ParseFloat(record[2], 64) | |
| 48 xh = append(xh, f) | |
| 49 | |
| 50 date = append(date, strings.ReplaceAll(record[0], "/", "-")) | |
| 51 } | |
| 52 | |
| 53 // Calc Moving-Average | |
| 54 xa := make([]float64, len(x)) | |
| 55 for i := n; i < len(x); i++ { | |
| 56 for j := 0; j < n; j++ { | |
| 57 xa[i] += x[i-j] | |
| 58 } | |
| 59 xa[i] /= float64(n) | |
| 60 } | |
| 61 | |
| 62 // Calc Variance & SD | |
| 63 v := make([]float64, len(x)) | |
| 64 sd := make([]float64, len(x)) | |
| 65 for i := n; i < len(x); i++ { | |
| 66 // variance | |
| 67 for j := 0; j < n; j++ { | |
| 68 v[i] += (x[i-j] - xa[i-j]) * (x[i-j] - xa[i-j]) | |
| 69 } | |
| 70 v[i] /= float64(n) | |
| 71 | |
| 72 // standard deviation | |
| 73 sd[i] = math.Sqrt(v[i]) | |
| 74 } | |
| 75 | |
| 76 // Calc Bollinger-Bands | |
| 77 bb1 := make([]float64, len(x)) | |
| 78 bb2 := make([]float64, len(x)) | |
| 79 for i := n * 2; i < len(x); i++ { | |
| 80 bb1[i], bb2[i] = x[i] - sd[i], x[i] + sd[i] | |
| 81 } | |
| 82 | |
| 83 // Calc RSI | |
| 84 rsi := make([]float64, len(x)) | |
| 85 for i := m; i < len(x); i++ { | |
| 86 var ru, rd float64 | |
| 87 for j := 0; j < m; j++ { | |
| 88 z := x[i-j-1] - x[i-j] | |
| 89 if z > 0 { | |
| 90 ru += z | |
| 91 } else { | |
| 92 rd += -z | |
| 93 } | |
| 94 } | |
| 95 rsi[i] = rd / (rd + ru) * 100 | |
| 96 } | |
| 97 | |
| 98 // Make Graph | |
| 99 // [chart.svg] | |
| 100 w, h := 800, 600 | |
| 101 | |
| 102 term := 200 | |
| 103 min, max := 200.0, 1.0 | |
| 104 for i := len(x) - term; i < len(x); i++ { | |
| 105 min = math.Min(min, x[i]) | |
| 106 max = math.Max(max, x[i]) | |
| 107 min = math.Min(min, bb1[i]) | |
| 108 max = math.Max(max, bb2[i]) | |
| 109 } | |
| 110 sx := float64(w) / float64(term) | |
| 111 sy := float64(h) / (max - min) | |
| 112 | |
| 113 svg := fmt.Sprintf("<svg xmlns='http://www.w3.org/2000/svg' width='%d' height='%d'>\n", w, h) | |
| 114 for y := int(min); y < int(max) + 1; y++ { | |
| 115 svg += make_line(h, 0, float64(y), w, float64(y), min, 1.0, sy, "gray", 0.2) | |
| 116 svg += make_label(h, 10, y, min, 1.0, sy, fmt.Sprintf("%d", y)) | |
| 117 } | |
| 118 for i, j, lm := len(x) - term, 0, ""; i < len(x); i, j = i + 1, j + 1 { | |
| 119 if !strings.EqualFold(lm, date[i][5:7]) { | |
| 120 svg += make_line(h, j, 0.0, j, float64(h), 0, sx, 1.0, "gray", 0.2) | |
| 121 svg += make_label(h, j, 20, 0, sx, 1.0, date[i][0:7]) | |
| 122 lm = date[i][5:7] | |
| 123 } | |
| 124 } | |
| 125 | |
| 126 for i, j := len(x) - term, 1; i < len(x); i, j = i + 1, j + 1 { | |
| 127 svg += make_line(h, j-1, x[i-1], j, x[i], min, sx, sy, "black", 1.5) | |
| 128 svg += make_line(h, j-1, xa[i-1], j, xa[i], min, sx, sy, "green", 0.7) | |
| 129 svg += make_line(h, j-1, bb1[i-1], j, bb1[i], min, sx, sy, "red", 0.2) | |
| 130 svg += make_line(h, j-1, bb2[i-1], j, bb2[i], min, sx, sy, "blue", 0.2) | |
| 131 } | |
| 132 svg += fmt.Sprint("</svg>\n") | |
| 133 if err := ioutil.WriteFile("chart.svg", []byte(svg), 0644); err != nil { | |
| 134 log.Fatal(err) | |
| 135 } | |
| 136 | |
| 137 // [rsi.svg] | |
| 138 w, h = w, 150 | |
| 139 sy = float64(h) / 100 | |
| 140 svg = fmt.Sprintf("<svg xmlns='http://www.w3.org/2000/svg' width='%d' height='%d'>\n", w, h) | |
| 141 svg += make_line(h, 0, 30.0, w, 30.0, 0, 1.0, sy, "gray", 0.2) | |
| 142 svg += make_label(h, 10, 30, 0, 1.0, sy, fmt.Sprintf("30%%")) | |
| 143 svg += make_line(h, 0, 50.0, w, 50.0, 0, 1.0, sy, "gray", 0.2) | |
| 144 svg += make_label(h, 10, 50, 0, 1.0, sy, fmt.Sprintf("50%%")) | |
| 145 svg += make_line(h, 0, 70.0, w, 70.0, 0, 1.0, sy, "gray", 0.2) | |
| 146 svg += make_label(h, 10, 70, 0, 1.0, sy, fmt.Sprintf("70%%")) | |
| 147 | |
| 148 for i, j, lm := len(x) - term, 0, ""; i < len(x); i, j = i + 1, j + 1 { | |
| 149 if !strings.EqualFold(lm, date[i][5:7]) { | |
| 150 svg += make_line(h, j, 0.0, j, float64(h), 0, sx, 1.0, "gray", 0.2) | |
| 151 svg += make_label(h, j, 20, 0, sx, 1.0, date[i][0:7]) | |
| 152 lm = date[i][5:7] | |
| 153 } | |
| 154 } | |
| 155 | |
| 156 for i, j := len(x) - term, 1; i < len(x); i, j = i + 1, j + 1 { | |
| 157 svg += make_line(h, j-1, rsi[i-1], j, rsi[i], 0, sx, sy, "black", 1.5) | |
| 158 } | |
| 159 svg += fmt.Sprint("</svg>\n") | |
| 160 if err := ioutil.WriteFile("rsi.svg", []byte(svg), 0644); err != nil { | |
| 161 log.Fatal(err) | |
| 162 } | |
| 163 | |
| 164 // Make Html | |
| 165 html := "<html><body>" | |
| 166 html += "<h2>Daily Chart</h2>" | |
| 167 html += "<img src='chart.svg' />" | |
| 168 html += "<h2>RSI</h2>" | |
| 169 html += "<img src='rsi.svg' />" | |
| 170 html += "</body><html>" | |
| 171 if err := ioutil.WriteFile("fx.html", []byte(html), 0644); err != nil { | |
| 172 log.Fatal(err) | |
| 173 } | |
| 174 | |
| 175 // Print Data | |
| 176 if false { | |
| 177 fmt.Println("[j] n x bb1 bb2 rsi | n x bb1 bb2") | |
| 178 fmt.Println("---") | |
| 179 for i, j := len(x) - term, 0; i < len(x); i++ { | |
| 180 fmt.Printf("[%04d] %04d %5.2f %5.2f %5.2f %3.1f | ", j, i, x[i], bb1[i], bb2[i], rsi[i]) | |
| 181 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) | |
| 182 fmt.Println() | |
| 183 j++ | |
| 184 } | |
| 185 fmt.Println("---") | |
| 186 fmt.Printf("min=%5.2f max=%5.2f\n", min, max) | |
| 187 } | |
| 188 } | |
| 189 | |
| 190 func make_line(h, x1 int, y1 float64, x2 int, y2 float64, os, sx, sy float64, c string, sw float64) string { | |
| 191 x1, y1 = int(float64(x1) * sx), (y1 - os) * sy | |
| 192 x2, y2 = int(float64(x2) * sx), (y2 - os) * sy | |
| 193 y1, y2 = float64(h) - y1, float64(h) - y2 | |
| 194 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) | |
| 195 } | |
| 196 | |
| 197 func make_label(h, x, y int, os, sx, sy float64, label string) string { | |
| 198 x = int(float64(x) * sx) | |
| 199 y = int((float64(y) - os) * sy) | |
| 200 y = h - y | |
| 201 return fmt.Sprintf("<text x='%d' y='%d'>%s</text>", x, y, label) | |
| 202 } | |
| 203 |
