我每隔几个月左右使用一次F#,在它之间我似乎忘了一切,所以我希望你能原谅我的无知。我的下面的代码是从雅虎提取数据。这是一个很好的例子,代表了我需要做的事情。返回的第一行具有列标题。我需要获取数据(列表的尾部)并将其插入数据库。基于返回的列标题生成插入语句的最佳方法是什么(列标题与数据库列名称匹配)?
在下面的例子中dataWithHeaders。[0]将包含“日期,开盘价,最高价,最低价,收盘价,成交量,调整收盘价”。我应该只拿这个字符串并在标题周围放置括号来创建插入吗?然后在insertData中添加值作为参数?有更优雅的解决方案吗?
let url = System.String.Format("http://ichart.finance.yahoo.com/table.csv?s={0}&g=d&ignore=.csv", "FB")
let splitLineIntoArray (line : string) =
line.Split(",".ToCharArray())
let insertData (data : string[]) =
// insert data
()
let client = new WebClient()
let dataWithHeaders =
client.DownloadString(url).Split(Environment.NewLine.ToCharArray())
let data =
dataWithHeaders
|> Array.toList
|> List.tail
|> List.map(splitLineIntoArray)
|> List.iter insertData
答案 0 :(得分:8)
如果要将数据加载到SQL Server,可以使用this excellent CSV reader(免费)和SqlBulkCopy
类。它简单而有效。
let loadStockPrices ticker =
use client = new WebClient()
let url = sprintf "http://ichart.finance.yahoo.com/table.csv?s=%s&g=d&ignore=.csv" ticker
use stringReader = new StringReader(client.DownloadString(url))
use csvReader = new CsvReader(stringReader, hasHeaders=true)
use con = new SqlConnection("<connection_string>")
con.Open()
use bulkCopy = new SqlBulkCopy(con, DestinationTableName="<destination_table>")
bulkCopy.WriteToServer(csvReader)
目标表应与传入数据(OHLC等)具有相同的列。
答案 1 :(得分:4)
编辑:类型提供程序可能是一个很好的方法,但SqlBulkCopy是def。以其简洁而着称。
为插入输入提供商代码:http://msdn.microsoft.com/en-us/library/hh361033(v=vs.110).aspx#BKMK_UpdateDB
type dbSchema = SqlDataConnection<"Data Source=MYSERVER\INSTANCE;Initial Catalog=MyDatabase;Integrated Security=SSPI;">
let db = dbSchema.GetDataContext()
// Enable the logging of database activity to the console.
db.DataContext.Log <- System.Console.Out
let newRecord = new dbSchema.ServiceTypes.Table1(Id = 100,
TestData1 = 35,
TestData2 = 2.0,
Name = "Testing123")
let newValues =
[ for i in [1 .. 10] ->
new dbSchema.ServiceTypes.Table3(Id = 700 + i,
Name = "Testing" + i.ToString(),
Data = i) ]
// Insert the new data into the database.
db.Table1.InsertOnSubmit(newRecord)
db.Table3.InsertAllOnSubmit(newValues)
try
db.DataContext.SubmitChanges()
printfn "Successfully inserted new rows."
with
| exn -> printfn "Exception:\n%s" exn.Message
我做了类似的事情。实际上,我在观看Luca Bolognese时写的这段代码就F#进行了演示。这实际上将刮掉雅虎的饲料并返回标准开发。和股价的差异。
此处的完整项目:https://github.com/djohnsonm/Stock-Ticker-App
open System.Net
open System.IO
let internal loadPrices ticker = async {
let url = @"http://ichart.finance.yahoo.com/table.csv?s=" + ticker + "&d=6&e=22&f=2011&g=d&a=2&b=13&c=1986&ignore=.csv"
let req = WebRequest.Create(url)
let resp = req.GetResponse()
let stream = resp.GetResponseStream()
let reader = new StreamReader(stream)
let csv = reader.ReadToEnd()
let prices =
csv.Split([|'\n'|])
|> Seq.skip 1
|> Seq.map (fun line -> line.Split([|','|]))
|> Seq.filter(fun values -> values |> Seq.length = 7)
|> Seq.map(fun values ->
System.DateTime.Parse(values.[0]),
float values.[6])
return prices}
type StockAnalyzer (lprices, days) =
let prices =
lprices
|> Seq.map snd
|> Seq.take days
static member GetAnalyzers (tickers, days) =
tickers
|> Seq.map loadPrices
|> Async.Parallel
|> Async.RunSynchronously
|> Seq.map (fun prices -> new StockAnalyzer(prices, days))
member s.Return =
let lastPrice = prices |> Seq.nth 0
let startPrice = prices |> Seq.nth(days-1)
lastPrice / startPrice - 1.
member s.StdDev =
let logRets =
prices
|> Seq.pairwise
|> Seq.map (fun (x,y) -> log(x/y))
let mean = logRets |> Seq.average
let sqr x = x * x
let var = logRets |> Seq.averageBy (fun r -> sqr (r-mean))
sqrt var