tushare 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,136 @@
1
+ require 'tushare/util'
2
+
3
+ module Tushare
4
+ module Stock
5
+ # 上海银行间同业拆放利率(Shibor)数据接口
6
+ module Shibor
7
+ extend Tushare::Util
8
+
9
+ # 获取上海银行间同业拆放利率(Shibor)
10
+ # Parameters
11
+ # ------
12
+ # year:年份(int)
13
+
14
+ # Return
15
+ # ------
16
+ # date:日期
17
+ # ON:隔夜拆放利率
18
+ # 1W:1周拆放利率
19
+ # 2W:2周拆放利率
20
+ # 1M:1个月拆放利率
21
+ # 3M:3个月拆放利率
22
+ # 6M:6个月拆放利率
23
+ # 9M:9个月拆放利率
24
+ # 1Y:1年拆放利率
25
+ def shibor_data(year = Time.now.year)
26
+ url = format(SHIBOR_DATA_URL, P_TYPE['http'], DOMAINS['shibor'],
27
+ PAGES['dw'], 'Shibor', year, SHIBOR_TYPE['Shibor'], year)
28
+ xls = ::Roo::Spreadsheet.open(URI.encode(url), extension: 'xls')
29
+ process_xls_file(xls, SHIBOR_COLS)
30
+ end
31
+
32
+ # 获取Shibor银行报价数据
33
+ # Parameters
34
+ # ------
35
+ # year:年份(int)
36
+
37
+ # Return
38
+ # ------
39
+ # date:日期
40
+ # bank:报价银行名称
41
+ # ON:隔夜拆放利率
42
+ # ON_B:隔夜拆放买入价
43
+ # ON_A:隔夜拆放卖出价
44
+ # 1W_B:1周买入
45
+ # 1W_A:1周卖出
46
+ # 2W_B:买入
47
+ # 2W_A:卖出
48
+ # 1M_B:买入
49
+ # 1M_A:卖出
50
+ # 3M_B:买入
51
+ # 3M_A:卖出
52
+ # 6M_B:买入
53
+ # 6M_A:卖出
54
+ # 9M_B:买入
55
+ # 9M_A:卖出
56
+ # 1Y_B:买入
57
+ # 1Y_A:卖出
58
+ def shibor_quote_data(year = Time.now.year)
59
+ url = format(SHIBOR_DATA_URL, P_TYPE['http'], DOMAINS['shibor'],
60
+ PAGES['dw'], 'Quote', year, SHIBOR_TYPE['Quote'], year)
61
+ xls = ::Roo::Spreadsheet.open(URI.encode(url), extension: 'xls')
62
+ process_xls_file(xls, QUOTE_COLS)
63
+ end
64
+
65
+ # 获取Shibor均值数据
66
+ # Parameters
67
+ # ------
68
+ # year:年份(int)
69
+
70
+ # Return
71
+ # ------
72
+ # date:日期
73
+ # 其它分别为各周期5、10、20均价
74
+ def shibor_ma_data(year = Time.now.year)
75
+ url = format(SHIBOR_DATA_URL, P_TYPE['http'], DOMAINS['shibor'],
76
+ PAGES['dw'], 'Shibor_Tendency', year, SHIBOR_TYPE['Tendency'],
77
+ year)
78
+ xls = ::Roo::Spreadsheet.open(URI.encode(url), extension: 'xls')
79
+ process_xls_file(xls, SHIBOR_MA_COLS)
80
+ end
81
+
82
+ # 获取贷款基础利率(LPR)
83
+ # Parameters
84
+ # ------
85
+ # year:年份(int)
86
+
87
+ # Return
88
+ # ------
89
+ # date:日期
90
+ # 1Y:1年贷款基础利率
91
+ def lpr_data(year = Time.now.year)
92
+ url = format(SHIBOR_DATA_URL, P_TYPE['http'], DOMAINS['shibor'],
93
+ PAGES['dw'], 'LPR', year, SHIBOR_TYPE['LPR'], year)
94
+ xls = ::Roo::Spreadsheet.open(URI.encode(url), extension: 'xls')
95
+ process_xls_file(xls, LPR_COLS)
96
+ end
97
+
98
+ # 获取贷款基础利率均值数据
99
+ # Parameters
100
+ # ------
101
+ # year:年份(int)
102
+
103
+ # Return
104
+ # ------
105
+ # date:日期
106
+ # 1Y_5:5日均值
107
+ # 1Y_10:10日均值
108
+ # 1Y_20:20日均值
109
+ def lpr_ma_data(year = Time.now.year)
110
+ url = format(SHIBOR_DATA_URL, P_TYPE['http'], DOMAINS['shibor'],
111
+ PAGES['dw'], 'LPR_Tendency', year,
112
+ SHIBOR_TYPE['LPR_Tendency'], year)
113
+ xls = ::Roo::Spreadsheet.open(URI.encode(url), extension: 'xls')
114
+ process_xls_file(xls, LPR_MA_COLS)
115
+ end
116
+
117
+ private
118
+
119
+ # process xls every sheet and every sheet skip the first row
120
+ def process_xls_file(xls, cols)
121
+ result = []
122
+ xls.each_with_pagename do |_, sheet|
123
+ sheet.drop(1).each do |row|
124
+ object = {}
125
+ cols.each_with_index { |key, index| object[key] = row[index] }
126
+ result << object
127
+ end
128
+ end
129
+ result
130
+ end
131
+
132
+ module_function :shibor_data, :shibor_quote_data, :shibor_ma_data,
133
+ :lpr_data, :lpr_ma_data, :process_xls_file
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,513 @@
1
+ require 'tushare/util'
2
+ require 'nokogiri'
3
+ require 'open-uri'
4
+
5
+ module Tushare
6
+ module Stock
7
+ module Trading
8
+ extend Tushare::Util
9
+
10
+ # 获取个股历史交易记录
11
+ # Parameters
12
+ # ------
13
+ # code:string
14
+ # 股票代码 e.g. 600848
15
+ # start_date:string
16
+ # 开始日期 format:YYYY-MM-DD 为空时取到API所提供的最早日期数据
17
+ # end_date:string
18
+ # 结束日期 format:YYYY-MM-DD 为空时取到最近一个交易日数据
19
+ # ktype:string
20
+ # 数据类型,D=日k线 W=周 M=月 5=5分钟 15=15分钟 30=30分钟 60=60分钟,默认为D
21
+ # return
22
+ # -------
23
+ # DataFrame
24
+ # 属性:日期 ,开盘价, 最高价, 收盘价, 最低价, 成交量, 价格变动 ,涨跌幅,5日均价,10日均价,20日均价,5日均量,10日均量,20日均量,换手率
25
+ def get_hist_data(code, options = {})
26
+
27
+ symbol_code = _code_to_symbol(code)
28
+
29
+ raise 'invalid code' if symbol_code == ''
30
+
31
+ options = { start_date: '', end_date: '', ktype: 'D', ascending: false }.merge(options)
32
+
33
+ if K_LABELS.include?(options[:ktype].upcase)
34
+ url = format(DAY_PRICE_URL,
35
+ P_TYPE['http'],
36
+ DOMAINS['ifeng'],
37
+ K_TYPE[options[:ktype].upcase],
38
+ symbol_code)
39
+ elsif K_MIN_LABELS.include?(options[:ktype])
40
+ url = format(DAY_PRICE_MIN_URL,
41
+ P_TYPE['http'],
42
+ DOMAINS['ifeng'],
43
+ symbol_code,
44
+ options[:ktype])
45
+ else
46
+ raise 'ktype input error.'
47
+ end
48
+
49
+ cols = INDEX_LABELS.include?(code) ? INX_DAY_PRICE_COLUMNS : DAY_PRICE_COLUMNS
50
+
51
+ resp = HTTParty.get(url)
52
+ if resp.code.to_s == '200'
53
+ records = JSON.parse(resp.body)['record']
54
+ unless records.empty?
55
+ cols = INX_DAY_PRICE_COLUMNS if records.first.size == 14
56
+
57
+ records.reverse! if options[:ascending] == false
58
+ if options[:start_date] != '' && options[:end_date] != ''
59
+ records = records.select { |x| Time.parse(x[0]) <= Time.parse("#{options[:end_date]} 23:59") && Time.parse(x[0]) >= Time.parse("#{options[:start_date]} 00:00") }
60
+ end
61
+
62
+ records.map { |r| Hash[cols.zip(r)] }
63
+ end
64
+ else
65
+ []
66
+ end
67
+ end
68
+ # '''
69
+ # 获取分笔数据
70
+ # Parameters
71
+ # ------
72
+ # code:string
73
+ # 股票代码 e.g. 600848
74
+ # date:string
75
+ # 日期 format:YYYY-MM-DD
76
+ # return
77
+ # -------
78
+ # DataFrame 当日所有股票交易数据(DataFrame)
79
+ # 属性:成交时间、成交价格、价格变动,成交手、成交金额(元),买卖类型
80
+ # '''
81
+ def get_tick_data(code, date = '')
82
+ return nil if code.nil? || code.size != 6 || date == ''
83
+
84
+ symbol_code = _code_to_symbol(code)
85
+
86
+ raise 'invalid code' if symbol_code == ''
87
+
88
+ url = format(TICK_PRICE_URL, P_TYPE['http'], DOMAINS['sf'], PAGES['dl'], date, symbol_code)
89
+
90
+ resp = HTTParty.get(url)
91
+ if resp.code.to_s == '200'
92
+ tb_value = resp.body.encode('utf-8', 'gbk')
93
+ CSV.new(tb_value, headers: :first_row, encoding: 'utf-8', col_sep: ' ').map { |a| Hash[TICK_COLUMNS.zip(a.fields)] }
94
+ else
95
+ []
96
+ end
97
+ end
98
+ # '''
99
+ # 获取sina大单数据
100
+ # Parameters
101
+ # ------
102
+ # code:string
103
+ # 股票代码 e.g. 600848
104
+ # date:string
105
+ # 日期 format:YYYY-MM-DD
106
+ # retry_count : int, 默认 3
107
+ # 如遇网络等问题重复执行的次数
108
+ # pause : int, 默认 0
109
+ # 重复请求数据过程中暂停的秒数,防止请求间隔时间太短出现的问题
110
+ # return
111
+ # -------
112
+ # DataFrame 当日所有股票交易数据(DataFrame)
113
+ # 属性:股票代码 股票名称 交易时间 价格 成交量 前一笔价格 类型(买、卖、中性盘)
114
+ # '''
115
+ def get_sina_dd(code, options = {})
116
+ return nil if code.nil? || code.size != 6
117
+ symbol_code = _code_to_symbol(code)
118
+ raise 'invalid code' if symbol_code == ''
119
+
120
+ options = { date: Time.now.strftime('%Y-%m-%d'), vol: 400 }.merge(options)
121
+
122
+ vol = options[:vol] * 100
123
+ url = format(SINA_DD, P_TYPE['http'], DOMAINS['vsf'], PAGES['sinadd'], symbol_code, vol, options[:date])
124
+ resp = HTTParty.get(url)
125
+ if resp.code.to_s == '200'
126
+ val = resp.body.encode('utf-8', 'gbk')
127
+ CSV.new(val, headers: :first_row, encoding: 'utf-8', col_sep: ',').map do |a|
128
+ fields = a.fields
129
+ fields[0] = fields[0][2..-1]
130
+ Hash[SINA_DD_COLS.zip(fields)]
131
+ end
132
+ else
133
+ []
134
+ end
135
+ end
136
+ # '''
137
+ # 获取当日分笔明细数据
138
+ # Parameters
139
+ # ------
140
+ # code:string
141
+ # 股票代码 e.g. 600848
142
+ # retry_count : int, 默认 3
143
+ # 如遇网络等问题重复执行的次数
144
+ # pause : int, 默认 0
145
+ # 重复请求数据过程中暂停的秒数,防止请求间隔时间太短出现的问题
146
+ # return
147
+ # -------
148
+ # DataFrame 当日所有股票交易数据(DataFrame)
149
+ # 属性:成交时间、成交价格、价格变动,成交手、成交金额(元),买卖类型
150
+ # '''
151
+ def get_today_ticks(code)
152
+ return nil if code.nil? || code.size != 6
153
+ symbol_code = _code_to_symbol(code)
154
+ raise 'invalid code' if symbol_code == ''
155
+
156
+ all_ticks = []
157
+
158
+ url = format(TODAY_TICKS_PAGE_URL, P_TYPE['http'], DOMAINS['vsf'], PAGES['jv'], Time.now.strftime('%Y-%m-%d'), symbol_code)
159
+ resp = HTTParty.get(url)
160
+ if resp.code.to_s == '200'
161
+ val = eval(resp.body[1..-2])
162
+ pages = val[:detailPages].sort { |x, y| x[:page] <=> y[:page] }
163
+ date = Time.now.strftime('%Y-%m-%d')
164
+ _write_head
165
+ pages.each do |page|
166
+ _write_console
167
+ _today_ticks(symbol_code, date, page[:page], all_ticks)
168
+ end
169
+ all_ticks
170
+ else
171
+ []
172
+ end
173
+ end
174
+ # '''
175
+ # 一次性获取最近一个日交易日所有股票的交易数据
176
+ # return
177
+ # -------
178
+ # DataFrame
179
+ # 属性:代码,名称,涨跌幅,现价,开盘价,最高价,最低价,前日收盘价,成交量,换手率
180
+ # '''
181
+ def get_today_all
182
+ _write_head
183
+ all_data = []
184
+ data = _parsing_dayprice_json(1)
185
+ unless data.nil?
186
+ all_data << data
187
+ (2...PAGE_NUM[0]).each do |page|
188
+ nd = _parsing_dayprice_json(page)
189
+ all_data << nd unless nd.nil?
190
+ end
191
+ all_data.flatten!
192
+ end
193
+ all_data
194
+ end
195
+
196
+ # 获取实时交易数据 getting real time quotes data
197
+ # 用于跟踪交易情况(本次执行的结果-上一次执行的数据)
198
+ # Parameters
199
+ # ------
200
+ # symbols : string, array-like object (list, tuple, Series).
201
+ # return
202
+ # -------
203
+ # DataFrame 实时交易数据
204
+ # 属性:0:name,股票名字
205
+ # 1:open,今日开盘价
206
+ # 2:pre_close,昨日收盘价
207
+ # 3:price,当前价格
208
+ # 4:high,今日最高价
209
+ # 5:low,今日最低价
210
+ # 6:bid,竞买价,即“买一”报价
211
+ # 7:ask,竞卖价,即“卖一”报价
212
+ # 8:volumn,成交量 maybe you need do volumn/100
213
+ # 9:amount,成交金额(元 CNY)
214
+ # 10:b1_v,委买一(笔数 bid volume)
215
+ # 11:b1_p,委买一(价格 bid price)
216
+ # 12:b2_v,“买二”
217
+ # 13:b2_p,“买二”
218
+ # 14:b3_v,“买三”
219
+ # 15:b3_p,“买三”
220
+ # 16:b4_v,“买四”
221
+ # 17:b4_p,“买四”
222
+ # 18:b5_v,“买五”
223
+ # 19:b5_p,“买五”
224
+ # 20:a1_v,委卖一(笔数 ask volume)
225
+ # 21:a1_p,委卖一(价格 ask price)
226
+ # ...
227
+ # 30:date,日期;
228
+ # 31:time,时间;
229
+ def get_realtime_quotes(symbols = nil)
230
+ symbols = [symbols] if symbols.is_a?(String)
231
+ symbols_list = (symbols || []).map { |code| code_to_symbol(code) }
232
+ .join(',')
233
+ url = format(LIVE_DATA_URL, P_TYPE['http'], DOMAINS['sinahq'],
234
+ _random, symbols_list)
235
+ resp = HTTParty.get(url)
236
+ resp_string = resp.body.encode('utf-8', 'gbk')
237
+ result = []
238
+ resp_string.scan(/\="(.*)";/).each_with_index do |match_array, match_index|
239
+ string = match_array.first
240
+ object = { 'code' => symbols[match_index] }
241
+ string.split(',').each_with_index do |s, index|
242
+ next if LIVE_DATA_COLS[index] == 's'
243
+ object[LIVE_DATA_COLS[index]] = s
244
+ end
245
+ result << object
246
+ end
247
+ result
248
+ end
249
+
250
+ # 获取历史复权数据
251
+ # Parameters
252
+ # ------
253
+ # code:string
254
+ # 股票代码 e.g. 600848
255
+ # start:string
256
+ # 开始日期 format:YYYY-MM-DD 为空时取当前日期
257
+ # end:string
258
+ # 结束日期 format:YYYY-MM-DD 为空时取去年今日
259
+ # autype:string
260
+ # 复权类型,qfq-前复权 hfq-后复权 None-不复权,默认为qfq
261
+ # drop_factor : bool, 默认 True
262
+ # 是否移除复权因子,在分析过程中可能复权因子意义不大,但是如需要先储存到数据库之后再分析的话,有该项目会更加灵活
263
+ # return
264
+ # -------
265
+ # DataFrame
266
+ # date 交易日期 (index)
267
+ # open 开盘价
268
+ # high 最高价
269
+ # close 收盘价
270
+ # low 最低价
271
+ # volume 成交量
272
+ # amount 成交金额
273
+ def get_h_data(code, start_date = nil, end_date = nil, autype = 'qfq',
274
+ index = false, drop_factor = true)
275
+ start_date = if start_date.nil?
276
+ Date.today.prev_year
277
+ else
278
+ Date.strptime(start_date, '%F')
279
+ end
280
+ end_date = if end_date.nil?
281
+ Date.today
282
+ else
283
+ Date.strptime(end_date, '%F')
284
+ end
285
+ qs = start_date.step(end_date)
286
+ .map { |d| [d.year, (d.month + 2) / 3] }
287
+ .uniq
288
+ _write_head
289
+ result = _parse_fq_data(_get_index_url(index, code, qs[0]), index)
290
+ if qs.length > 1
291
+ 1.upto(qs.length - 1).each do |i|
292
+ _write_console
293
+ result.concat _parse_fq_data(_get_index_url(index, code, qs[i]),
294
+ index)
295
+ end
296
+ end
297
+ return [] if result.empty?
298
+ sorted_result = result.sort_by { |object| Date.strptime(object['date'], '%F') }
299
+ last_date = sorted_result.last['date']
300
+ result = result.uniq { |object| object['date'] }.select do |object|
301
+ date = Date.strptime(object['date'], '%F')
302
+ date >= start_date && date <= end_date
303
+ end
304
+ if index
305
+ return result.sort_by { |object| Date.strptime(object['date'], '%F') }
306
+ end
307
+ # 判断复权
308
+ if autype == 'hfq'
309
+ result.map do |object|
310
+ object.delete 'factor' if drop_factor
311
+ %w(open high close low).each do |key|
312
+ object[key] = object[key].to_f.round(2)
313
+ end
314
+ end
315
+ if index
316
+ return result.sort_by { |object| Date.strptime(object['date'], '%F') }
317
+ end
318
+ result
319
+ elsif autype == 'qfq'
320
+ result.map { |object| object.delete 'factor' } if drop_factor
321
+ fq_factors = _parse_fq_factor(code, start_date, end_date)
322
+ fq_factors.sort_by! { |object| Date.strptime(object['date'], '%F') }
323
+ frow = fq_factors.select { |object| object['date'] == last_date }.first
324
+ rt = get_realtime_quotes(code)
325
+ return nil if rt.empty?
326
+ pre_close = if rt.first['high'].to_f == 0 && rt.first['low'].to_f == 0
327
+ rt.first['pre_close'].to_f
328
+ elsif holiday? Date.today
329
+ rt.first['price'].to_f
330
+ elsif Time.now.hour > 9 && Time.now.hour < 18
331
+ rt.first['pre_close'].to_f
332
+ else
333
+ rt.first['price'].to_f
334
+ end
335
+ rate = frow['factor'].to_f / pre_close
336
+ result.each do |object|
337
+ %w(open high low close).each do |key|
338
+ object[key] = (object[key].to_f / rate).round(2)
339
+ end
340
+ end
341
+ result.sort_by { |object| Date.strptime(object['date'], '%F') }
342
+ else
343
+ result.each do |object|
344
+ %w(open high low close).each do |key|
345
+ object[key] = (object[key].to_f / object['factor'].to_f).round(2)
346
+ end
347
+ object.delete 'factor' if drop_factor
348
+ end
349
+ result.sort_by { |object| Date.strptime(object['date'], '%F') }
350
+ end
351
+ end
352
+
353
+ # 获取大盘指数行情
354
+ # return
355
+ # -------
356
+ # DataFrame
357
+ # code:指数代码
358
+ # name:指数名称
359
+ # change:涨跌幅
360
+ # open:开盘价
361
+ # preclose:昨日收盘价
362
+ # close:收盘价
363
+ # high:最高价
364
+ # low:最低价
365
+ # volume:成交量(手)
366
+ # amount:成交金额(亿元)
367
+ def get_index
368
+ url = format(INDEX_HQ_URL, P_TYPE['http'], DOMAINS['sinahq'])
369
+ resp = HTTParty.get(url)
370
+ string = resp.body.encode('utf-8', 'gbk')
371
+ .delete('var hq_str_sh')
372
+ .delete('var hq_str_sz')
373
+ .delete('";')
374
+ .delete('"')
375
+ .tr!('=', ',')
376
+ csv = CSV.new(string)
377
+ result = []
378
+ headers = INDEX_HEADER.split(',')
379
+ csv.each do |row|
380
+ object = {}
381
+ row.each_with_index do |value, index|
382
+ next unless INDEX_COLS.include? headers[index]
383
+ object[headers[index]] = value
384
+ end
385
+ object['change'] = ((object['close'].to_f / object['preclose'].to_f - 1) * 100).round(2)
386
+ object['amount'] = (object['amount'].to_f / 100_000_000).round(4)
387
+ result << object
388
+ end
389
+ result
390
+ end
391
+
392
+ def get_hists(symbols, start_date: '', end_date: '', ktype: 'D')
393
+ if symbols.respond_to? :each
394
+ result = []
395
+ symbols.each do |symbol|
396
+ data = get_hist_data(symbol, start_date: start_date,
397
+ end_date: end_date,
398
+ ktype: ktype)
399
+ data.map { |object| object['code'] = symbol }
400
+ result.concat data
401
+ end
402
+ result
403
+ else
404
+ nil
405
+ end
406
+ end
407
+
408
+ protected
409
+
410
+ def _parse_fq_factor(code, start_date, end_date)
411
+ symbol = _code_to_symbol(code)
412
+ url = format(HIST_FQ_FACTOR_URL, P_TYPE['http'], DOMAINS['vsf'],
413
+ symbol)
414
+ resp = HTTParty.get(url)
415
+ string = resp.body[1..-2].gsub('{_', '{"')
416
+ .gsub!('total', '"total"')
417
+ .gsub!('data', '"data"')
418
+ .gsub!(':"', '":"')
419
+ .gsub!('",_', '","')
420
+ .tr!('_', '-')
421
+ json = JSON.parse(string)
422
+ result = []
423
+ json['data'].each_pair do |key, value|
424
+ result << { 'date' => key, 'factor' => value.to_f }
425
+ end
426
+ result.uniq { |object| object['date'] }
427
+ end
428
+
429
+ def _parse_fq_data(url, index)
430
+ html = Nokogiri::HTML(open(url), nil, 'gbk')
431
+ columns = index ? HIST_FQ_COLS[0..7] : HIST_FQ_COLS
432
+ result = []
433
+ html.css('table#FundHoldSharesTable tr').drop(2).each do |tr|
434
+ object = {}
435
+ tr.css('td').each_with_index do |td, i|
436
+ next if columns[i].nil?
437
+ object[columns[i]] = td.text.strip
438
+ end
439
+ result << object
440
+ end
441
+ result
442
+ end
443
+
444
+ def _get_index_url(index, code, qt)
445
+ if index
446
+ format(HIST_INDEX_URL, P_TYPE['http'], DOMAINS['vsf'], code, qt[0],
447
+ qt[1])
448
+ else
449
+ format(HIST_FQ_URL, P_TYPE['http'], DOMAINS['vsf'], code, qt[0],
450
+ qt[1])
451
+ end
452
+ end
453
+
454
+ def _today_ticks(symbol, tdate, pageNo, ticks)
455
+ url = format(TODAY_TICKS_URL, P_TYPE['http'], DOMAINS['vsf'], PAGES['t_ticks'], symbol, tdate, pageNo)
456
+ doc = Nokogiri::HTML(open(url), nil, 'gbk')
457
+ doc.css('table#datatbl > tbody > tr').each do |tr|
458
+ items = []
459
+ tr.children.each do |td|
460
+ items << td.content.gsub(/\s+/, '').gsub('--', '0').gsub('%', '')
461
+ end
462
+ ticks << Hash[TODAY_TICK_COLUMNS.zip(items)] unless items.empty?
463
+ end
464
+ end
465
+ # '''
466
+ # 处理当日行情分页数据,格式为json
467
+ # Parameters
468
+ # ------
469
+ # pageNum:页码
470
+ # return
471
+ # -------
472
+ # DataFrame 当日所有股票交易数据(DataFrame)
473
+ # '''
474
+ def _parsing_dayprice_json(pageNum = 1)
475
+ _write_console
476
+ url = format(SINA_DAY_PRICE_URL, P_TYPE['http'], DOMAINS['vsf'], PAGES['jv'], pageNum)
477
+
478
+ resp = HTTParty.get(url)
479
+ if resp.code.to_s == '200'
480
+ val = resp.body.encode('utf-8', 'gbk')
481
+ return nil if val == 'null'
482
+ hs = eval(val)
483
+ cols = DAY_TRADING_COLUMNS.clone
484
+ cols.delete('symbol')
485
+ hs.map { |x| t = {}; cols.each { |c| t[c.to_sym] = x[c.to_sym] }; t }
486
+
487
+ else
488
+ nil
489
+ end
490
+ end
491
+
492
+ def code_to_symbol(code)
493
+ return INDEX_LIST[code] if INDEX_LABELS.include? code
494
+ return '' if code.length != 6
495
+ return "sh#{code}" if %w(5 6 9).include? code[0]
496
+ return "sz#{code}"
497
+ end
498
+
499
+ def _random(n = 13)
500
+ start_int = 10 ** (n - 1)
501
+ end_int = (10 ** n) -1
502
+ rand(start_int..end_int).to_s
503
+ end
504
+
505
+ module_function :get_hist_data, :get_tick_data, :get_sina_dd,
506
+ :get_today_ticks, :get_today_all, :_today_ticks,
507
+ :_parsing_dayprice_json, :get_realtime_quotes,
508
+ :_random, :code_to_symbol, :get_h_data, :_parse_fq_factor,
509
+ :_get_index_url, :_parse_fq_data, :get_index, :get_hists
510
+ end
511
+ end
512
+
513
+ end