unageanu-clickclient_scrap 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.
Files changed (4) hide show
  1. data/ChangeLog +0 -0
  2. data/README +18 -0
  3. data/lib/clickclient_scrap.rb +273 -0
  4. metadata +56 -0
data/ChangeLog ADDED
File without changes
data/README ADDED
@@ -0,0 +1,18 @@
1
+
2
+ ==クリック証券Fxクライアントライブラリ
3
+
4
+ クリック証券の携帯向けサイト「モバトレ君」にアクセスし、
5
+ スクレイピングでレート情報の取得や取り引きを行うライブラリです。
6
+
7
+ ===実装済みの機能
8
+ - ログイン
9
+ - ログアウト
10
+ - レート一覧の取得
11
+
12
+ ===注意事項
13
+ - スクレイピングによるアクセスのため、Webサイトの仕様変更等により
14
+ 突然動作しなくなる可能性があります。
15
+
16
+ ===免責
17
+ - 本ライブラリの利用は自己責任でお願いします。
18
+ - ライブラリの不備・不具合等によるあらゆる損害について、作成者は責任を負いません。
@@ -0,0 +1,273 @@
1
+ begin
2
+ require 'rubygems'
3
+ rescue LoadError
4
+ end
5
+ require 'httpclient'
6
+ require 'rexml/document'
7
+ require 'date'
8
+ require 'kconv'
9
+
10
+ #
11
+ #=== クリック証券アクセスクライアント
12
+ #
13
+ #*Version*:: -
14
+ #*License*:: Ruby ライセンスに準拠
15
+ #
16
+ #クリック証券を利用するためのクライアントライブラリです。携帯向けサイトのスクレイピングにより以下の機能を提供します。
17
+ #- 外為証拠金取引(FX)取引
18
+ #
19
+ #====依存モジュール
20
+ #「{httpclient}[http://dev.ctor.org/http-access2]」を利用しています。以下のコマンドを実行してインストールしてください。
21
+ #
22
+ # gem install httpclient --source http://dev.ctor.org/download/
23
+ #
24
+ #====基本的な使い方
25
+ #
26
+ # require 'clickclient'
27
+ #
28
+ # c = ClickClient::Client.new
29
+ # # c = ClickClient::Client.new https://<プロキシホスト>:<プロキシポート> # プロキシを利用する場合
30
+ # c.fx_session( "<ユーザー名>", "<パスワード>" ) { | fx_session |
31
+ # # 通貨ペア一覧取得
32
+ # list = fx_session.list_currency_pairs
33
+ # puts list
34
+ # }
35
+ #
36
+ #====免責
37
+ #- 本ライブラリの利用は自己責任でお願いします。
38
+ #- ライブラリの不備・不具合等によるあらゆる損害について、作成者は責任を負いません。
39
+ #
40
+ module ClickClient
41
+
42
+ # クライアント
43
+ class Client
44
+ # ホスト名
45
+ DEFAULT_HOST_NAME = "https://sec-sso.click-sec.com/mf"
46
+
47
+ # 通貨ペア: 米ドル-円
48
+ USDJPY = :USDJPY
49
+ # 通貨ペア: ユーロ-円
50
+ EURJPY = :EURJPY
51
+ # 通貨ペア: イギリスポンド-円
52
+ GBPJPY = :GBPJPY
53
+ # 通貨ペア: 豪ドル-円
54
+ AUDJPY = :AUDJPY
55
+ # 通貨ペア: ニュージーランドドル-円
56
+ NZDJPY = :NZDJPY
57
+ # 通貨ペア: カナダドル-円
58
+ CADJPY = :CADJPY
59
+ # 通貨ペア: スイスフラン-円
60
+ CHFJPY = :CHFJPY
61
+ # 通貨ペア: 南アランド-円
62
+ ZARJPY = :ZARJPY
63
+ # 通貨ペア: ユーロ-米ドル
64
+ EURUSD = :EURUSD
65
+ # 通貨ペア: イギリスポンド-米ドル
66
+ GBPUSD = :GBPUSD
67
+ # 通貨ペア: 豪ドル-米ドル
68
+ AUDUSD = :AUDUSD
69
+ # 通貨ペア: ユーロ-スイスフラン
70
+ EURCHF = :EURCHF
71
+ # 通貨ペア: イギリスポンド-スイスフラン
72
+ GBPCHF = :GBPCHF
73
+ # 通貨ペア: 米ドル-スイスフラン
74
+ USDCHF = :USDCHF
75
+
76
+ # 売買区分: 買い
77
+ BUY = 0
78
+ # 売買区分: 売り
79
+ SELL = 1
80
+
81
+ # 注文タイプ: 通常
82
+ ORDER_TYPE_NORMAL = 0
83
+ # 注文タイプ: IFD
84
+ ORDER_TYPE_IFD = 1
85
+ # 注文タイプ: OCO
86
+ ORDER_TYPE_OCO = 2
87
+ # 注文タイプ: IFD-OCO
88
+ ORDER_TYPE_IFD_OCO = 3
89
+
90
+
91
+ #
92
+ #===コンストラクタ
93
+ #
94
+ #*proxy*:: プロキシホストを利用する場合、そのホスト名とパスを指定します。
95
+ # 例) https://proxyhost.com:80
96
+ #
97
+ def initialize( proxy=nil )
98
+ @client = HTTPClient.new( proxy, "Mozilla/5.0")
99
+ #@client.debug_dev=STDOUT
100
+ @client.set_cookie_store("cookie.dat")
101
+ @host_name = DEFAULT_HOST_NAME
102
+ end
103
+
104
+ #ログインし、セッションを開始します。
105
+ #-ブロックを指定した場合、引数としてセッションを指定してブロックを実行します。ブロック実行後、ログアウトします。
106
+ #-そうでない場合、セッションを返却します。この場合、ClickClient::FX::FxSession#logoutを実行しログアウトしてください。
107
+ #
108
+ #戻り値:: ClickClient::FX::CurrencyPairの配列。
109
+ #戻り値:: ClickClient::FX::CurrencyPairの配列。
110
+ def fx_session( userid, password, &block )
111
+ @client.get("#{@host_name}/" )
112
+ result = @client.post_content("#{@host_name}/sso-redirect", {
113
+ "j_username"=>userid,
114
+ "j_password"=>password,
115
+ "LoginForm"=>"ログイン".tosjis,
116
+ "s"=>"02",
117
+ "p"=>"80"
118
+ })
119
+ if result.toutf8 =~ /<META HTTP-EQUIV="REFRESH" CONTENT="0;URL=([^"]*)">/
120
+ uri = URI.parse( $1 )
121
+ base = "#{uri.scheme}://#{uri.host}:#{uri.port}"
122
+ result = @client.get_content($1)
123
+ commands = result.toutf8.scan( /<a[^>]*?href="([^"]*)"[^>]*>([^<]*)<\/a>/).inject({}) {|r,l|
124
+ r[l[1]] = "#{base}#{l[0]}"; r
125
+ }
126
+ session = FX::FxSession.new( @client, commands )
127
+ if block_given?
128
+ begin
129
+ yield session
130
+ ensure
131
+ session.logout
132
+ end
133
+ else
134
+ return session
135
+ end
136
+ else
137
+ error = result.toutf8 =~ /<font color="red">([^<]*)</ ? $1.strip : result
138
+ raise "login failed.detail=#{error}".toutf8
139
+ end
140
+ end
141
+
142
+ #ホスト名
143
+ attr :host_name, true
144
+ end
145
+
146
+ module FX
147
+ #=== FX取引のためのセッションクラス
148
+ #Client#fx_sessionのブロックの引数として渡されます。詳細はClient#fx_sessionを参照ください。
149
+ class FxSession
150
+
151
+ def initialize( client, commands )
152
+ @client = client
153
+ @commands = commands
154
+ end
155
+ #レート一覧を取得します。
156
+ #
157
+ #戻り値:: 通貨ペアをキーとするClickClient::FX::Rateのハッシュ。
158
+ def list_rates
159
+ result = @client.get_content( @commands["レート一覧(新規注文)"] )
160
+ @swaps = list_swaps unless @swaps
161
+ reg = />([A-Z]+\/[A-Z]+)<\/a>[^\-\.\d]*?([\d]+\.[\d]+\-[\d]+)/
162
+ return result.toutf8.scan( reg ).inject({}) {|r,l|
163
+ pair = l[0].gsub( /\//, "" ).to_sym
164
+ swap = @swaps[pair]
165
+ rate = FxSession.convert_rate l[1]
166
+ if ( rate && swap )
167
+ r[pair] = Rate.new( pair, rate[0], rate[1], swap.sell_swap, swap.buy_swap )
168
+ end
169
+ r
170
+ }
171
+ end
172
+ #12.34-35 形式の文字列をbidレート、askレートに変換する。
173
+ def self.convert_rate( str ) #:nodoc:
174
+ if str =~ /([\d]+)\.([\d]+)\-([\d]+)/
175
+ high = $1
176
+ low = $2
177
+ low2 = $3
178
+ bid = high.to_f+(low.to_f/(10**low.length))
179
+ ask_low = (low[0...low.length-low2.length] + low2).to_f
180
+ if low.to_f > ask_low
181
+ ask_low += 10**low2.length
182
+ end
183
+ ask = high.to_f+(ask_low/10**low.length)
184
+ return [bid,ask]
185
+ end
186
+ end
187
+
188
+ #スワップの一覧を取得します。
189
+ #
190
+ #戻り値:: 通貨ペアをキーとするClickClient::FX::Swapのハッシュ。
191
+ def list_swaps
192
+ result = @client.get_content( @commands["スワップ/証拠金一覧"] )
193
+ reg = /<dd>([A-Z]+\/[A-Z]+) <font[^>]*>売<\/font>[^\-\d]*?([\-\d]+)[^\-\d]*<font[^>]*>買<\/font>[^\-\d]*([\-\d]+)[^\-\d]*<\/dd>/
194
+ return result.toutf8.scan( reg ).inject({}) {|r,l|
195
+ pair = l[0].gsub( /\//, "" ).to_sym
196
+ r[pair] = Swap.new( pair, l[1].to_i, l[2].to_i ); r
197
+ }
198
+ end
199
+
200
+ #
201
+ #注文を行います。
202
+ #
203
+ #*currency_pair_code*:: 通貨ペアコード(必須)
204
+ #*sell_or_buy*:: 売買区分。ClickClient::FX::BUY,ClickClient::FX::SELLのいずれかを指定します。(必須)
205
+ #*unit*:: 取引数量(必須)
206
+ #*options*:: 注文のオプション。注文方法に応じて以下の情報を設定できます。
207
+ # - <b>通常注文</b> ※注文レートが設定されていれば通常取引となります。
208
+ # - <tt>:rate</tt> .. 注文レート(必須)
209
+ # - <tt>:execution_expression</tt> .. 執行条件。ClickClient::FX::EXECUTION_EXPRESSION_LIMIT_ORDER等を指定します(必須)
210
+ # - <tt>:expiration_type</tt> .. 有効期限。ClickClient::FX::EXPIRATION_TYPE_TODAY等を指定します(必須)
211
+ # - <tt>:expiration_date</tt> .. 有効期限が「日付指定(ClickClient::FX::EXPIRATION_TYPE_SPECIFIED)」の場合の有効期限をDateで指定します。(有効期限が「日付指定」の場合、必須)
212
+ #<b>戻り値</b>:: ClickClient::FX::OrderResult
213
+ #
214
+ def order ( currency_pair_code, sell_or_buy, unit, options={} )
215
+ result = @client.get_content( @commands["レート一覧(新規注文)"] )
216
+ if result.toutf8 =~ /<form[~>]?*action="([^"]*)"[~>]*>(.*?<select name="P001"[^>]*>(.*)<\/select>.*?<select name="P100"[^>]*>(.*)<\/select>.*)<\/form>)/m
217
+ action = $1
218
+ p001 = $3
219
+ p100 = $4
220
+ hidden = $2
221
+ # 通貨ペア
222
+ pairs = p001.scan( /<option value="([^"]+)">([A-Z]+\/[A-Z]+)/m ).inject({}) {|r,l|
223
+ pair = l[1].gsub( /\//, "" ).to_sym
224
+ r[pair] = l[0]; r
225
+ }
226
+ # 取り引き種別
227
+ type = p100.scan( /<option value="([^"]+)">([^\s]+)/m ).inject({}) {|r,l|
228
+ r[l[1]] = l[0]; r
229
+ }
230
+ # hidden
231
+ params = hidden.scan( /<input type="hidden" name="([^"]+)" value="([^"]+)">/m ).inject({}) {|r,l|
232
+ r[l[1]] = l[0]; r
233
+ }
234
+ end
235
+ # if ( options[:rate] != nil )
236
+ # if ( options[:stop_order_rate] != nil )
237
+ # # 逆指値レートが指定されていればOCO取引
238
+ # path = "/ws/fx/ocoChumon.do"
239
+ # body << "&srp=#{options[:rate].to_s}"
240
+ # body << "&grp=#{options[:stop_order_rate].to_s}"
241
+ # else
242
+ # # そうでなければ通常取引
243
+ # raise "options[:execution_expression] is required." if options[:execution_expression] == nil
244
+ # path = "/ws/fx/tsujoChumon.do"
245
+ # body << "&crp=#{options[:rate].to_s}"
246
+ # body << "&sjt=#{options[:execution_expression].to_s}"
247
+ # end
248
+ # raise "options[:expiration_type] is required." if options[:expiration_type] == nil
249
+ # body << "&bbt=#{sell_or_buy.to_s}"
250
+ # body << "&thn=#{unit.to_s}"
251
+ # body << "&dat=#{options[:expiration_type].to_s}"
252
+ # body << "&ykd=" << options[:expiration_date].strftime( "%Y%m%d%H" ) if options[:expiration_date] != nil
253
+ # end
254
+ # result = @client.post( @base_uri + path, body)
255
+ # doc = ClickClient.parse( result.content )
256
+ # return OrderResult.new( doc.root )
257
+ end
258
+
259
+ # ログアウトします。
260
+ def logout
261
+ @client.get_content( @commands["ログアウト"] )
262
+ end
263
+ end
264
+
265
+ #=== スワップ
266
+ Swap = Struct.new(:pair, :sell_swap, :buy_swap)
267
+ #=== レート
268
+ Rate = Struct.new(:pair, :bid_rate, :ask_rate, :sell_swap, :buy_swap )
269
+ end
270
+ end
271
+
272
+
273
+
metadata ADDED
@@ -0,0 +1,56 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: unageanu-clickclient_scrap
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Masaya Yamauchi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-02-13 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: y-masaya@red.hot.co.jp
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README
24
+ files:
25
+ - README
26
+ - ChangeLog
27
+ - lib/clickclient_scrap.rb
28
+ has_rdoc: true
29
+ homepage: http://github.com/unageanu/clickclient_scrap/tree/master
30
+ post_install_message:
31
+ rdoc_options:
32
+ - --main
33
+ - README
34
+ require_paths:
35
+ - lib
36
+ required_ruby_version: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: "0"
41
+ version:
42
+ required_rubygems_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: "0"
47
+ version:
48
+ requirements: []
49
+
50
+ rubyforge_project:
51
+ rubygems_version: 1.2.0
52
+ signing_key:
53
+ specification_version: 2
54
+ summary: click securities client library for ruby.
55
+ test_files: []
56
+