sbiclient 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.
data/README ADDED
@@ -0,0 +1,30 @@
1
+
2
+ ==SBI証券Fxクライアントライブラリ
3
+
4
+ SBI証券の携帯向けサイトにアクセスし、
5
+ スクレイピングでレート情報の取得や取り引きを行うライブラリです。
6
+
7
+ ===実装済みの機能
8
+ - ログイン
9
+ - ログアウト
10
+ - レート一覧の取得
11
+ - 建玉一覧の取得
12
+ - 注文一覧の取得
13
+ - 注文
14
+ -- 指値
15
+ -- 逆指値
16
+ -- OCO
17
+ -- IFD
18
+ -- IFD-OCO
19
+ -- トレール
20
+ - 注文のキャンセル
21
+ - 決済
22
+ --成行
23
+
24
+ ===注意事項
25
+ - スクレイピングによるアクセスのため、Webサイトの仕様変更等により
26
+ 突然動作しなくなる可能性があります。
27
+
28
+ ===免責
29
+ - 本ライブラリの利用は自己責任でお願いします。
30
+ - ライブラリの不備・不具合等によるあらゆる損害について、作成者は責任を負いません。
@@ -0,0 +1,150 @@
1
+
2
+ require 'rubygems'
3
+ require 'jiji/plugin/securities_plugin'
4
+ require 'sbiclient'
5
+ require 'thread'
6
+
7
+ # SBI証券アクセスプラグイン
8
+ class SBISecuritiesPlugin
9
+ include JIJI::Plugin::SecuritiesPlugin
10
+
11
+ #プラグインの識別子を返します。
12
+ def plugin_id
13
+ :sbi_securities
14
+ end
15
+ #プラグインの表示名を返します。
16
+ def display_name
17
+ "SBI Securities"
18
+ end
19
+ #「jiji setting」でユーザーに入力を要求するデータの情報を返します。
20
+ def input_infos
21
+ [ Input.new( :user, "Please input a user name of SBI Securities.", false, nil ),
22
+ Input.new( :password, "Please input a password of SBI Securities.", true, nil ),
23
+ Input.new( :trade_password, "Please input a trade password of SBI Securities.", true, nil ),
24
+ Input.new( :proxy, "Please input a proxy. example: http://example.com:80 (default: nil )", false, nil ) ]
25
+ end
26
+
27
+ #プラグインを初期化します。
28
+ def init_plugin( props, logger )
29
+ @session = SBISecuritiesPluginSession.new( props, logger )
30
+ end
31
+ #プラグインを破棄します。
32
+ def destroy_plugin
33
+ @session.close
34
+ end
35
+
36
+ #利用可能な通貨ペア一覧を取得します。
37
+ def list_pairs
38
+ return ALL_PAIRS.map {|pair|
39
+ count = 10000
40
+ if pair == SBIClient::FX::MSDJPY \
41
+ || pair == SBIClient::FX::MURJPY \
42
+ || pair == SBIClient::FX::MBPJPY \
43
+ || pair == SBIClient::FX::MUDJPY \
44
+ || pair == SBIClient::FX::MZDJPY
45
+ count = 1000
46
+ elsif pair == SBIClient::FX::ZARJPY
47
+ count = 100000
48
+ end
49
+ Pair.new( pair, count )
50
+ }
51
+ end
52
+
53
+ #現在のレートを取得します。
54
+ def list_rates
55
+ @session.list_rates.inject({}) {|r,p|
56
+ r[p[0]] = Rate.new( p[1].bid_rate, p[1].ask_rate, p[1].sell_swap, p[1].buy_swap )
57
+ r
58
+ }
59
+ end
60
+
61
+ #成り行きで発注を行います。
62
+ def order( pair, sell_or_buy, count )
63
+
64
+ # 建玉一覧を取得
65
+ before = @session.list_positions.inject( Set.new ) {|s,i| s << i[0]; s }
66
+ # 発注
67
+ @session.order( pair, sell_or_buy == :buy ? SBIClient::FX::BUY : SBIClient::FX::SELL, count )
68
+ # 建玉を特定
69
+ position = nil
70
+ # 10s待っても取得できなければあきらめる
71
+ 20.times {|i|
72
+ sleep 0.5
73
+ position = @session.list_positions.find {|i| !before.include?(i[0]) }
74
+ break if position
75
+ }
76
+ raise "order fialed." unless position
77
+ return JIJI::Plugin::SecuritiesPlugin::Position.new( position[1].position_id )
78
+ end
79
+
80
+ #建玉を決済します。
81
+ def commit( position_id, count )
82
+ @session.settle( position_id, count )
83
+ end
84
+
85
+ private
86
+
87
+ ALL_PAIRS = [
88
+ SBIClient::FX::USDJPY, SBIClient::FX::EURJPY,
89
+ SBIClient::FX::GBPJPY, SBIClient::FX::AUDJPY,
90
+ SBIClient::FX::NZDJPY, SBIClient::FX::CADJPY,
91
+ SBIClient::FX::CHFJPY, SBIClient::FX::ZARJPY,
92
+ SBIClient::FX::EURUSD, SBIClient::FX::GBPUSD,
93
+ SBIClient::FX::AUDUSD, SBIClient::FX::NOKJPY,
94
+ SBIClient::FX::MUDJPY, SBIClient::FX::HKDJPY,
95
+ SBIClient::FX::SEKJPY, SBIClient::FX::MZDJPY,
96
+ SBIClient::FX::KRWJPY, SBIClient::FX::PLNJPY,
97
+ SBIClient::FX::MARJPY, SBIClient::FX::SGDJPY,
98
+ SBIClient::FX::MSDJPY, SBIClient::FX::MXNJPY,
99
+ SBIClient::FX::MURJPY, SBIClient::FX::TRYJPY,
100
+ SBIClient::FX::MBPJPY, SBIClient::FX::CNYJPY
101
+ ]
102
+ end
103
+
104
+ class SBISecuritiesPluginSession
105
+ def initialize( props, logger )
106
+ @props = props
107
+ @logger = logger
108
+ @m = Mutex.new
109
+ end
110
+ def method_missing( name, *args )
111
+ @m.synchronize {
112
+ begin
113
+ session.send( name, *args )
114
+ rescue
115
+ # エラーになった場合はセッションを再作成する
116
+ close
117
+ raise $!
118
+ end
119
+ }
120
+ end
121
+ def close
122
+ begin
123
+ @session.logout if @session
124
+ rescue
125
+ @logger.error $!
126
+ ensure
127
+ @session = nil
128
+ @client = nil
129
+ end
130
+ end
131
+ def session
132
+ begin
133
+ proxy = nil
134
+ if @props.key?(:proxy) && @props[:proxy] != nil && @props[:proxy].length > 0
135
+ proxy = @props[:proxy]
136
+ end
137
+ @client ||= SBIClient::Client.new( proxy )
138
+ @session ||= @client.fx_session( @props[:user], @props[:password], @props[:trade_password] )
139
+ rescue
140
+ @logger.error $!
141
+ raise $!
142
+ end
143
+ @session
144
+ end
145
+ end
146
+
147
+ JIJI::Plugin.register(
148
+ JIJI::Plugin::SecuritiesPlugin::FUTURE_NAME,
149
+ SBISecuritiesPlugin.new )
150
+