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 |