配列の配列への格納
日足描画用のCSVファイル(ソースと同一ディレクトリに配置)を開いて、一旦Stringを要素とする配列(1日分の日付とOHLC値)の配列resultに格納する。さらにresultをDoubleを要素とする配列(1日分のOHLC値)の配列arに変換する。変換にはCの関数atofを使う。文字/数値の変換後、CSVファイルの中のOHLC値から最大最小値の検出も行う。 (Xcode7.0 + Swift2.0 + Terminal.App or Xcode8.3.2 + Swift3.1 + Terminal.App)
残り課題
- 配列arをNSDateとDoubleを格納した配列の配列へと修正。
- resultに1日分の日付、OHLC値に加えてVolumeも格納するよう修正。
swift2.0.swift
import Foundation
import Darwin
var result: [[String]] = []
let path = "./TEST_Stock.csv"
//let path = "./stest.csv"
//NSString.stringWithContentsOfFileを呼ぶと、ambigousとか言うので...
do {
var data = try String(contentsOfFile: path,
encoding: NSUTF8StringEncoding)
data.enumerateLines { (line, stop) -> () in
result.append(line.componentsSeparatedByString(","))
}
} catch let e as NSError {print(e.localizedDescription)}
//print(result)
// taking last 10 elements
let limit = 10
let r: Range<Int> = 0..<result.count-limit
result.removeRange(r)
for (idx, e) in result.enumerate() {
print("\(idx) : \(e)")
}
var ar: [[Double]] = []
func minmax(result: [[String]], inout ar: [[Double]]) -> (Double, Double) {
// taking partial part, #1 to #4 of Array -> ArraySlice
let result0 = result.map( {Array($0[1...4])} )
ar = result0.map({$0.map({atof($0)})})
//var max: Double = -1.0, min: Double = Double.infinity//1.0e38
var max: Double = -Double.infinity, min: Double = -max
for e in ar {
// giita:// tag:swift map reduce
max = e.reduce(max, combine: {$0>$1 ? $0 : $1})
min = e.reduce(min, combine: {$0<$1 ? $0 : $1})
}
return (min, max)
}
let tap = minmax(result, ar: &ar)
print(tap)
TEST_Stock.csv
MDATE,OPEN,HIGH,LOW,CLOSE,VOLUME
1987/8/1,24755,24755,24755,24755,0
1987/8/3,24483,24483,24483,24483,0
1987/8/4,24172,24172,24172,24172,0
1987/8/5,24297,24297,24297,24297,0
1987/8/6,24658,24658,24658,24658,0
1987/8/7,24800,24800,24800,24800,0
1987/8/10,25119,25119,25119,25119,0
1987/8/11,25282,25282,25282,25282,0
1987/8/12,25560,25560,25560,25560,0
1987/8/13,25575,25575,25575,25575,0
1987/8/14,25494,25494,25494,25494,0
1987/8/17,25378,25378,25378,25378,0
1987/8/18,25344,25344,25344,25344,0
1987/8/19,25231,25231,25231,25231,0
1987/8/20,25396,25396,25396,25396,0
1987/8/21,25559,25559,25559,25559,0
1987/8/22,25764,25764,25764,25764,0
1987/8/24,25754,25754,25754,25754,0
1987/8/25,25643,25643,25643,25643,0
1987/8/26,25875,25875,25875,25875,0
1987/8/27,25968,25968,25968,25968,0
1987/8/28,25974,25974,25974,25974,0
1987/8/29,26048,26048,26048,26048,0
1987/8/31,26029,26029,26029,26029,0
1987/9/1,26118,26118,26118,26118,0
1987/9/2,25946,25946,25946,25946,0
1987/9/3,25649,25649,25649,25649,0
1987/9/4,25744,25744,25744,25744,0
Swift3.1用に書き直し
swift3.1.swift
// Swift3.1でコンパイル出来る。Swift4.xも後日試してみる。
import Foundation
var result: [[String]] = []
let path = "./TEST_Stock.csv"
var data: String = try! String(contentsOfFile: path)
data.enumerateLines { (line, stop) -> () in
result.append(line.components(separatedBy:","))
}
let limit = 10
let r: Range<Int> = 0..<result.count-limit
result.removeSubrange(r)
for (idx, e) in result.enumerated() {
print("\(idx) : \(e)")
}
print(result)
/* print(data) */
var ar: [[Double]] = []
func minmax(_ result: [[String]], ar: inout [[Double]]) -> (Double, Double) {
// taking partial part, #1 to #4 of Array -> ArraySlice
let result0 = result.map( {Array($0[1...4])} )
ar = result0.map({$0.map({atof($0)})})
//var max: Double = -1.0, min: Double = Double.infinity//1.0e38
var max: Double = -Double.infinity, min: Double = -max
for e in ar {
// giita:// tag:swift map reduce
max = e.reduce(max, {$0>$1 ? $0 : $1})
// max = e.reduce(max, combine: {$0>$1 ? $0 : $1})
min = e.reduce(min, {$0<$1 ? $0 : $1})
}
return (min, max)
}
let tap = minmax(result, ar: &ar)
print(tap)
/* 1. inout keyワードは、変数名の前に置くのでは無く、型名の前に置く */
/* 2. reduceメソッドは無名ラベルを使ったセレクタに変更reduce(_:_:) */
おまけ 日付を文字列で、文字列を日付に
DateFormatterオブジェクト、TimeZoneオブジェクトを使う
swift3.1.swift
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US")
dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
dateFormatter.dateFormat = "yyyy/MM/dd HH:mm:ss Z"
print(dateFormatter.string(from:Date()))
dateFormatter.timeZone = TimeZone(abbreviation: "JST")
print(dateFormatter.string(from:Date()))
dateFormatter.locale = Locale(identifier: "ja_JP")
dateFormatter.dateStyle = .medium
dateFormatter.timeStyle = .full
print(dateFormatter.string(from:Date()))
/* print(TimeZone.abbreviationDictionary) */
/* 2018/12/21 02:03:31 +0000 */
/* 2018/12/21 11:03:31 +0900 */
/* 2018/12/21 11時03分31秒 日本標準時 */
逆(文字列を日付に)はDateformatter#date(from:)を使う。
文字列を日付に)は
【Swift】Dateの王道 【日付】