opentick-ruby 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +6 -0
- data/README +16 -0
- data/doc/created.rid +1 -0
- data/doc/fr_class_index.html +49 -0
- data/doc/fr_file_index.html +27 -0
- data/doc/fr_method_index.html +81 -0
- data/doc/index.html +24 -0
- data/doc/rdoc-style.css +208 -0
- data/lib/opentick.rb +543 -0
- data/opentick.gemspec +20 -0
- metadata +62 -0
data/ChangeLog
ADDED
data/README
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
Ruby implementation for Opentick API. Copyright(c) 2007 Adigamov Timur (timur at adigamov dot com)
|
2
|
+
|
3
|
+
License
|
4
|
+
|
5
|
+
This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
|
6
|
+
|
7
|
+
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
8
|
+
|
9
|
+
You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
10
|
+
Use At Your Own Risk
|
11
|
+
|
12
|
+
As the license indicates, this code is provided AS IS, WITH NO WARRANTY WHATSOEVER, not even an implied warranty of merchantability or fitness for a particular purpose.
|
13
|
+
|
14
|
+
*ANY USE YOU MAKE OF THIS CODE IS ENTIRELY AT YOUR OWN RISK.*
|
15
|
+
|
16
|
+
This code may contain any number of errors or bugs, both known and unknown. Use of this code may result in monetary loss due to known or unknown bugs and errors. In no event shall the author be liable or responsible for any loss whatsoever, direct or indirect, that may occur as a result of your use of this code.
|
data/doc/created.rid
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Thu, 08 Nov 2007 00:59:41 +0300
|
@@ -0,0 +1,49 @@
|
|
1
|
+
|
2
|
+
<?xml version="1.0" encoding="iso-8859-1"?>
|
3
|
+
<!DOCTYPE html
|
4
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
5
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
6
|
+
|
7
|
+
<!--
|
8
|
+
|
9
|
+
Classes
|
10
|
+
|
11
|
+
-->
|
12
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
13
|
+
<head>
|
14
|
+
<title>Classes</title>
|
15
|
+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
16
|
+
<link rel="stylesheet" href="rdoc-style.css" type="text/css" />
|
17
|
+
<base target="docwin" />
|
18
|
+
</head>
|
19
|
+
<body>
|
20
|
+
<div id="index">
|
21
|
+
<h1 class="section-bar">Classes</h1>
|
22
|
+
<div id="index-entries">
|
23
|
+
<a href="classes/OpenTick.html">OpenTick</a><br />
|
24
|
+
<a href="classes/OpenTick/Debug.html">OpenTick::Debug</a><br />
|
25
|
+
<a href="classes/OpenTick/IncomingMessages.html">OpenTick::IncomingMessages</a><br />
|
26
|
+
<a href="classes/OpenTick/IncomingMessages/AbstractMessage.html">OpenTick::IncomingMessages::AbstractMessage</a><br />
|
27
|
+
<a href="classes/OpenTick/IncomingMessages/ErrorResponse.html">OpenTick::IncomingMessages::ErrorResponse</a><br />
|
28
|
+
<a href="classes/OpenTick/IncomingMessages/HistoryStreamResponse.html">OpenTick::IncomingMessages::HistoryStreamResponse</a><br />
|
29
|
+
<a href="classes/OpenTick/IncomingMessages/ListExchangesResponse.html">OpenTick::IncomingMessages::ListExchangesResponse</a><br />
|
30
|
+
<a href="classes/OpenTick/IncomingMessages/LoginResponse.html">OpenTick::IncomingMessages::LoginResponse</a><br />
|
31
|
+
<a href="classes/OpenTick/IncomingMessages/LogoutReponse.html">OpenTick::IncomingMessages::LogoutReponse</a><br />
|
32
|
+
<a href="classes/OpenTick/IncomingMessages/TickStreamResponse.html">OpenTick::IncomingMessages::TickStreamResponse</a><br />
|
33
|
+
<a href="classes/OpenTick/OpenTick.html">OpenTick::OpenTick</a><br />
|
34
|
+
<a href="classes/OpenTick/OutgoingMessages.html">OpenTick::OutgoingMessages</a><br />
|
35
|
+
<a href="classes/OpenTick/OutgoingMessages/AbstractMessage.html">OpenTick::OutgoingMessages::AbstractMessage</a><br />
|
36
|
+
<a href="classes/OpenTick/OutgoingMessages/CancelHistDataRequest.html">OpenTick::OutgoingMessages::CancelHistDataRequest</a><br />
|
37
|
+
<a href="classes/OpenTick/OutgoingMessages/CancelTickStreamRequest.html">OpenTick::OutgoingMessages::CancelTickStreamRequest</a><br />
|
38
|
+
<a href="classes/OpenTick/OutgoingMessages/HeartBeat.html">OpenTick::OutgoingMessages::HeartBeat</a><br />
|
39
|
+
<a href="classes/OpenTick/OutgoingMessages/HistTicksRequest.html">OpenTick::OutgoingMessages::HistTicksRequest</a><br />
|
40
|
+
<a href="classes/OpenTick/OutgoingMessages/HistoryStreamRequest.html">OpenTick::OutgoingMessages::HistoryStreamRequest</a><br />
|
41
|
+
<a href="classes/OpenTick/OutgoingMessages/ListExchangesRequest.html">OpenTick::OutgoingMessages::ListExchangesRequest</a><br />
|
42
|
+
<a href="classes/OpenTick/OutgoingMessages/LoginRequest.html">OpenTick::OutgoingMessages::LoginRequest</a><br />
|
43
|
+
<a href="classes/OpenTick/OutgoingMessages/LogoutRequest.html">OpenTick::OutgoingMessages::LogoutRequest</a><br />
|
44
|
+
<a href="classes/OpenTick/OutgoingMessages/TickSnapshotRequest.html">OpenTick::OutgoingMessages::TickSnapshotRequest</a><br />
|
45
|
+
<a href="classes/OpenTick/OutgoingMessages/TickStreamExRequest.html">OpenTick::OutgoingMessages::TickStreamExRequest</a><br />
|
46
|
+
</div>
|
47
|
+
</div>
|
48
|
+
</body>
|
49
|
+
</html>
|
@@ -0,0 +1,27 @@
|
|
1
|
+
|
2
|
+
<?xml version="1.0" encoding="iso-8859-1"?>
|
3
|
+
<!DOCTYPE html
|
4
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
5
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
6
|
+
|
7
|
+
<!--
|
8
|
+
|
9
|
+
Files
|
10
|
+
|
11
|
+
-->
|
12
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
13
|
+
<head>
|
14
|
+
<title>Files</title>
|
15
|
+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
16
|
+
<link rel="stylesheet" href="rdoc-style.css" type="text/css" />
|
17
|
+
<base target="docwin" />
|
18
|
+
</head>
|
19
|
+
<body>
|
20
|
+
<div id="index">
|
21
|
+
<h1 class="section-bar">Files</h1>
|
22
|
+
<div id="index-entries">
|
23
|
+
<a href="files/lib/opentick_rb.html">lib/opentick.rb</a><br />
|
24
|
+
</div>
|
25
|
+
</div>
|
26
|
+
</body>
|
27
|
+
</html>
|
@@ -0,0 +1,81 @@
|
|
1
|
+
|
2
|
+
<?xml version="1.0" encoding="iso-8859-1"?>
|
3
|
+
<!DOCTYPE html
|
4
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
5
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
6
|
+
|
7
|
+
<!--
|
8
|
+
|
9
|
+
Methods
|
10
|
+
|
11
|
+
-->
|
12
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
13
|
+
<head>
|
14
|
+
<title>Methods</title>
|
15
|
+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
16
|
+
<link rel="stylesheet" href="rdoc-style.css" type="text/css" />
|
17
|
+
<base target="docwin" />
|
18
|
+
</head>
|
19
|
+
<body>
|
20
|
+
<div id="index">
|
21
|
+
<h1 class="section-bar">Methods</h1>
|
22
|
+
<div id="index-entries">
|
23
|
+
<a href="classes/OpenTick/OpenTick.html#M000050">close (OpenTick::OpenTick)</a><br />
|
24
|
+
<a href="classes/OpenTick/OpenTick.html#M000051">dispatch (OpenTick::OpenTick)</a><br />
|
25
|
+
<a href="classes/OpenTick.html#M000003">get_exchange_list (OpenTick)</a><br />
|
26
|
+
<a href="classes/OpenTick.html#M000001">get_historical_quotes (OpenTick)</a><br />
|
27
|
+
<a href="classes/OpenTick.html#M000002">get_historical_ticks (OpenTick)</a><br />
|
28
|
+
<a href="classes/OpenTick/OutgoingMessages/AbstractMessage.html#M000031">header (OpenTick::OutgoingMessages::AbstractMessage)</a><br />
|
29
|
+
<a href="classes/OpenTick/OpenTick.html#M000055">heart_beat (OpenTick::OpenTick)</a><br />
|
30
|
+
<a href="classes/OpenTick/IncomingMessages/AbstractMessage.html#M000011">inherited (OpenTick::IncomingMessages::AbstractMessage)</a><br />
|
31
|
+
<a href="classes/OpenTick/IncomingMessages/LoginResponse.html#M000005">load (OpenTick::IncomingMessages::LoginResponse)</a><br />
|
32
|
+
<a href="classes/OpenTick/IncomingMessages/TickStreamResponse.html#M000016">load (OpenTick::IncomingMessages::TickStreamResponse)</a><br />
|
33
|
+
<a href="classes/OpenTick/IncomingMessages/LogoutReponse.html#M000007">load (OpenTick::IncomingMessages::LogoutReponse)</a><br />
|
34
|
+
<a href="classes/OpenTick/IncomingMessages/ErrorResponse.html#M000018">load (OpenTick::IncomingMessages::ErrorResponse)</a><br />
|
35
|
+
<a href="classes/OpenTick/IncomingMessages/HistoryStreamResponse.html#M000020">load (OpenTick::IncomingMessages::HistoryStreamResponse)</a><br />
|
36
|
+
<a href="classes/OpenTick/IncomingMessages/ListExchangesResponse.html#M000014">load (OpenTick::IncomingMessages::ListExchangesResponse)</a><br />
|
37
|
+
<a href="classes/OpenTick/IncomingMessages/AbstractMessage.html#M000012">load (OpenTick::IncomingMessages::AbstractMessage)</a><br />
|
38
|
+
<a href="classes/OpenTick/OpenTick.html#M000048">login (OpenTick::OpenTick)</a><br />
|
39
|
+
<a href="classes/OpenTick/IncomingMessages/AbstractMessage.html#M000008">message_id (OpenTick::IncomingMessages::AbstractMessage)</a><br />
|
40
|
+
<a href="classes/OpenTick/IncomingMessages/TickStreamResponse.html#M000015">message_id (OpenTick::IncomingMessages::TickStreamResponse)</a><br />
|
41
|
+
<a href="classes/OpenTick/IncomingMessages/HistoryStreamResponse.html#M000019">message_id (OpenTick::IncomingMessages::HistoryStreamResponse)</a><br />
|
42
|
+
<a href="classes/OpenTick/IncomingMessages/ListExchangesResponse.html#M000013">message_id (OpenTick::IncomingMessages::ListExchangesResponse)</a><br />
|
43
|
+
<a href="classes/OpenTick/IncomingMessages/ErrorResponse.html#M000017">message_id (OpenTick::IncomingMessages::ErrorResponse)</a><br />
|
44
|
+
<a href="classes/OpenTick/OutgoingMessages/ListExchangesRequest.html#M000022">message_id (OpenTick::OutgoingMessages::ListExchangesRequest)</a><br />
|
45
|
+
<a href="classes/OpenTick/IncomingMessages/LoginResponse.html#M000004">message_id (OpenTick::IncomingMessages::LoginResponse)</a><br />
|
46
|
+
<a href="classes/OpenTick/OutgoingMessages/CancelHistDataRequest.html#M000024">message_id (OpenTick::OutgoingMessages::CancelHistDataRequest)</a><br />
|
47
|
+
<a href="classes/OpenTick/OutgoingMessages/HeartBeat.html#M000044">message_id (OpenTick::OutgoingMessages::HeartBeat)</a><br />
|
48
|
+
<a href="classes/OpenTick/OutgoingMessages/HistTicksRequest.html#M000026">message_id (OpenTick::OutgoingMessages::HistTicksRequest)</a><br />
|
49
|
+
<a href="classes/OpenTick/OutgoingMessages/LogoutRequest.html#M000042">message_id (OpenTick::OutgoingMessages::LogoutRequest)</a><br />
|
50
|
+
<a href="classes/OpenTick/OutgoingMessages/AbstractMessage.html#M000028">message_id (OpenTick::OutgoingMessages::AbstractMessage)</a><br />
|
51
|
+
<a href="classes/OpenTick/OutgoingMessages/HistoryStreamRequest.html#M000040">message_id (OpenTick::OutgoingMessages::HistoryStreamRequest)</a><br />
|
52
|
+
<a href="classes/OpenTick/OutgoingMessages/TickStreamExRequest.html#M000038">message_id (OpenTick::OutgoingMessages::TickStreamExRequest)</a><br />
|
53
|
+
<a href="classes/OpenTick/IncomingMessages/LogoutReponse.html#M000006">message_id (OpenTick::IncomingMessages::LogoutReponse)</a><br />
|
54
|
+
<a href="classes/OpenTick/OutgoingMessages/LoginRequest.html#M000034">message_id (OpenTick::OutgoingMessages::LoginRequest)</a><br />
|
55
|
+
<a href="classes/OpenTick/OutgoingMessages/TickSnapshotRequest.html#M000036">message_id (OpenTick::OutgoingMessages::TickSnapshotRequest)</a><br />
|
56
|
+
<a href="classes/OpenTick/OutgoingMessages/CancelTickStreamRequest.html#M000032">message_id (OpenTick::OutgoingMessages::CancelTickStreamRequest)</a><br />
|
57
|
+
<a href="classes/OpenTick/OutgoingMessages/AbstractMessage.html#M000029">method_missing (OpenTick::OutgoingMessages::AbstractMessage)</a><br />
|
58
|
+
<a href="classes/OpenTick/IncomingMessages/AbstractMessage.html#M000010">method_missing (OpenTick::IncomingMessages::AbstractMessage)</a><br />
|
59
|
+
<a href="classes/OpenTick/Debug.html#M000021">method_name (OpenTick::Debug)</a><br />
|
60
|
+
<a href="classes/OpenTick/IncomingMessages/AbstractMessage.html#M000009">new (OpenTick::IncomingMessages::AbstractMessage)</a><br />
|
61
|
+
<a href="classes/OpenTick/OpenTick.html#M000046">new (OpenTick::OpenTick)</a><br />
|
62
|
+
<a href="classes/OpenTick/OutgoingMessages/AbstractMessage.html#M000030">new (OpenTick::OutgoingMessages::AbstractMessage)</a><br />
|
63
|
+
<a href="classes/OpenTick/OpenTick.html#M000047">open (OpenTick::OpenTick)</a><br />
|
64
|
+
<a href="classes/OpenTick/OpenTick.html#M000053">read_from_socket (OpenTick::OpenTick)</a><br />
|
65
|
+
<a href="classes/OpenTick/OpenTick.html#M000054">reader (OpenTick::OpenTick)</a><br />
|
66
|
+
<a href="classes/OpenTick/OpenTick.html#M000049">reconnect (OpenTick::OpenTick)</a><br />
|
67
|
+
<a href="classes/OpenTick/OutgoingMessages/HeartBeat.html#M000045">send (OpenTick::OutgoingMessages::HeartBeat)</a><br />
|
68
|
+
<a href="classes/OpenTick/OutgoingMessages/CancelHistDataRequest.html#M000025">send (OpenTick::OutgoingMessages::CancelHistDataRequest)</a><br />
|
69
|
+
<a href="classes/OpenTick/OutgoingMessages/LogoutRequest.html#M000043">send (OpenTick::OutgoingMessages::LogoutRequest)</a><br />
|
70
|
+
<a href="classes/OpenTick/OutgoingMessages/ListExchangesRequest.html#M000023">send (OpenTick::OutgoingMessages::ListExchangesRequest)</a><br />
|
71
|
+
<a href="classes/OpenTick/OutgoingMessages/HistTicksRequest.html#M000027">send (OpenTick::OutgoingMessages::HistTicksRequest)</a><br />
|
72
|
+
<a href="classes/OpenTick/OutgoingMessages/HistoryStreamRequest.html#M000041">send (OpenTick::OutgoingMessages::HistoryStreamRequest)</a><br />
|
73
|
+
<a href="classes/OpenTick/OutgoingMessages/CancelTickStreamRequest.html#M000033">send (OpenTick::OutgoingMessages::CancelTickStreamRequest)</a><br />
|
74
|
+
<a href="classes/OpenTick/OutgoingMessages/LoginRequest.html#M000035">send (OpenTick::OutgoingMessages::LoginRequest)</a><br />
|
75
|
+
<a href="classes/OpenTick/OutgoingMessages/TickSnapshotRequest.html#M000037">send (OpenTick::OutgoingMessages::TickSnapshotRequest)</a><br />
|
76
|
+
<a href="classes/OpenTick/OutgoingMessages/TickStreamExRequest.html#M000039">send (OpenTick::OutgoingMessages::TickStreamExRequest)</a><br />
|
77
|
+
<a href="classes/OpenTick/OpenTick.html#M000052">subscribe (OpenTick::OpenTick)</a><br />
|
78
|
+
</div>
|
79
|
+
</div>
|
80
|
+
</body>
|
81
|
+
</html>
|
data/doc/index.html
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
<?xml version="1.0" encoding="iso-8859-1"?>
|
2
|
+
<!DOCTYPE html
|
3
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
|
4
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
|
5
|
+
|
6
|
+
<!--
|
7
|
+
|
8
|
+
RDoc Documentation
|
9
|
+
|
10
|
+
-->
|
11
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
12
|
+
<head>
|
13
|
+
<title>RDoc Documentation</title>
|
14
|
+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
15
|
+
</head>
|
16
|
+
<frameset rows="20%, 80%">
|
17
|
+
<frameset cols="25%,35%,45%">
|
18
|
+
<frame src="fr_file_index.html" title="Files" name="Files" />
|
19
|
+
<frame src="fr_class_index.html" name="Classes" />
|
20
|
+
<frame src="fr_method_index.html" name="Methods" />
|
21
|
+
</frameset>
|
22
|
+
<frame src="files/lib/opentick_rb.html" name="docwin" />
|
23
|
+
</frameset>
|
24
|
+
</html>
|
data/doc/rdoc-style.css
ADDED
@@ -0,0 +1,208 @@
|
|
1
|
+
|
2
|
+
body {
|
3
|
+
font-family: Verdana,Arial,Helvetica,sans-serif;
|
4
|
+
font-size: 90%;
|
5
|
+
margin: 0;
|
6
|
+
margin-left: 40px;
|
7
|
+
padding: 0;
|
8
|
+
background: white;
|
9
|
+
}
|
10
|
+
|
11
|
+
h1,h2,h3,h4 { margin: 0; color: #efefef; background: transparent; }
|
12
|
+
h1 { font-size: 150%; }
|
13
|
+
h2,h3,h4 { margin-top: 1em; }
|
14
|
+
|
15
|
+
a { background: #eef; color: #039; text-decoration: none; }
|
16
|
+
a:hover { background: #039; color: #eef; }
|
17
|
+
|
18
|
+
/* Override the base stylesheet's Anchor inside a table cell */
|
19
|
+
td > a {
|
20
|
+
background: transparent;
|
21
|
+
color: #039;
|
22
|
+
text-decoration: none;
|
23
|
+
}
|
24
|
+
|
25
|
+
/* and inside a section title */
|
26
|
+
.section-title > a {
|
27
|
+
background: transparent;
|
28
|
+
color: #eee;
|
29
|
+
text-decoration: none;
|
30
|
+
}
|
31
|
+
|
32
|
+
/* === Structural elements =================================== */
|
33
|
+
|
34
|
+
div#index {
|
35
|
+
margin: 0;
|
36
|
+
margin-left: -40px;
|
37
|
+
padding: 0;
|
38
|
+
font-size: 90%;
|
39
|
+
}
|
40
|
+
|
41
|
+
|
42
|
+
div#index a {
|
43
|
+
margin-left: 0.7em;
|
44
|
+
}
|
45
|
+
|
46
|
+
div#index .section-bar {
|
47
|
+
margin-left: 0px;
|
48
|
+
padding-left: 0.7em;
|
49
|
+
background: #ccc;
|
50
|
+
font-size: small;
|
51
|
+
}
|
52
|
+
|
53
|
+
|
54
|
+
div#classHeader, div#fileHeader {
|
55
|
+
width: auto;
|
56
|
+
color: white;
|
57
|
+
padding: 0.5em 1.5em 0.5em 1.5em;
|
58
|
+
margin: 0;
|
59
|
+
margin-left: -40px;
|
60
|
+
border-bottom: 3px solid #006;
|
61
|
+
}
|
62
|
+
|
63
|
+
div#classHeader a, div#fileHeader a {
|
64
|
+
background: inherit;
|
65
|
+
color: white;
|
66
|
+
}
|
67
|
+
|
68
|
+
div#classHeader td, div#fileHeader td {
|
69
|
+
background: inherit;
|
70
|
+
color: white;
|
71
|
+
}
|
72
|
+
|
73
|
+
|
74
|
+
div#fileHeader {
|
75
|
+
background: #057;
|
76
|
+
}
|
77
|
+
|
78
|
+
div#classHeader {
|
79
|
+
background: #048;
|
80
|
+
}
|
81
|
+
|
82
|
+
|
83
|
+
.class-name-in-header {
|
84
|
+
font-size: 180%;
|
85
|
+
font-weight: bold;
|
86
|
+
}
|
87
|
+
|
88
|
+
|
89
|
+
div#bodyContent {
|
90
|
+
padding: 0 1.5em 0 1.5em;
|
91
|
+
}
|
92
|
+
|
93
|
+
div#description {
|
94
|
+
padding: 0.5em 1.5em;
|
95
|
+
background: #efefef;
|
96
|
+
border: 1px dotted #999;
|
97
|
+
}
|
98
|
+
|
99
|
+
div#description h1,h2,h3,h4,h5,h6 {
|
100
|
+
color: #125;;
|
101
|
+
background: transparent;
|
102
|
+
}
|
103
|
+
|
104
|
+
div#validator-badges {
|
105
|
+
text-align: center;
|
106
|
+
}
|
107
|
+
div#validator-badges img { border: 0; }
|
108
|
+
|
109
|
+
div#copyright {
|
110
|
+
color: #333;
|
111
|
+
background: #efefef;
|
112
|
+
font: 0.75em sans-serif;
|
113
|
+
margin-top: 5em;
|
114
|
+
margin-bottom: 0;
|
115
|
+
padding: 0.5em 2em;
|
116
|
+
}
|
117
|
+
|
118
|
+
|
119
|
+
/* === Classes =================================== */
|
120
|
+
|
121
|
+
table.header-table {
|
122
|
+
color: white;
|
123
|
+
font-size: small;
|
124
|
+
}
|
125
|
+
|
126
|
+
.type-note {
|
127
|
+
font-size: small;
|
128
|
+
color: #DEDEDE;
|
129
|
+
}
|
130
|
+
|
131
|
+
.xxsection-bar {
|
132
|
+
background: #eee;
|
133
|
+
color: #333;
|
134
|
+
padding: 3px;
|
135
|
+
}
|
136
|
+
|
137
|
+
.section-bar {
|
138
|
+
color: #333;
|
139
|
+
border-bottom: 1px solid #999;
|
140
|
+
margin-left: -20px;
|
141
|
+
}
|
142
|
+
|
143
|
+
|
144
|
+
.section-title {
|
145
|
+
background: #79a;
|
146
|
+
color: #eee;
|
147
|
+
padding: 3px;
|
148
|
+
margin-top: 2em;
|
149
|
+
margin-left: -30px;
|
150
|
+
border: 1px solid #999;
|
151
|
+
}
|
152
|
+
|
153
|
+
.top-aligned-row { vertical-align: top }
|
154
|
+
.bottom-aligned-row { vertical-align: bottom }
|
155
|
+
|
156
|
+
/* --- Context section classes ----------------------- */
|
157
|
+
|
158
|
+
.context-row { }
|
159
|
+
.context-item-name { font-family: monospace; font-weight: bold; color: black; }
|
160
|
+
.context-item-value { font-size: small; color: #448; }
|
161
|
+
.context-item-desc { color: #333; padding-left: 2em; }
|
162
|
+
|
163
|
+
/* --- Method classes -------------------------- */
|
164
|
+
.method-detail {
|
165
|
+
background: #efefef;
|
166
|
+
padding: 0;
|
167
|
+
margin-top: 0.5em;
|
168
|
+
margin-bottom: 1em;
|
169
|
+
border: 1px dotted #ccc;
|
170
|
+
}
|
171
|
+
.method-heading {
|
172
|
+
color: black;
|
173
|
+
background: #ccc;
|
174
|
+
border-bottom: 1px solid #666;
|
175
|
+
padding: 0.2em 0.5em 0 0.5em;
|
176
|
+
}
|
177
|
+
.method-signature { color: black; background: inherit; }
|
178
|
+
.method-name { font-weight: bold; }
|
179
|
+
.method-args { font-style: italic; }
|
180
|
+
.method-description { padding: 0 0.5em 0 0.5em; }
|
181
|
+
|
182
|
+
/* --- Source code sections -------------------- */
|
183
|
+
|
184
|
+
a.source-toggle { font-size: 90%; }
|
185
|
+
div.method-source-code {
|
186
|
+
background: #262626;
|
187
|
+
color: #ffdead;
|
188
|
+
margin: 1em;
|
189
|
+
padding: 0.5em;
|
190
|
+
border: 1px dashed #999;
|
191
|
+
overflow: hidden;
|
192
|
+
}
|
193
|
+
|
194
|
+
div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
195
|
+
|
196
|
+
/* --- Ruby keyword styles --------------------- */
|
197
|
+
|
198
|
+
.standalone-code { background: #221111; color: #ffdead; overflow: hidden; }
|
199
|
+
|
200
|
+
.ruby-constant { color: #7fffd4; background: transparent; }
|
201
|
+
.ruby-keyword { color: #00ffff; background: transparent; }
|
202
|
+
.ruby-ivar { color: #eedd82; background: transparent; }
|
203
|
+
.ruby-operator { color: #00ffee; background: transparent; }
|
204
|
+
.ruby-identifier { color: #ffdead; background: transparent; }
|
205
|
+
.ruby-node { color: #ffa07a; background: transparent; }
|
206
|
+
.ruby-comment { color: #b22222; font-weight: bold; background: transparent; }
|
207
|
+
.ruby-regexp { color: #ffa07a; background: transparent; }
|
208
|
+
.ruby-value { color: #7fffd4; background: transparent; }
|
data/lib/opentick.rb
ADDED
@@ -0,0 +1,543 @@
|
|
1
|
+
=begin
|
2
|
+
* Ruby implementation for Opentick API *
|
3
|
+
Messages:
|
4
|
+
1. OTLogin - done
|
5
|
+
@TODO: reconnect on redirect flag
|
6
|
+
2. OTLogout - done
|
7
|
+
3. OTRequestTickStream (deprecated - see OTRequestTickStreamEx)
|
8
|
+
4. OTCancelTickStream - done
|
9
|
+
5. OTRequestHistData - done
|
10
|
+
6. OTCancelHistData - done
|
11
|
+
7. OTRequestListExchanges - done
|
12
|
+
8. OTRequestListSymbols
|
13
|
+
9. OTHeartBeat - done
|
14
|
+
10. OTRequestEqInit
|
15
|
+
11. OTRequestOptionChain (deprecated - see OTRequestOptionChainEx)
|
16
|
+
12. OTCancelOptionChain
|
17
|
+
13. OTRequestBookStream
|
18
|
+
14. OTCancelBookStream
|
19
|
+
15. OTRequestTickStreamEx - done
|
20
|
+
16. OTRequestOptionChainEx
|
21
|
+
17. OTRequestHistTicks - done
|
22
|
+
18. OTRequestSplits
|
23
|
+
19. OTRequestDividends
|
24
|
+
20. OTRequestHistBooks
|
25
|
+
21. OTRequestBookStreamEx
|
26
|
+
22. OTRequestOptionChainU
|
27
|
+
23. OTRequestOptionInit
|
28
|
+
24. OTRequestListSymbolsEx
|
29
|
+
25. OTRequestTickSnapshot - done
|
30
|
+
26. OTRequestOptionChainSnapshot
|
31
|
+
=end
|
32
|
+
|
33
|
+
require 'socket'
|
34
|
+
require 'logger'
|
35
|
+
require 'thread'
|
36
|
+
require 'stringio'
|
37
|
+
|
38
|
+
module OpenTick
|
39
|
+
|
40
|
+
OT_HEADER_LEN = 12
|
41
|
+
OT_COMMAND_STATUS_OK=1
|
42
|
+
OT_COMMAND_STATUS_ERROR=2
|
43
|
+
# ���� ��������
|
44
|
+
OT_TICK_TYPE_TRADE=4
|
45
|
+
OT_TICK_TYPE_QUOTE=1
|
46
|
+
OT_HIST_RAW_TICKS=1
|
47
|
+
OT_HIST_OHLC_DAILY=5
|
48
|
+
|
49
|
+
module Debug
|
50
|
+
# return current class and method name
|
51
|
+
def method_name
|
52
|
+
self.class.name + "." + caller[0][/`([^']*)'/, 1]
|
53
|
+
end # method_name
|
54
|
+
end # module
|
55
|
+
|
56
|
+
class OpenTick
|
57
|
+
include Debug
|
58
|
+
attr_accessor :sessionId
|
59
|
+
|
60
|
+
def initialize(host, port)
|
61
|
+
OTLogger.debug(method_name)
|
62
|
+
@host = host
|
63
|
+
@port = port
|
64
|
+
@server = Hash.new
|
65
|
+
@sessionId = nil
|
66
|
+
@listeners = Hash.new { |hash, key|
|
67
|
+
hash[key] = Array.new
|
68
|
+
}
|
69
|
+
self.open
|
70
|
+
end # initialize
|
71
|
+
|
72
|
+
# open TCPSocket with opentick server
|
73
|
+
# create threads for reader and heartBeat functions
|
74
|
+
def open
|
75
|
+
OTLogger.debug(method_name)
|
76
|
+
@reqId = 1
|
77
|
+
@server[:socket] = TCPSocket.open(@host, @port)
|
78
|
+
Thread.abort_on_exception = true
|
79
|
+
@server[:sync_thread] = Thread.new {
|
80
|
+
self.heart_beat
|
81
|
+
}
|
82
|
+
@server[:reader_thread] = Thread.new {
|
83
|
+
self.reader
|
84
|
+
}
|
85
|
+
end # open
|
86
|
+
|
87
|
+
def login(user, password)
|
88
|
+
self.subscribe(IncomingMessages::LoginResponse, lambda {|msg|
|
89
|
+
if msg.redirectFlag.to_i == 1
|
90
|
+
ot.reconnect(msg.redirectHost, msg.redirectHost.to_i)
|
91
|
+
else
|
92
|
+
@sessionId = msg.sessionId
|
93
|
+
end
|
94
|
+
})
|
95
|
+
self.dispatch(OutgoingMessages::LoginRequest.new(:login => user, :password => password))
|
96
|
+
# waiting for login response
|
97
|
+
while @sessionId.nil? ; end
|
98
|
+
end # login
|
99
|
+
|
100
|
+
# reconnect to new opentick server
|
101
|
+
def reconnect(host, port)
|
102
|
+
@server[:socket] = TCPSocket.open(@host, @port)
|
103
|
+
Thread.abort_on_exception = true
|
104
|
+
end
|
105
|
+
|
106
|
+
# kill reader and heart_beat threads
|
107
|
+
# close TCPSocket
|
108
|
+
def close
|
109
|
+
OTLogger.debug(method_name)
|
110
|
+
@server[:reader_thread].kill
|
111
|
+
@server[:sync_thread].kill
|
112
|
+
@server[:socket].close()
|
113
|
+
@server = Hash.new
|
114
|
+
end # close
|
115
|
+
|
116
|
+
# send message to server
|
117
|
+
def dispatch(message)
|
118
|
+
OTLogger.debug(method_name)
|
119
|
+
raise Exception.new("dispatch() must be given an OutgoingMessages::AbstractMessage subclass") unless message.is_a?(OutgoingMessages::AbstractMessage)
|
120
|
+
message.sessionId = @sessionId unless @sessionId.nil?
|
121
|
+
message.reqId = @reqId += 1
|
122
|
+
queue = message.header(@server) + message.send
|
123
|
+
@server[:socket].syswrite [queue.length].pack("l") + queue
|
124
|
+
end # dispatch
|
125
|
+
|
126
|
+
# subscribe listener(Proc) to type of message
|
127
|
+
def subscribe(messageClass, code)
|
128
|
+
OTLogger.debug(method_name)
|
129
|
+
raise(Exception.new("Invalid argument type (#{messageClass}, #{code.class}) - " +
|
130
|
+
" must be (IncomingMessages::AbstractMessage, Proc)")) unless
|
131
|
+
messageClass <= IncomingMessages::AbstractMessage && code.is_a?(Proc)
|
132
|
+
@listeners[messageClass].push(code)
|
133
|
+
end
|
134
|
+
|
135
|
+
protected
|
136
|
+
|
137
|
+
def read_from_socket( server, len=server[:len] )
|
138
|
+
buf = StringIO.new
|
139
|
+
while buf.size < len
|
140
|
+
begin
|
141
|
+
IO.select([server[:socket]])
|
142
|
+
buf.write server[:socket].readpartial(len - buf.size )
|
143
|
+
end
|
144
|
+
end
|
145
|
+
buf
|
146
|
+
end # read_from_socket
|
147
|
+
|
148
|
+
# read messages from server
|
149
|
+
# parse message
|
150
|
+
# call listeners
|
151
|
+
def reader
|
152
|
+
OTLogger.debug(method_name)
|
153
|
+
while true
|
154
|
+
# temporary buffer
|
155
|
+
buf = StringIO.new
|
156
|
+
# reading message length and message header
|
157
|
+
buf = read_from_socket( @server, OT_HEADER_LEN + 4 )
|
158
|
+
# unpacking header
|
159
|
+
msgLen, msgType, cmdStatus, cmdType, reqId = buf.string.unpack("lccxxll")
|
160
|
+
OTLogger.debug("msgLen = #{msgLen} msgType = #{IncomingMessages::Table[cmdType].name} cmdStatus = #{cmdStatus} cmdType = #{cmdType} reqId = #{reqId}")
|
161
|
+
# saving request id
|
162
|
+
if cmdStatus != OT_COMMAND_STATUS_OK
|
163
|
+
# server return error
|
164
|
+
OTLogger.error("Error command status msgLen = #{msgLen} msgType = #{msgType} cmdStatus = #{cmdStatus} cmdType = #{cmdType} reqId = #{reqId}")
|
165
|
+
# reading rest of the message
|
166
|
+
p @server[:socket].sysread(msgLen - OT_HEADER_LEN)
|
167
|
+
else
|
168
|
+
# saving message length
|
169
|
+
@server[:len] = msgLen - OT_HEADER_LEN
|
170
|
+
if IncomingMessages::Table[cmdType] != nil and msgLen > 0
|
171
|
+
msg = IncomingMessages::Table[cmdType].new( read_from_socket( @server ))
|
172
|
+
msg.reqId = @reqId
|
173
|
+
@listeners[msg.class].each { |listener|
|
174
|
+
listener.call(msg)
|
175
|
+
}
|
176
|
+
else
|
177
|
+
OTLogger.error("Error command type msgLen = #{msgLen} msgType = #{msgType} cmdStatus = #{cmdStatus} cmdType = #{cmdType} reqId = #{reqId}")
|
178
|
+
@server[:socket].sysread(msgLen - OT_HEADER_LEN - 4)
|
179
|
+
end # if IncomingMessages::Table[cmdType] != nil and msgLen > 0
|
180
|
+
end # if cmdStatus != OT_COMMAND_STATUS_OK
|
181
|
+
end # while
|
182
|
+
end # reader
|
183
|
+
|
184
|
+
# send hearbeat message every 4 seconds
|
185
|
+
def heart_beat
|
186
|
+
OTLogger.debug(method_name)
|
187
|
+
msgSync = OutgoingMessages::HeartBeat.new
|
188
|
+
while true
|
189
|
+
sleep(4)
|
190
|
+
dispatch(msgSync)
|
191
|
+
end # while
|
192
|
+
end # heartBeat
|
193
|
+
|
194
|
+
end # class OpenTick
|
195
|
+
|
196
|
+
module OutgoingMessages
|
197
|
+
|
198
|
+
OT_MSG_CLIENT_REQUEST = 1
|
199
|
+
|
200
|
+
class AbstractMessage
|
201
|
+
include Debug
|
202
|
+
|
203
|
+
def self.message_id
|
204
|
+
raise "AbstractMessage.message_id called - you need to override this in a subclass."
|
205
|
+
end
|
206
|
+
def method_missing(m, *args)
|
207
|
+
if args[0].is_a?(String)
|
208
|
+
instance_eval("@#{m}\"#{args[0]}\"")
|
209
|
+
else
|
210
|
+
instance_eval("@#{m}#{args[0]}")
|
211
|
+
end
|
212
|
+
end # method_missing
|
213
|
+
def initialize(data=nil)
|
214
|
+
OTLogger.debug("* initialize #{self.class.name}")
|
215
|
+
@data = Hash.new.replace(data) unless data == nil
|
216
|
+
end # initialize
|
217
|
+
def header(server)
|
218
|
+
[OT_MSG_CLIENT_REQUEST, OT_COMMAND_STATUS_OK, self.class.message_id, @reqId].to_a.pack("ccxxll")
|
219
|
+
end # header
|
220
|
+
end # class AbstractMessage
|
221
|
+
|
222
|
+
# OTLogin request message
|
223
|
+
# Data format is { :login => string, :password => string }
|
224
|
+
class LoginRequest < AbstractMessage
|
225
|
+
def self.message_id
|
226
|
+
1
|
227
|
+
end
|
228
|
+
def send
|
229
|
+
OTLogger.debug(method_name)
|
230
|
+
[3, 8, 4, "*"*16, 0x00.chr+0x19.chr+0x21.chr+0x2b.chr+0x14.chr+0x32.chr, @data[:login], @data[:password]].to_a.pack("sccA16A6a64a64")
|
231
|
+
end # send
|
232
|
+
end # class Login
|
233
|
+
|
234
|
+
# OTLogout request message
|
235
|
+
# Data format is { }
|
236
|
+
class LogoutRequest < AbstractMessage
|
237
|
+
def self.message_id
|
238
|
+
2
|
239
|
+
end
|
240
|
+
def send
|
241
|
+
[@data[:sessionId]].to_a.pack("a64")
|
242
|
+
end # send
|
243
|
+
end # class Logout
|
244
|
+
|
245
|
+
# OTCancelTickStream
|
246
|
+
# Data format is { :cancelId => int }
|
247
|
+
class CancelTickStreamRequest < AbstractMessage
|
248
|
+
def self.message_id
|
249
|
+
4
|
250
|
+
end
|
251
|
+
def send
|
252
|
+
[@data[:sessionId], @data[:cancelId]].to_a.pack("a64i")
|
253
|
+
end # send
|
254
|
+
end # class CancelTickStreamRequest
|
255
|
+
|
256
|
+
# OTRequestHistData request message
|
257
|
+
# Data format is { :exchange => string, :ticker => string, :from => int, :to => int, type => byte, interval => short }
|
258
|
+
class HistoryStreamRequest < AbstractMessage
|
259
|
+
def self.message_id
|
260
|
+
5
|
261
|
+
end
|
262
|
+
def send
|
263
|
+
OTLogger.debug(method_name)
|
264
|
+
[@data[:sessionId],@data[:exchange],@data[:ticker],@data[:from],@data[:to],@data[:type],@data[:interval]].to_a.pack("a64a15a15xxiicxs")
|
265
|
+
end
|
266
|
+
end # class HistoryStreamRequest
|
267
|
+
|
268
|
+
# OTCancelHistData
|
269
|
+
# Data format is { :cancelId => int }
|
270
|
+
class CancelHistDataRequest < AbstractMessage
|
271
|
+
def self.message_id
|
272
|
+
6
|
273
|
+
end
|
274
|
+
def send
|
275
|
+
[@data[:sessionId], @data[:cancelId]].to_a.pack("a64i")
|
276
|
+
end # send
|
277
|
+
end # class CancelHistDataRequest
|
278
|
+
|
279
|
+
# OTRequestListExchanges request message
|
280
|
+
# Data format is { }
|
281
|
+
class ListExchangesRequest < AbstractMessage
|
282
|
+
def self.message_id
|
283
|
+
7
|
284
|
+
end
|
285
|
+
def send
|
286
|
+
OTLogger.debug(method_name)
|
287
|
+
[@sessionId].to_a.pack("a64")
|
288
|
+
end # send
|
289
|
+
end # class ListExchangesRequest
|
290
|
+
|
291
|
+
# OTHeartBeat request message
|
292
|
+
# Data format is { }
|
293
|
+
class HeartBeat < AbstractMessage
|
294
|
+
def self.message_id
|
295
|
+
9
|
296
|
+
end
|
297
|
+
def send
|
298
|
+
OTLogger.debug(method_name)
|
299
|
+
""
|
300
|
+
end # send
|
301
|
+
end # class HeartBeat
|
302
|
+
|
303
|
+
# OTRequestTickStreamEx request message
|
304
|
+
# Data format is { :exchange => string, :ticker => string, :mask => int }
|
305
|
+
class TickStreamExRequest < AbstractMessage
|
306
|
+
def self.message_id
|
307
|
+
15
|
308
|
+
end
|
309
|
+
def send
|
310
|
+
OTLogger.debug(method_name)
|
311
|
+
[@data[:sessionId],@data[:exchange],@data[:ticker],@data[:mask]].to_a.pack("a64a15a15xxl")
|
312
|
+
end # send
|
313
|
+
end # class TickStreamEx
|
314
|
+
|
315
|
+
# OTRequestHistTicks request message
|
316
|
+
# Data format is { :exchange => string, :ticker => string, :from => int, :to => int, mask => int}
|
317
|
+
class HistTicksRequest < AbstractMessage
|
318
|
+
def self.message_id
|
319
|
+
17
|
320
|
+
end
|
321
|
+
def send
|
322
|
+
OTLogger.debug(method_name)
|
323
|
+
[@sessionId,@data[:exchange],@data[:ticker],@data[:from],@data[:to],@data[:mask]].to_a.pack("a64a15a15iii")
|
324
|
+
end # send
|
325
|
+
end # class HistTicksRequest
|
326
|
+
|
327
|
+
# OTRequestTickSnapshot request message
|
328
|
+
# Data format is { :exchange => string, :ticker => string, :mask => int }
|
329
|
+
class TickSnapshotRequest < AbstractMessage
|
330
|
+
def self.message_id
|
331
|
+
25
|
332
|
+
end
|
333
|
+
def send
|
334
|
+
OTLogger.debug(method_name)
|
335
|
+
[@data[:sessionId],@data[:exchange],@data[:ticker],@data[:mask]].to_a.pack("a64a15a15xxl")
|
336
|
+
end # send
|
337
|
+
end # class TickSnapshot
|
338
|
+
end # module OutgoiingMessage
|
339
|
+
|
340
|
+
module IncomingMessages
|
341
|
+
|
342
|
+
OT_MSG_SERVER_RESPONSE = 2
|
343
|
+
Classes = Array.new
|
344
|
+
|
345
|
+
class AbstractMessage
|
346
|
+
include Debug
|
347
|
+
attr_accessor :reqId
|
348
|
+
|
349
|
+
def self.message_id
|
350
|
+
raise "AbstractMessage.message_id called - you need to override this in a subclass."
|
351
|
+
end
|
352
|
+
def initialize(buf)
|
353
|
+
raise Exception.new("Don't use AbstractMessage directly; use the subclass for your specific message type") if self.class.name == "AbstractMessage"
|
354
|
+
self.load(buf)
|
355
|
+
end # initialize
|
356
|
+
def method_missing(m, *args)
|
357
|
+
instance_eval("@"+m.id2name)
|
358
|
+
end # method_missing
|
359
|
+
def AbstractMessage.inherited(by)
|
360
|
+
super(by)
|
361
|
+
Classes.push(by)
|
362
|
+
end # inherited
|
363
|
+
def load
|
364
|
+
raise Exception.new("Don't use AbstractMessage; override load() in a subclass.")
|
365
|
+
end # load
|
366
|
+
end # class AbstractMessage
|
367
|
+
|
368
|
+
class ErrorResponse < AbstractMessage
|
369
|
+
def self.message_id
|
370
|
+
-1
|
371
|
+
end
|
372
|
+
def load(buf)
|
373
|
+
end
|
374
|
+
end # class ErrorResponse
|
375
|
+
|
376
|
+
class LoginResponse < AbstractMessage
|
377
|
+
def self.message_id
|
378
|
+
1
|
379
|
+
end
|
380
|
+
def load(buf)
|
381
|
+
OTLogger.debug(method_name)
|
382
|
+
@sessionId, @redirectFlag, @redirectHost, @redirectHost = buf.string.unpack("a64ca64s")
|
383
|
+
end # load
|
384
|
+
end # class LoginResponse
|
385
|
+
|
386
|
+
class LogoutReponse < AbstractMessage
|
387
|
+
def self.message_id
|
388
|
+
2
|
389
|
+
end
|
390
|
+
def load
|
391
|
+
OTLogger.debug(method_name)
|
392
|
+
end # load
|
393
|
+
end # class LogoutResponse
|
394
|
+
|
395
|
+
class TickStreamResponse < AbstractMessage
|
396
|
+
def self.message_id
|
397
|
+
3
|
398
|
+
end
|
399
|
+
def load(buf)
|
400
|
+
OTLogger.debug(method_name)
|
401
|
+
@tickType, @timeStamp, @rest = buf.string.unpack("lcla*")
|
402
|
+
case @tickType.to_i
|
403
|
+
when 3
|
404
|
+
@price, @size, @volume, @sn, @indicator, @tickindicator, @flags, @exchange = @rest.unpack("diqiccca2")
|
405
|
+
when 1
|
406
|
+
@bidSize, @askSize, @bidPrice, @askPrice, @askExchange, @indicator, @tickindicator, @bidExchange, @tickExchange = @rest.unpack("iidda2cca2a2")
|
407
|
+
when 2
|
408
|
+
when 4
|
409
|
+
end
|
410
|
+
end # load
|
411
|
+
end # class RequestTickStream
|
412
|
+
|
413
|
+
class HistoryStreamResponse < AbstractMessage
|
414
|
+
def self.message_id
|
415
|
+
5
|
416
|
+
end
|
417
|
+
def load(buf)
|
418
|
+
OTLogger.debug(method_name)
|
419
|
+
@rowNum, @rest = buf.string.unpack("la*")
|
420
|
+
@data = Array.new
|
421
|
+
@rowNum.times {|i|
|
422
|
+
@data[i] = Hash.new
|
423
|
+
@data[i][:type], @data[i][:time], @rest = @rest.unpack("cia*")
|
424
|
+
case @data[i][:type]
|
425
|
+
when 50
|
426
|
+
@data[i][:openPrice], @data[i][:highPrice], @data[i][:lowPrice], @data[i][:closePrice], @data[i][:volume], @rest = @rest.unpack("ddddqa*")
|
427
|
+
when 3
|
428
|
+
@data[i][:price], @data[i][:size], @data[i][:volume], @data[i][:sn], @data[i][:indicator], @data[i][:tickInd], @data[i][:flags], @rest = @rest.unpack("diqiccca*")
|
429
|
+
end
|
430
|
+
}
|
431
|
+
end
|
432
|
+
end # class HistoryStreamResponse
|
433
|
+
|
434
|
+
class ListExchangesResponse < AbstractMessage
|
435
|
+
def self.message_id
|
436
|
+
7
|
437
|
+
end
|
438
|
+
def load(buf)
|
439
|
+
OTLogger.debug(method_name)
|
440
|
+
urlLen, @rest = buf.string.unpack("sa*")
|
441
|
+
@url, @exNum, @rest = @rest.unpack("a#{urlLen}sa*")
|
442
|
+
@data = Array.new
|
443
|
+
@exNum.times {|i|
|
444
|
+
@data[i] = Hash.new
|
445
|
+
@data[i][:code], @data[i][:availFlag], titleLen, @rest = @rest.unpack("a15csa*")
|
446
|
+
@data[i][:title], descLen, @rest = @rest.unpack("a#{titleLen}sa*")
|
447
|
+
@data[i][:desc], @rest = @rest.unpack("a#{descLen}a*")
|
448
|
+
}
|
449
|
+
end
|
450
|
+
end # class ListExchangesResponse
|
451
|
+
|
452
|
+
Table = Hash.new
|
453
|
+
Classes.each { |msg_class|
|
454
|
+
Table[msg_class.message_id] = msg_class
|
455
|
+
}
|
456
|
+
end # module IncomingMessage
|
457
|
+
|
458
|
+
OTLogger = Logger.new(STDERR)
|
459
|
+
OTLogger.level = Logger::Severity::DEBUG
|
460
|
+
|
461
|
+
def self.get_historical_quotes( login, password, symbol, exchange, type, from, to )
|
462
|
+
# create connection
|
463
|
+
ot = OpenTick.new("feed1.opentick.com", 10010)
|
464
|
+
# history response listener
|
465
|
+
ot.subscribe(IncomingMessages::HistoryStreamResponse, lambda {|msg|
|
466
|
+
if msg.rowNum == 1 and msg.data[0][:type] == 0
|
467
|
+
# recieve end data flag
|
468
|
+
ot.sessionId = nil
|
469
|
+
else
|
470
|
+
msg.rowNum.times { |i|
|
471
|
+
case msg.data[i][:type]
|
472
|
+
when 50
|
473
|
+
yield [Time.at(msg.data[i][:time]), msg.data[i][:openPrice], msg.data[i][:highPrice], msg.data[i][:lowPrice], msg.data[i][:closePrice], msg.data[i][:volume]]
|
474
|
+
end
|
475
|
+
}
|
476
|
+
end
|
477
|
+
})
|
478
|
+
# sending login request
|
479
|
+
ot.login(login, password)
|
480
|
+
# send history request
|
481
|
+
ot.dispatch(OutgoingMessages::HistoryStreamRequest.new(:sessionId => sessionId, :exchange => exchange, :ticker => symbol, :from => from, :to => to, :type => type, :interval => 1))
|
482
|
+
# waiting for end data
|
483
|
+
while not sessionId.nil? ; end
|
484
|
+
ot.close
|
485
|
+
end # get_historical_quotes
|
486
|
+
|
487
|
+
def self.get_historical_ticks( login, password, symbol, exchange, mask, from, to )
|
488
|
+
# create connection
|
489
|
+
ot = OpenTick.new("feed1.opentick.com", 10010)
|
490
|
+
# history response listener
|
491
|
+
ot.subscribe(IncomingMessages::HistoryStreamResponse, lambda {|msg|
|
492
|
+
if msg.rowNum == 1 and msg.data[0][:type] == 0
|
493
|
+
# recieve end data flag
|
494
|
+
ot.sessionId = nil
|
495
|
+
else
|
496
|
+
msg.rowNum.times { |i|
|
497
|
+
case msg.data[i][:type]
|
498
|
+
when 3
|
499
|
+
yield [msg.data[i][:time], msg.data[i][:sn], msg.data[i][:price], msg.data[i][:volume]]#, msg.data[:data][i][:size], msg.data[:data][i][:indicator], msg.data[:data][i][:tickInd], msg.data[:data][i][:flags]]
|
500
|
+
end
|
501
|
+
}
|
502
|
+
end
|
503
|
+
})
|
504
|
+
# login response listener
|
505
|
+
ot.login(login, password)
|
506
|
+
# send history request
|
507
|
+
ot.dispatch(OutgoingMessages::HistTicksRequest.new(:exchange => exchange, :ticker => symbol, :from => from, :to => to, :mask => mask))
|
508
|
+
# waiting for end data
|
509
|
+
while not ot.sessionId.nil? ; end
|
510
|
+
ot.close
|
511
|
+
end # get_historical_ticks
|
512
|
+
|
513
|
+
def self.get_exchange_list(login, password)
|
514
|
+
# create connection
|
515
|
+
ot = OpenTick.new("feed1.opentick.com", 10010)
|
516
|
+
# history response listener
|
517
|
+
ot.subscribe(IncomingMessages::ListExchangesResponse, lambda {|msg|
|
518
|
+
(msg.data.select {|x| x[:availFlag] == 1}).each { |x| yield [x[:title].strip, x[:code].strip]}
|
519
|
+
ot.sessionId = nil
|
520
|
+
})
|
521
|
+
# sending login request
|
522
|
+
ot.login(login, password)
|
523
|
+
# send history request
|
524
|
+
ot.dispatch(OutgoingMessages::ListExchangesRequest.new)
|
525
|
+
# waiting for end data
|
526
|
+
while not ot.sessionId.nil? ; end
|
527
|
+
ot.close
|
528
|
+
end
|
529
|
+
|
530
|
+
end # module OpenTick
|
531
|
+
|
532
|
+
if $0 == __FILE__
|
533
|
+
|
534
|
+
login = 'test_opentick'
|
535
|
+
password = '123123'
|
536
|
+
|
537
|
+
#OpenTick.get_historical_quotes(login,password,"GOOG", "Q", 1, Time.now.to_i-24*3600, Time.now.to_i) { |msg| p msg}
|
538
|
+
|
539
|
+
#OpenTick.get_historical_ticks(login, password,"GOOG", "Q", 4, Time.now.to_i-24*3600, Time.now.to_i) { |msg| p msg}
|
540
|
+
|
541
|
+
OpenTick.get_exchange_list(login, password) {|x| p x}
|
542
|
+
|
543
|
+
end
|
data/opentick.gemspec
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
SPEC = Gem::Specification.new do |s|
|
4
|
+
s.name = "opentick-ruby"
|
5
|
+
s.version = "0.1.1"
|
6
|
+
s.platform = Gem::Platform::RUBY
|
7
|
+
s.summary = "Ruby implementation for Opentick API"
|
8
|
+
s.files = Dir["./*"] + Dir["*/**"]
|
9
|
+
s.require_path = 'lib'
|
10
|
+
s.extra_rdoc_files = ["README", "ChangeLog"]
|
11
|
+
s.author = "Timur Adigamov"
|
12
|
+
s.email = "timur at adigamov dot com"
|
13
|
+
s.homepage = "http://www.tradeindexfuture.com"
|
14
|
+
end
|
15
|
+
|
16
|
+
if $0==__FILE__
|
17
|
+
p SPEC
|
18
|
+
Gem.manage_gems
|
19
|
+
Gem::Builder.new(SPEC).build
|
20
|
+
end
|
metadata
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.4
|
3
|
+
specification_version: 1
|
4
|
+
name: opentick-ruby
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.1.1
|
7
|
+
date: 2007-11-08 00:00:00 +03:00
|
8
|
+
summary: Ruby implementation for Opentick API
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: timur at adigamov dot com
|
12
|
+
homepage: http://www.tradeindexfuture.com
|
13
|
+
rubyforge_project:
|
14
|
+
description:
|
15
|
+
autorequire:
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: false
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- Timur Adigamov
|
31
|
+
files:
|
32
|
+
- ./ChangeLog
|
33
|
+
- ./doc
|
34
|
+
- ./lib
|
35
|
+
- ./opentick.gemspec
|
36
|
+
- ./README
|
37
|
+
- doc/classes
|
38
|
+
- doc/created.rid
|
39
|
+
- doc/files
|
40
|
+
- doc/fr_class_index.html
|
41
|
+
- doc/fr_file_index.html
|
42
|
+
- doc/fr_method_index.html
|
43
|
+
- doc/index.html
|
44
|
+
- doc/rdoc-style.css
|
45
|
+
- lib/opentick.rb
|
46
|
+
- README
|
47
|
+
- ChangeLog
|
48
|
+
test_files: []
|
49
|
+
|
50
|
+
rdoc_options: []
|
51
|
+
|
52
|
+
extra_rdoc_files:
|
53
|
+
- README
|
54
|
+
- ChangeLog
|
55
|
+
executables: []
|
56
|
+
|
57
|
+
extensions: []
|
58
|
+
|
59
|
+
requirements: []
|
60
|
+
|
61
|
+
dependencies: []
|
62
|
+
|