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,165 @@
1
+ require 'tushare/util'
2
+
3
+ module Tushare
4
+ module Stock
5
+ # 新闻事件数据接口
6
+ module NewsEvent
7
+ extend Tushare::Util
8
+
9
+ # 获取即时财经新闻
10
+
11
+ # Parameters
12
+ # --------
13
+ # top:数值,显示最新消息的条数,默认为80条
14
+ # show_content:是否显示新闻内容,默认False
15
+
16
+ # Return
17
+ # --------
18
+ # DataFrame
19
+ # classify :新闻类别
20
+ # title :新闻标题
21
+ # time :发布时间
22
+ # url :新闻链接
23
+ # content:新闻内容(在show_content为True的情况下出现)
24
+ def latest_news(top = PAGE_NUM[2], show_content = false)
25
+ url = format(LATEST_URL, P_TYPE['http'], DOMAINS['sina'],
26
+ PAGES['lnews'], top, _random)
27
+ resp = HTTParty.get(url)
28
+ events = eval(resp.body.encode('utf-8', 'gbk').sub('var ', '')
29
+ .delete(' '))[:list]
30
+ result = []
31
+ events.each do |event|
32
+ object = {}
33
+ object['classify'] = event[:channel][:title]
34
+ object['title'] = event[:title]
35
+ object['url'] = event[:url]
36
+ object['time'] = Time.at(event[:time]).strftime('%m-%d %H:%M')
37
+ object['content'] = latest_content(object['url']) if show_content
38
+ result << object
39
+ end
40
+ result
41
+ end
42
+
43
+ # 个股信息地雷
44
+ # Parameters
45
+ # --------
46
+ # code:股票代码
47
+ # date:信息公布日期
48
+
49
+ # Return
50
+ # --------
51
+ # DataFrame,属性列表:
52
+ # title:信息标题
53
+ # type:信息类型
54
+ # date:公告日期
55
+ # url:信息内容URL
56
+ def notices(code, date = nil)
57
+ return nil if code.nil?
58
+ symbol = code[0] == '6' ? "sh#{code}" : "sz#{code}"
59
+ url = format(NOTICE_INFO_URL, P_TYPE['http'], DOMAINS['vsf'],
60
+ PAGES['ntinfo'], symbol)
61
+ url = "#{url}&gg_date=#{date}" if date
62
+ doc = Nokogiri::HTML(open(url), nil, 'gbk')
63
+ rows = doc.css('table.body_table tbody tr')
64
+ result = []
65
+ rows.each do |row|
66
+ object = {}
67
+ a = row.css('th a')[0]
68
+ tds = row.css('td')
69
+ object['title'] = a.content
70
+ object['type'] = tds[0].content
71
+ object['date'] = tds[1].content
72
+ object['url'] = "#{P_TYPE['http']}#{DOMAINS['vsf']}#{a.attr('href')}"
73
+ result << object
74
+ end
75
+ result
76
+ end
77
+
78
+ # 获取信息地雷内容
79
+ # Parameter
80
+ # --------
81
+ # url:内容链接
82
+
83
+ # Return
84
+ # --------
85
+ # string:信息内容
86
+ def notice_content(url)
87
+ doc = Nokogiri::HTML(open(url))
88
+ doc.css('div#content pre')[0].content.strip
89
+ end
90
+
91
+ # 获取sina财经股吧首页的重点消息
92
+ # Parameter
93
+ # --------
94
+ # show_content:是否显示内容,默认False
95
+
96
+ # Return
97
+ # --------
98
+ # DataFrame
99
+ # title, 消息标题
100
+ # content, 消息内容(show_content=True的情况下)
101
+ # ptime, 发布时间
102
+ # rcounts,阅读次数
103
+ def guba_sina(show_content = false)
104
+ url = format(GUBA_SINA_URL, P_TYPE['http'], DOMAINS['sina'])
105
+ doc = Nokogiri::HTML(open(url), nil, 'gbk')
106
+ res = doc.css('ul.list_05 li')
107
+ heads = doc.css('div.tit_04')
108
+ result = []
109
+ heads.each do |head|
110
+ object = {}
111
+ link = head.css('a').first
112
+ object[:title] = link.content
113
+ object[:url] = link.attr('href')
114
+ object.merge!(_guba_content(object[:url]))
115
+ object.delete(:content) unless show_content
116
+ result << object
117
+ end
118
+ res.each do |row|
119
+ object = {}
120
+ link = row.css('a')[1]
121
+ object[:title] = link.text
122
+ object[:url] = link.attr('href')
123
+ object.merge!(_guba_content(object[:url]))
124
+ object.delete(:content) unless show_content
125
+ result << object
126
+ end
127
+
128
+ result
129
+ end
130
+
131
+ private
132
+
133
+ def _guba_content(url)
134
+ doc = Nokogiri::HTML(open(url), nil, 'gbk')
135
+ content = doc.css('div.ilt_p p').text
136
+ ptime = doc.css('div.fl_left.iltp_time span').text
137
+ rcounts_text = doc.css('div.fl_right.iltp_span span')[1].text
138
+ rcounts = rcounts_text.gsub(/\D/, '')
139
+ { content: content, ptime: ptime, rcounts: rcounts }
140
+ end
141
+
142
+ # 获取即时财经新闻内容
143
+ # Parameter
144
+ # --------
145
+ # url:新闻链接
146
+
147
+ # Return
148
+ # --------
149
+ # string:返回新闻的文字内容
150
+ def latest_content(url)
151
+ doc = Nokogiri::HTML(open(url))
152
+ doc.css('div#artibody p').text
153
+ end
154
+
155
+ def _random(n = 16)
156
+ start_point = 10 ** (n - 1)
157
+ end_point = (10 ** n) - 1
158
+ rand(start_point..end_point).to_s
159
+ end
160
+
161
+ module_function :latest_news, :notices, :guba_sina, :_guba_content,
162
+ :latest_content, :_random
163
+ end
164
+ end
165
+ end
@@ -0,0 +1,473 @@
1
+ require 'tushare/util'
2
+
3
+ module Tushare
4
+ module Stock
5
+ # 投资参考数据接口
6
+ module Reference
7
+ extend Tushare::Util
8
+
9
+ # 获取分配预案数据
10
+ # Parameters
11
+ # year:年份
12
+ # start_page: 开始页数
13
+
14
+ # returns
15
+ # code:股票代码
16
+ # name:股票名称
17
+ # year:分配年份
18
+ # report_date:公布日期
19
+ # divi:分红金额(每10股)
20
+ # shares:转增和送股数(每10股)
21
+ def profit_data(year = Time.now.year, start_page = 0)
22
+ doc_generator = lambda do |p|
23
+ url = format(DP_163_URL, P_TYPE['http'], DOMAINS['163'],
24
+ PAGES['163dp'], year, p)
25
+ Nokogiri.HTML(open(url))
26
+ end
27
+ row_finder = lambda do |doc|
28
+ doc.css('div.fn_rp_list table > tr')
29
+ end
30
+ row_processor = lambda do |row|
31
+ row.drop(1).map { |item| item.content.strip }
32
+ end
33
+ last_page_guard = lambda do |doc|
34
+ last_element = doc.css('div.mod_pages > :last-child').first
35
+ last_element.name == 'span'
36
+ end
37
+ get_data(0, DP_163_COLS, doc_generator, row_finder,
38
+ row_processor, last_page_guard)
39
+ end
40
+
41
+ # 获取业绩预告数据
42
+ # Parameters
43
+ # --------
44
+ # year:int 年度 e.g:2014
45
+ # quarter:int 季度 :1、2、3、4,只能输入这4个季度
46
+ # 说明:由于是从网站获取的数据,需要一页页抓取,速度取决于您当前网络速度
47
+
48
+ # Return
49
+ # --------
50
+ # DataFrame
51
+ # code,代码
52
+ # name,名称
53
+ # type,业绩变动类型【预增、预亏等】
54
+ # report_date,发布日期
55
+ # pre_eps,上年同期每股收益
56
+ # range,业绩变动范围
57
+ def forecast_data(year, quarter)
58
+ check_year(year)
59
+ check_quarter(quarter)
60
+ doc_generator = lambda do |p|
61
+ url = format(FORECAST_URL, P_TYPE['http'], DOMAINS['vsf'],
62
+ PAGES['fd'], year, quarter, p, PAGE_NUM[1])
63
+ Nokogiri.HTML(open(url), nil, 'gbk')
64
+ end
65
+ row_finder = lambda do |doc|
66
+ doc.css('table.list_table > tr')
67
+ end
68
+ row_processor = lambda do |row|
69
+ row.to_a.values_at(0, 1, 2, 3, 6, 7).map { |item| item.content.strip }
70
+ end
71
+ last_page_guard = lambda do |doc|
72
+ next_page = doc.css('div.pages > a:last').css('a.nolink')
73
+ !next_page.empty?
74
+ end
75
+ get_data(1, FORECAST_COLS, doc_generator, row_finder,
76
+ row_processor, last_page_guard)
77
+ end
78
+
79
+ # 获取限售股解禁数据
80
+ # Parameters
81
+ # --------
82
+ # year:年份,默认为当前年
83
+ # month:解禁月份,默认为当前月
84
+ # retry_count : int, 默认 3
85
+ # 如遇网络等问题重复执行的次数
86
+ # pause : int, 默认 0
87
+ # 重复请求数据过程中暂停的秒数,防止请求间隔时间太短出现的问题
88
+
89
+ # Return
90
+ # ------
91
+ # DataFrame
92
+ # code:股票代码
93
+ # name:名称
94
+ # date:解禁日期
95
+ # count:解禁数量(万股)
96
+ # ratio:占总盘比率
97
+ def xsg_data(year = Time.now.year, month = Time.now.month)
98
+ url = format(XSG_URL, P_TYPE['http'], DOMAINS['em'], PAGES['emxsg'], year,
99
+ month)
100
+ lines = HTTParty.get(url).slice(3..-3)
101
+ lines.split('","').map do |row|
102
+ arr = row.split(',').values_at(1, 3, 4, 5, 6)
103
+ arr[3] = (arr[3].to_f / 10_000).round(2)
104
+ arr[4] = (arr[4].to_f * 100).round(2)
105
+ object = {}
106
+ XSG_COLS.each_with_index do |key, index|
107
+ object[key] = arr[index]
108
+ end
109
+ object
110
+ end
111
+ end
112
+
113
+ # 获取基金持股数据
114
+ # Parameters
115
+ # --------
116
+ # year:年份e.g 2014
117
+ # quarter:季度(只能输入1,2,3,4这个四个数字)
118
+
119
+ # Return
120
+ # ------
121
+ # DataFrame
122
+ # code:股票代码
123
+ # name:名称
124
+ # date:报告日期
125
+ # nums:基金家数
126
+ # nlast:与上期相比(增加或减少了)
127
+ # count:基金持股数(万股)
128
+ # clast:与上期相比
129
+ # amount:基金持股市值
130
+ # ratio:占流通盘比率
131
+ def fund_holdings(year, quarter)
132
+ check_year(year)
133
+ check_quarter(quarter)
134
+ start_date, end_date = QUARTS_DIC[quarter.to_s]
135
+ start_date = format(start_date % (quarter == 1 && year - 1 || year))
136
+ end_date = format(end_date % year)
137
+ url_generator = lambda do |page|
138
+ format(FUND_HOLDS_URL, P_TYPE['http'], DOMAINS['163'], PAGES['163fh'],
139
+ PAGES['163fh'], page, start_date, end_date, rand(5))
140
+ end
141
+ resp = HTTParty.get(url_generator.call(0))
142
+ page_count = JSON.parse(resp)['pagecount']
143
+ result = []
144
+ 1.upto(page_count) do |page|
145
+ _write_console
146
+ resp = HTTParty.get url_generator.call(page)
147
+ data = JSON.parse(resp)['list']
148
+ data.each do |datum|
149
+ object = {}
150
+ object['code'] = datum['SYMBOL']
151
+ object['name'] = datum['SNAME']
152
+ object['date'] = datum['REPORTDATE']
153
+ object['nums'] = datum['SHULIANG']
154
+ object['nlast'] = datum['SHULIANGBIJIAO']
155
+ object['count'] = (datum['GUSHU'].to_f / 10_000).round(2)
156
+ object['clast'] = (datum['GUSHUBIJIAO'].to_f / 10_000).round(2)
157
+ object['amount'] = (datum['SHIZHI'].to_f / 10_000).round(2)
158
+ object['ratio'] = (datum['SCSTC27'].to_f * 100).round(2)
159
+ result << object
160
+ end
161
+ end
162
+ result
163
+ end
164
+
165
+ # 获取新股上市数据
166
+ # Parameters
167
+ # --------
168
+ # retry_count : int, 默认 3
169
+ # 如遇网络等问题重复执行的次数
170
+ # pause : int, 默认 0
171
+ # 重复请求数据过程中暂停的秒数,防止请求间隔时间太短出现的问题
172
+
173
+ # Return
174
+ # ------
175
+ # DataFrame
176
+ # code:股票代码
177
+ # name:名称
178
+ # ipo_date:上网发行日期
179
+ # issue_date:上市日期
180
+ # amount:发行数量(万股)
181
+ # markets:上网发行数量(万股)
182
+ # price:发行价格(元)
183
+ # pe:发行市盈率
184
+ # limit:个人申购上限(万股)
185
+ # funds:募集资金(亿元)
186
+ # ballot:网上中签率(%)
187
+ def new_stocks
188
+ url = format(NEW_STOCKS_URL, P_TYPE['http'], DOMAINS['vsf'],
189
+ PAGES['newstock'], 1)
190
+ doc_generator = lambda do |p|
191
+ url = format(NEW_STOCKS_URL, P_TYPE['http'], DOMAINS['vsf'],
192
+ PAGES['newstock'], p)
193
+ Nokogiri.HTML open(url), nil, 'gbk'
194
+ end
195
+ row_finder = lambda do |doc|
196
+ doc.css('table#NewStockTable > tr').drop(2)
197
+ end
198
+ row_processor = lambda do |row|
199
+ arr = row.to_a
200
+ arr.delete_at 1
201
+ arr.map(&:content).map(&:strip)
202
+ end
203
+ last_page_guard = lambda do |doc|
204
+ doc.css('table.table2 tr:first td:first a').last.text != '尾页'
205
+ end
206
+ get_data(1, NEW_STOCKS_COLS, doc_generator, row_finder,
207
+ row_processor, last_page_guard)
208
+ end
209
+
210
+ # 获取沪市融资融券数据列表
211
+ # Parameters
212
+ # --------
213
+ # start:string
214
+ # 开始日期 format:YYYY-MM-DD 为空时取去年今日
215
+ # end:string
216
+ # 结束日期 format:YYYY-MM-DD 为空时取当前日期
217
+ # retry_count : int, 默认 3
218
+ # 如遇网络等问题重复执行的次数
219
+ # pause : int, 默认 0
220
+ # 重复请求数据过程中暂停的秒数,防止请求间隔时间太短出现的问题
221
+
222
+ # Return
223
+ # ------
224
+ # DataFrame
225
+ # opDate:信用交易日期
226
+ # rzye:本日融资余额(元)
227
+ # rzmre: 本日融资买入额(元)
228
+ # rqyl: 本日融券余量
229
+ # rqylje: 本日融券余量金额(元)
230
+ # rqmcl: 本日融券卖出量
231
+ # rzrqjyzl:本日融资融券余额(元)
232
+ def sh_margins(start_date = nil, end_date = nil)
233
+ start_date ||= Date.today.prev_year.strftime('%Y-%m-%d')
234
+ end_date ||= Date.today.strftime('%Y-%m-%d')
235
+ start_date = start_date.delete '-'
236
+ end_date = end_date.delete '-'
237
+ page_no = ''
238
+ begin_page = ''
239
+ end_page = ''
240
+ result = []
241
+
242
+ loop do
243
+ tail = format(MAR_SH_HZ_TAIL_URL, page_no, begin_page, end_page)
244
+ if page_no == ''
245
+ page_no = 6
246
+ tail = ''
247
+ else
248
+ page_no += 5
249
+ end
250
+ begin_page = page_no
251
+ end_page = page_no + 4
252
+ url = format(MAR_SH_HZ_URL, P_TYPE['http'], DOMAINS['sseq'],
253
+ PAGES['qmd'], _random(5), start_date, end_date, tail,
254
+ _random)
255
+ ref = format(MAR_SH_HZ_REF_URL, P_TYPE['http'], DOMAINS['sse'])
256
+ resp = HTTParty.get(
257
+ url,
258
+ headers: { 'Referer' => ref },
259
+ cookies: MAR_SH_COOKIES
260
+ )
261
+ json = JSON.parse(resp.body.sub(/jsonpCallback\d+\(/, '')[0..-2])['pageHelp']
262
+
263
+ json['data'].each do |datum|
264
+ object = {}
265
+ MAR_SH_HZ_COLS.each do |key|
266
+ if key == 'opDate'
267
+ date = datum[key]
268
+ object[key] = format('%s-%s-%s', date[0..3], date[4..5], date[6..7])
269
+ else
270
+ object[key] = datum[key]
271
+ end
272
+ end
273
+ result << object
274
+ end
275
+
276
+ page_count = json['pageCount']
277
+ data_page = page_count % 5 > 0 ? page_count / 5 + 1 : page_count / 5
278
+ break unless begin_page < data_page * 5
279
+ end
280
+ result
281
+ end
282
+
283
+ # 获取沪市融资融券明细列表
284
+ # Parameters
285
+ # --------
286
+ # date:string
287
+ # 明细数据日期 format:YYYY-MM-DD 默认为空''
288
+ # symbol:string
289
+ # 标的代码,6位数字e.g.600848,默认为空
290
+ # start:string
291
+ # 开始日期 format:YYYY-MM-DD 默认为空''
292
+ # end:string
293
+ # 结束日期 format:YYYY-MM-DD 默认为空''
294
+ # retry_count : int, 默认 3
295
+ # 如遇网络等问题重复执行的次数
296
+ # pause : int, 默认 0
297
+ # 重复请求数据过程中暂停的秒数,防止请求间隔时间太短出现的问题
298
+
299
+ # Return
300
+ # ------
301
+ # DataFrame
302
+ # opDate:信用交易日期
303
+ # stockCode:标的证券代码
304
+ # securityAbbr:标的证券简称
305
+ # rzye:本日融资余额(元)
306
+ # rzmre: 本日融资买入额(元)
307
+ # rzche:本日融资偿还额(元)
308
+ # rqyl: 本日融券余量
309
+ # rqmcl: 本日融券卖出量
310
+ # rqchl: 本日融券偿还量
311
+ def sh_margin_details(date = '', symbol = '', start_date = '', end_date = '')
312
+ date = date == '' ? date : date.delete('-')
313
+ start_date = start_date == '' ? start_date : start_date.delete('-')
314
+ end_date = end_date == '' ? end_date : end_date.delete('-')
315
+ date = '' if start_date != '' && end_date != ''
316
+ page_no = ''
317
+ begin_page = ''
318
+ end_page = ''
319
+ result = []
320
+
321
+ loop do
322
+ tail = format(MAR_SH_HZ_TAIL_URL, page_no, begin_page, end_page)
323
+ if page_no == ''
324
+ page_no = 6
325
+ tail = ''
326
+ else
327
+ page_no += 5
328
+ end
329
+ begin_page = page_no
330
+ end_page = page_no + 4
331
+ url = format(MAR_SH_MX_URL, P_TYPE['http'], DOMAINS['sseq'],
332
+ PAGES['qmd'], _random(5), date, symbol, start_date,
333
+ end_date, tail, _random)
334
+ ref = format(MAR_SH_HZ_REF_URL, P_TYPE['http'], DOMAINS['sse'])
335
+ resp = HTTParty.get(
336
+ url,
337
+ headers: { 'Referer' => ref },
338
+ cookies: MAR_SH_COOKIES
339
+ )
340
+ json = JSON.parse(resp.body.sub(/jsonpCallback\d+\(/, '')[0..-2])['pageHelp']
341
+
342
+ json['data'].each do |datum|
343
+ object = {}
344
+ MAR_SH_MX_COLS.each do |key|
345
+ if key == 'opDate'
346
+ date = datum[key]
347
+ object[key] = format('%s-%s-%s', date[0..3], date[4..5], date[6..7])
348
+ else
349
+ object[key] = datum[key]
350
+ end
351
+ end
352
+ result << object
353
+ end
354
+
355
+ page_count = json['pageCount']
356
+ data_page = page_count % 5 > 0 ? page_count / 5 + 1 : page_count / 5
357
+ p result.size
358
+ break unless begin_page < data_page * 5
359
+ end
360
+ result
361
+ end
362
+
363
+ def sz_margins(start_date = nil, end_date = nil)
364
+ if start_date.nil? && end_date.nil?
365
+ start_date ||= Date.today.prev_day(7)
366
+ end_date ||= Date.today
367
+ end
368
+ raise MAR_SZ_HZ_MSG2 if start_date.nil? || end_date.nil?
369
+ range = (start_date..end_date).to_a
370
+ raise MAR_SZ_HZ_MSG if range.size > 261
371
+ _write_head
372
+ result = []
373
+ range.each do |date|
374
+ _write_console
375
+ url = format(MAR_SZ_HZ_URL, P_TYPE['http'], DOMAINS['szse'],
376
+ PAGES['szsefc'], date.strftime('%Y-%m-%d'))
377
+ doc = Nokogiri::HTML(open(url), nil, 'gbk')
378
+ begin
379
+ row = doc.css('tr')[1].css('td')
380
+ rescue
381
+ next
382
+ end
383
+ object = { 'opDate' => date}
384
+ MAR_SZ_HZ_COLS.each_with_index do |key, index|
385
+ object[key] = row[index].content.strip
386
+ end
387
+ result << object
388
+ end
389
+ puts "\n"
390
+ result
391
+ end
392
+
393
+ # 获取深市融资融券明细列表
394
+ # Parameters
395
+ # --------
396
+ # date:string
397
+ # 明细数据日期 format:YYYY-MM-DD 默认为空''
398
+ # retry_count : int, 默认 3
399
+ # 如遇网络等问题重复执行的次数
400
+ # pause : int, 默认 0
401
+ # 重复请求数据过程中暂停的秒数,防止请求间隔时间太短出现的问题
402
+
403
+ # Return
404
+ # ------
405
+ # DataFrame
406
+ # opDate:信用交易日期
407
+ # stockCode:标的证券代码
408
+ # securityAbbr:标的证券简称
409
+ # rzmre: 融资买入额(元)
410
+ # rzye:融资余额(元)
411
+ # rqmcl: 融券卖出量
412
+ # rqyl: 融券余量
413
+ # rqye: 融券余量(元)
414
+ # rzrqye:融资融券余额(元)
415
+ def sz_margin_details(date = nil)
416
+ date ||= Date.today.prev_day.strftime('%Y-%m-%d')
417
+ url = format(MAR_SZ_MX_URL, P_TYPE['http'], DOMAINS['szse'],
418
+ PAGES['szsefc'], date)
419
+ doc = Nokogiri::HTML(open(url), nil, 'gbk')
420
+ rows = doc.css('tr')[1..-2]
421
+ result = []
422
+ rows.each do |row|
423
+ object = { 'opDate' => date }
424
+ tds = row.css('td')
425
+ MAR_SZ_MX_COLS.each_with_index do |key, index|
426
+ object[key] = tds[index].content.strip
427
+ end
428
+ result << object
429
+ end
430
+ result
431
+ end
432
+
433
+ private
434
+
435
+ def get_data(start_page, headers, doc_generator, row_finder,
436
+ row_processor, last_page_guard)
437
+ _write_head
438
+ [].concat process_data(start_page, headers, doc_generator,
439
+ row_finder, row_processor, last_page_guard)
440
+ end
441
+
442
+ def process_data(start_page, headers, doc_generator, row_finder,
443
+ row_processor, last_page_guard)
444
+ result = []
445
+ page = start_page
446
+ loop do
447
+ _write_console
448
+ doc = doc_generator.call(page)
449
+ row_finder.call(doc).each do |tr|
450
+ object = {}
451
+ row_processor.call(tr.css('td')).each_with_index do |item, index|
452
+ object[headers[index]] = item if headers[index]
453
+ end
454
+ result << object
455
+ end
456
+ break if last_page_guard.call(doc)
457
+ page += 1
458
+ end
459
+ result
460
+ end
461
+
462
+ def _random(n = 13)
463
+ start_int = 10**(n-1)
464
+ end_int = (10**n) - 1
465
+ rand(start_int..end_int).to_s
466
+ end
467
+
468
+ module_function :profit_data, :forecast_data, :fund_holdings, :new_stocks,
469
+ :sh_margins, :sh_margin_details, :sz_margins, :xsg_data,
470
+ :sz_margin_details, :get_data, :process_data, :_random
471
+ end
472
+ end
473
+ end