clickclient 0.0.1

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.
data/History.txt ADDED
@@ -0,0 +1,4 @@
1
+ == 0.0.1 2007-12-15
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
data/License.txt ADDED
@@ -0,0 +1,57 @@
1
+ Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.co.jp>.
2
+ You can redistribute it and/or modify it under either the terms of the GPL,
3
+ or the conditions below:
4
+
5
+ 1. You may make and give away verbatim copies of the source form of the
6
+ software without restriction, provided that you duplicate all of the
7
+ original copyright notices and associated disclaimers.
8
+
9
+ 2. You may modify your copy of the software in any way, provided that
10
+ you do at least ONE of the following:
11
+
12
+ a) place your modifications in the Public Domain or otherwise
13
+ make them Freely Available, such as by posting said
14
+ modifications to Usenet or an equivalent medium, or by allowing
15
+ the author to include your modifications in the software.
16
+
17
+ b) use the modified software only within your corporation or
18
+ organization.
19
+
20
+ c) rename any non-standard executables so the names do not conflict
21
+ with standard executables, which must also be provided.
22
+
23
+ d) make other distribution arrangements with the author.
24
+
25
+ 3. You may distribute the software in object code or executable
26
+ form, provided that you do at least ONE of the following:
27
+
28
+ a) distribute the executables and library files of the software,
29
+ together with instructions (in the manual page or equivalent)
30
+ on where to get the original distribution.
31
+
32
+ b) accompany the distribution with the machine-readable source of
33
+ the software.
34
+
35
+ c) give non-standard executables non-standard names, with
36
+ instructions on where to get the original software distribution.
37
+
38
+ d) make other distribution arrangements with the author.
39
+
40
+ 4. You may modify and include the part of the software into any other
41
+ software (possibly commercial). But some files in the distribution
42
+ are not written by the author, so that they are not under this terms.
43
+
44
+ They are gc.c(partly), utils.c(partly), regex.[ch], st.[ch] and some
45
+ files under the ./missing directory. See each file for the copying
46
+ condition.
47
+
48
+ 5. The scripts and library files supplied as input to or produced as
49
+ output from the software do not automatically fall under the
50
+ copyright of the software, but belong to whomever generated them,
51
+ and may be sold commercially, and may be aggregated with this
52
+ software.
53
+
54
+ 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
55
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
56
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
57
+ PURPOSE.
data/README.txt ADDED
@@ -0,0 +1,34 @@
1
+ = CLICK Client -- CLICK Securities Web Service Client Library for Ruby.
2
+
3
+ CLICK Client is a CLICK Securities Web Service Client for Ruby.
4
+ CLICK Client はクリック証券Webサービスにアクセスするためのクライアントライブラリです。
5
+ 以下の機能を提供します。
6
+
7
+ * 外為証拠金取引(FX)取引
8
+
9
+
10
+ == Dounload
11
+
12
+ CLICK Clientの最新バージョンは以下のサイトからダウンロードできます。
13
+
14
+ * http://rubyforge.org/projects/clickclient
15
+
16
+
17
+ == Installation
18
+
19
+ rubygemを使ってインストール可能です。なお、依存もジュールとして「httpclient」も必要となります。
20
+ 以下のコマンドを実行してインストールしてください。
21
+
22
+ % [sudo] gem install httpclient --source http://dev.ctor.org/download/
23
+ % [sudo] gem install clickclient
24
+
25
+
26
+ == License
27
+
28
+ Ruby ライセンスに準拠
29
+
30
+
31
+ == Disclaimer
32
+ * 本ライブラリの利用は自己責任でお願いします。
33
+ * ライブラリの不備・不具合等によるあらゆる損害について、作成者は責任を負いません。
34
+
@@ -0,0 +1,202 @@
1
+ require File.dirname(__FILE__) + '/../lib/clickclient'
2
+
3
+ require 'kconv'
4
+
5
+ #== 利用サンプル
6
+ #ローカルサーバーに接続し、結果を表示します。
7
+ c = ClickClient::Client.new
8
+
9
+ # ローカルサーバーへの接続設定
10
+ c.host_name = "http://localhost:8000"
11
+ c.fx_path = "/webservice/ws-redirect"
12
+ c.fx_session( "012345678", "sdfsdf" ) { | fx_session |
13
+
14
+ # 通貨ペア一覧取得
15
+ # 引数で取得する通貨ペアコードを配列で指定
16
+ # 指定しない場合すべての通貨ペアの情報を取得。
17
+ puts "\n--- list_currency_pairs"
18
+ list = fx_session.list_currency_pairs [GMO::FX::USDJPY, GMO::FX::EURJPY]
19
+ list.each{ |currency_pair_code, value| puts value }
20
+
21
+ # レート一覧取得
22
+ puts "\n--- list_rates"
23
+ list = fx_session.list_rates
24
+ list.each{ |currency_pair_code, value| puts value }
25
+
26
+ # 成り行き注文
27
+ puts "\n--- order - buy"
28
+ puts fx_session.order( GMO::FX::USDJPY, GMO::FX::BUY, 2 )
29
+ puts "\n--- order - sell"
30
+ result = fx_session.order( GMO::FX::USDJPY, GMO::FX::SELL, 1, {
31
+ :slippage=>99,
32
+ :slippage_base_rate=>list[GMO::FX::USDJPY].bid_rate
33
+ })
34
+ puts result
35
+
36
+ # 成り行き決済注文
37
+ puts "\n--- settle"
38
+ puts fx_session.settle( result.order_no, 1 )
39
+ puts fx_session.settle( result.order_no, 2, {
40
+ :slippage=>99,
41
+ :slippage_base_rate=>list[GMO::FX::USDJPY].bid_rate
42
+ })
43
+
44
+ # 通常注文
45
+ puts "\n--- order - basic sell"
46
+ result = fx_session.order( GMO::FX::USDJPY, GMO::FX::SELL, 1, {
47
+ :rate=>145.19,
48
+ :execution_expression=>GMO::FX::EXECUTION_EXPRESSION_LIMIT_ORDER,
49
+ :expiration_type=>GMO::FX::EXPIRATION_TYPE_SPECIFIED,
50
+ :expiration_date=>DateTime.new( 2007, 11, 5, 0 )
51
+ })
52
+ puts result
53
+
54
+ # 注文変更
55
+ puts "\n--- edit_order"
56
+ fx_session.edit_order( result.order_no, {
57
+ :rate=>145.19,
58
+ :expiration_type=>GMO::FX::EXPIRATION_TYPE_TODAY
59
+ })
60
+
61
+ # 注文取消し
62
+ puts "\n--- cancel_order"
63
+ fx_session.cancel_order( result.order_no )
64
+
65
+ # 通常決済注文
66
+ puts "\n--- settle - basic"
67
+ result = fx_session.order( GMO::FX::USDJPY, GMO::FX::SELL, 2, {
68
+ :rate=>145.19,
69
+ :execution_expression=>GMO::FX::EXECUTION_EXPRESSION_LIMIT_ORDER,
70
+ :expiration_type=>GMO::FX::EXPIRATION_TYPE_TODAY
71
+ })
72
+ puts fx_session.settle( result.order_no, 2, {
73
+ :rate=>146.20,
74
+ :execution_expression=>GMO::FX::EXECUTION_EXPRESSION_LIMIT_ORDER,
75
+ :expiration_type=>GMO::FX::EXPIRATION_TYPE_SPECIFIED,
76
+ :expiration_date=>DateTime.new( 2007, 11, 5, 0 )
77
+ })
78
+
79
+ # OCO注文
80
+ puts "\n--- order - oco"
81
+ result = fx_session.order( GMO::FX::USDJPY, GMO::FX::SELL, 1, {
82
+ :rate=>145.19,
83
+ :stop_order_rate=>144.19,
84
+ :expiration_type=>GMO::FX::EXPIRATION_TYPE_SPECIFIED,
85
+ :expiration_date=>DateTime.new( 2007, 11, 5, 0 )
86
+ })
87
+ puts result
88
+
89
+ # OCO注文変更
90
+ puts "\n--- edit - oco"
91
+ fx_session.edit_order( result.limit_order_no, {
92
+ :stop_order_no=>result.stop_order_no,
93
+ :rate=>145.29,
94
+ :stop_order_rate=>144.29,
95
+ :expiration_type=>GMO::FX::EXPIRATION_TYPE_SPECIFIED,
96
+ :expiration_date=>DateTime.new( 2007, 11, 6, 0 )
97
+ })
98
+
99
+ # OCO決済注文
100
+ puts "\n--- settle - oco"
101
+ puts fx_session.settle( result.limit_order_no, 2, {
102
+ :rate=>146.20,
103
+ :stop_order_rate=>144.19,
104
+ :execution_expression=>GMO::FX::EXECUTION_EXPRESSION_LIMIT_ORDER,
105
+ :expiration_type=>GMO::FX::EXPIRATION_TYPE_SPECIFIED,
106
+ :expiration_date=>DateTime.new( 2007, 11, 5, 0 )
107
+ })
108
+
109
+ # IFD取引
110
+ puts "\n--- order - ifd"
111
+ result = fx_session.order( GMO::FX::USDJPY, GMO::FX::SELL, 1, {
112
+ :rate=>145.19,
113
+ :execution_expression=>GMO::FX::EXECUTION_EXPRESSION_LIMIT_ORDER,
114
+ :expiration_type=>GMO::FX::EXPIRATION_TYPE_SPECIFIED,
115
+ :expiration_date=>DateTime.new( 2007, 11, 5, 0 ),
116
+ :settle=>{
117
+ :unit=>1,
118
+ :sell_or_buy=>GMO::FX::BUY,
119
+ :rate=>145.91,
120
+ :execution_expression=>GMO::FX::EXECUTION_EXPRESSION_LIMIT_ORDER,
121
+ :expiration_type=>GMO::FX::EXPIRATION_TYPE_SPECIFIED,
122
+ :expiration_date=>DateTime.new( 2007, 11, 5, 0 ),
123
+ }
124
+ })
125
+ puts result
126
+
127
+ # IFD注文変更
128
+ puts "\n--- edit - ifd"
129
+ fx_session.edit_order( result.order_no, {
130
+ :rate=>145.29,
131
+ :expiration_type=>GMO::FX::EXPIRATION_TYPE_TODAY,
132
+ :settle=>{
133
+ :order_no=>result.settlement_order_no,
134
+ :rate=>145.91,
135
+ :expiration_type=>GMO::FX::EXPIRATION_TYPE_SPECIFIED,
136
+ :expiration_date=>DateTime.new( 2007, 11, 6, 0 ),
137
+ }
138
+ })
139
+
140
+ # IFD-OCO取引
141
+ puts "\n--- order - ifd-oco"
142
+ result = fx_session.order( GMO::FX::USDJPY, GMO::FX::SELL, 1, {
143
+ :rate=>145.19,
144
+ :execution_expression=>GMO::FX::EXECUTION_EXPRESSION_LIMIT_ORDER,
145
+ :expiration_type=>GMO::FX::EXPIRATION_TYPE_TODAY,
146
+ :settle=>{
147
+ :unit=>1,
148
+ :sell_or_buy=>GMO::FX::BUY,
149
+ :rate=>145.91,
150
+ :stop_order_rate=>144.15,
151
+ :execution_expression=>GMO::FX::EXECUTION_EXPRESSION_LIMIT_ORDER,
152
+ :expiration_type=>GMO::FX::EXPIRATION_TYPE_SPECIFIED,
153
+ :expiration_date=>DateTime.new( 2007, 11, 5, 0 ),
154
+ }
155
+ })
156
+ puts result
157
+
158
+ # IFD-OCO注文変更
159
+ puts "\n--- edit - ifd-oco"
160
+ fx_session.edit_order( result.order_no, {
161
+ :rate=>145.29,
162
+ :expiration_type=>GMO::FX::EXPIRATION_TYPE_SPECIFIED,
163
+ :expiration_date=>DateTime.new( 2007, 11, 6, 0 ),
164
+ :settle=>{
165
+ :order_no=>result.kessaiSashineChumonBango,
166
+ :stop_order_no=>result.kessaiGyakusashiChumonBango,
167
+ :rate=>145.21,
168
+ :stop_order_rate=>144.15,
169
+ :expiration_type=>GMO::FX::EXPIRATION_TYPE_SPECIFIED,
170
+ :expiration_date=>DateTime.new( 2007, 11, 6, 0 ),
171
+ }
172
+ })
173
+
174
+ # 注文一覧取得
175
+ # 引数で、注文状態コード(必須)、通貨ペアコード、注文日期間開始日、注文日期間終了日を指定可能。
176
+ puts "\n--- list_orders"
177
+ list = fx_session.list_orders GMO::FX::ORDER_CONDITION_ALL, GMO::FX::EURJPY, Date.new( 2007, 10, 1 ), Date.new( 2007, 11, 1 )
178
+ list.each{ |item| puts item }
179
+
180
+ # 建玉一覧取得
181
+ # 引数で、通貨ペアコードを指定可能。(省略可)
182
+ puts "\n--- list_open_interests"
183
+ list = fx_session.list_open_interests( GMO::FX::EURJPY )
184
+ list.each{ |item| puts item }
185
+
186
+ # 約定一覧取得
187
+ # 引数で、取得期間(開始日,終了日)(必須)、通貨ペアコード、取引タイプ(新規Or決済)を指定可能。
188
+ puts "\n--- list_execution_results"
189
+ list = fx_session.list_execution_results( Date.new( 2007, 10, 1 ), Date.new( 2007, 11, 1 ) )
190
+ list.each{ |item| puts item }
191
+ list = fx_session.list_execution_results( Date.new( 2007, 10, 1 ), Date.new( 2007, 11, 1 ), GMO::FX::TRADE_TYPE_NEW, GMO::FX::EURJPY )
192
+ list.each{ |item| puts item }
193
+
194
+ # 余力情報の取得
195
+ puts "\n--- get_margin"
196
+ puts fx_session.get_margin
197
+
198
+ # お知らせ一覧取得
199
+ puts "\n--- list_messages"
200
+ list = fx_session.list_messages
201
+ list.each{ |item| puts item.to_s.tosjis }
202
+ }
@@ -0,0 +1,208 @@
1
+ begin
2
+ require 'rubygems'
3
+ rescue LoadError
4
+ end
5
+ require 'httpclient'
6
+ require 'rexml/document'
7
+ require 'date'
8
+
9
+ #
10
+ #=== クリック証券アクセスクライアント
11
+ #
12
+ #*Version*:: 0.0.1
13
+ #*License*:: Ruby ライセンスに準拠
14
+ #
15
+ #クリック証券Webサービスを利用するためのクライアントライブラリです。以下の機能を提供します。
16
+ #- 外為証拠金取引(FX)取引
17
+ #
18
+ #====依存モジュール
19
+ #「{httpclient}[http://dev.ctor.org/http-access2]」を利用しています。以下のコマンドを実行してインストールしてください。
20
+ #
21
+ # gem install httpclient --source http://dev.ctor.org/download/
22
+ #
23
+ #====基本的な使い方
24
+ #
25
+ # require 'clickclient'
26
+ #
27
+ # c = ClickClient::Client.new
28
+ # # c = ClickClient::Client.new https://<プロキシホスト>:<プロキシポート> # プロキシを利用する場合
29
+ # c.fx_session( "<ユーザー名>", "<パスワード>" ) { | fx_session |
30
+ # # 通貨ペア一覧取得
31
+ # list = fx_session.list_currency_pairs
32
+ # puts list
33
+ # }
34
+ #なお、ご利用にあたっては「{クリック証券Webサービス利用規約}[https://sec.gmo.jp/corp/guide/regulations/pdf/reg_webservice.pdf]
35
+ #」(PDF)に同意して頂く必要があります。
36
+ #
37
+ #====免責
38
+ #- 本ライブラリの利用は自己責任でお願いします。
39
+ #- ライブラリの不備・不具合等によるあらゆる損害について、作成者は責任を負いません。
40
+ #
41
+ module ClickClient
42
+
43
+ # クライアント
44
+ class Client
45
+
46
+ # ホスト名
47
+ DEFAULT_HOST_NAME = "https://sec-sso.gmo.jp"
48
+
49
+ #
50
+ #===コンストラクタ
51
+ #
52
+ #*proxy*:: プロキシホストを利用する場合、そのホスト名とパスを指定します。
53
+ # 例) https://proxyhost.com:80
54
+ #
55
+ def initialize( proxy=nil )
56
+ @client = HTTPClient.new( proxy, "ClickClientLib")
57
+ @client.set_cookie_store("cookie.dat")
58
+ @host_name = DEFAULT_HOST_NAME
59
+ end
60
+
61
+ #ホスト名
62
+ attr :host_name, true
63
+
64
+ private
65
+ # ログインしてブロックを実行する。ブロックの実行後ログアウトする。
66
+ def session( uri, userid, password, &block )
67
+
68
+ # sequence 1
69
+ result = @client.post(uri, "u=" << userid )
70
+ seq2_uri = result.header["Location"].to_s
71
+ raise "fail session-1.responce=" << result.content if seq2_uri == nil || seq2_uri.length <= 0
72
+
73
+ # sequence 2
74
+ result = @client.get( seq2_uri )
75
+ doc = REXML::Document.new(result.content)
76
+ unless ( doc.text( "./loginResponse/responseStatus" ) =~ /OK/ )
77
+ raise "fail session-2." << doc.text( "./loginResponse/message" )
78
+ end
79
+
80
+ # sequence 3
81
+ base_uri = File.dirname( seq2_uri )
82
+ result = @client.post( base_uri + "/ws-login", "j_username=#{userid}&j_password=#{password}" )
83
+ seq4_uri = result.header["Location"]
84
+ if ( seq4_uri == nil || seq4_uri.length <= 0 )
85
+ doc = REXML::Document.new(result.content)
86
+ raise "fail session-3." << doc.text( "./loginResponse/message" )
87
+ end
88
+
89
+ # sequence 4
90
+ # responseStatusがOKになるまでリダイレクトが続く。
91
+ while ( true )
92
+ result = @client.get( seq4_uri )
93
+ doc = REXML::Document.new(result.content)
94
+ if ( doc.text( "./loginResponse/responseStatus" ) =~ /OK/ )
95
+ break
96
+ else
97
+ seq4_uri = result.header["Location"]
98
+ raise "fail session-4.responce=" << result.content if seq4_uri == nil || seq4_uri.length <= 0
99
+ end
100
+ end
101
+
102
+ begin
103
+ block.call( @client, base_uri )
104
+ ensure
105
+ # logout
106
+ result = @client.post( base_uri + "/ws-logout" )
107
+ doc = REXML::Document.new(result.content)
108
+ unless ( doc.text( "./logoutResponse/responseStatus" ) =~ /OK/ )
109
+ raise "fail session-5." << doc.text( "./logoutResponse/message" )
110
+ end
111
+ end
112
+
113
+ end
114
+ end
115
+
116
+ private
117
+
118
+ #
119
+ #=== 結果オブジェクトの抽象基底クラス。
120
+ #
121
+ class Base #:nodoc:
122
+ def initialize( item )
123
+ # 属性と子要素の値を、オブジェクトの属性として格納する。
124
+ item.attributes.each { |name, value|
125
+ set_attribute(name.to_s ,value)
126
+ }
127
+ item.elements.each { |elm|
128
+ if ( elm.name != "responseStatus" && elm.name != "message" )
129
+ set_attribute(elm.name.to_s, elm.text)
130
+ end
131
+ }
132
+ end
133
+ def to_s
134
+ str = ""
135
+ instance_variables.each { |name|
136
+ str += name + "=" + instance_variable_get(name).to_s + ", "
137
+ }
138
+ return str.chop.chop
139
+ end
140
+ def method_missing( name, *args )
141
+ if name.to_s =~ /(.*?)=/
142
+ name = $1
143
+ setter = true
144
+ end
145
+
146
+ # 同名の属性があればそれのReaderと見なし、属性値を返す。
147
+ value = instance_variable_get("@" << name.to_s)
148
+ unless ( value == nil )
149
+ if setter
150
+ instance_variable_set( "@" << name, args[0] )
151
+ else
152
+ return value
153
+ end
154
+ else
155
+ super(name)
156
+ end
157
+ end
158
+ def hash
159
+ hash = 0
160
+ values.each {|v|
161
+ hash = v.hash + 31 * hash
162
+ }
163
+ return hash
164
+ end
165
+ def eql?(other)
166
+ return false if other == nil
167
+ return false unless other.is_a?( Base )
168
+ a = values
169
+ b = other.values
170
+ return false if a.length != b.length
171
+ a.length.times{|i|
172
+ return false unless a[i].eql? b[i]
173
+ }
174
+ return true
175
+ end
176
+ protected
177
+ def values
178
+ values = []
179
+ instance_variables.each { |name|
180
+ values << instance_variable_get(name)
181
+ }
182
+ return values
183
+ end
184
+ private
185
+ def set_attribute(name ,value)
186
+ if ( value =~ /^\d+$/)
187
+ value = value.to_i
188
+ elsif ( value =~ /^[\d\.]+$/)
189
+ value = value.to_f
190
+ elsif ( value =~ /^\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2}$/)
191
+ value = DateTime.strptime( value, "%Y-%m-%d %H:%M:%S")
192
+ elsif ( value =~ /^\d{4}-\d{2}-\d{2}$/)
193
+ value = DateTime.strptime( value, "%Y-%m-%d")
194
+ end
195
+ instance_variable_set( "@" << name, value )
196
+ end
197
+ end
198
+
199
+ # 結果を解析し、エラーであれば例外をスローする。
200
+ def self.parse( content )
201
+ doc = REXML::Document.new( content )
202
+ unless ( doc.text( "./*/responseStatus" ) =~ /OK/ )
203
+ raise "fail." << doc.text( "./*/message" )
204
+ end
205
+ return doc
206
+ end
207
+
208
+ end