orders 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,24 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+ log
21
+ .idea
22
+ .bundle
23
+
24
+ ## PROJECT::SPECIFIC
data/HISTORY ADDED
@@ -0,0 +1,11 @@
1
+ == 0.0.0 / 2011-03-18
2
+
3
+ * Birthday!
4
+
5
+ == 0.0.1 / 2011-03-18
6
+
7
+ * Structure created
8
+
9
+ == 0.0.2 / 2011-03-19
10
+
11
+ * Namespace renamed to Orders
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Arvicco
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,26 @@
1
+ = orders
2
+ by:: Arvicco
3
+ url:: http://github.com/arvicco/orders
4
+
5
+ == DESCRIPTION:
6
+
7
+ Basic structures used to create DOM models.
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ Enclosed structures are used to accumulate, analyse and visualize streams of market
12
+ order data (either in aggregated or full order log form). They are required by the
13
+ client and gateway modules that deal with market order data streams and derived
14
+ artefacts (such as OrderBooks).
15
+
16
+ Data structures need to be:
17
+ 1) memory-efficient
18
+ 2) thread-safe (without too much synchronization penalty)
19
+ 3) iteration-safe (adding new element while iterating should not raise exception)
20
+
21
+ == INSTALL:
22
+
23
+ $ sudo gem install order_book
24
+
25
+ == LICENSE:
26
+ Copyright (c) 2011 Arvicco. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,25 @@
1
+ begin
2
+ require 'rake'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ gem 'rake', '~> 0.8.3.1'
6
+ require 'rake'
7
+ end
8
+
9
+ require 'pathname'
10
+
11
+ BASE_PATH = Pathname.new(__FILE__).dirname
12
+ LIB_PATH = BASE_PATH + 'lib'
13
+ PKG_PATH = BASE_PATH + 'pkg'
14
+ DOC_PATH = BASE_PATH + 'rdoc'
15
+
16
+ $LOAD_PATH.unshift LIB_PATH.to_s
17
+ require 'version'
18
+
19
+ NAME = 'orders'
20
+ CLASS_NAME = Orders
21
+
22
+ # Load rakefile tasks
23
+ Dir['tasks/*.rake'].sort.each { |file| load file }
24
+
25
+ # Project-specific tasks
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.2
@@ -0,0 +1,9 @@
1
+ Feature: something something
2
+ In order to something something
3
+ A user something something
4
+ something something something
5
+
6
+ Scenario: something something
7
+ Given inspiration
8
+ When I create a sweet new gem
9
+ Then everyone should see how awesome I am
File without changes
@@ -0,0 +1,10 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
2
+
3
+ require 'pathname'
4
+ require 'bundler'
5
+ Bundler.setup
6
+ Bundler.require :cucumber
7
+
8
+ require 'order_book'
9
+
10
+ BASE_PATH = Pathname.new(__FILE__).dirname + '../..'
@@ -0,0 +1,12 @@
1
+ module SystemHelper
2
+
3
+ def windows?
4
+ RUBY_PLATFORM =~ /mswin|windows|mingw/ || cygwin?
5
+ end
6
+
7
+ def cygwin?
8
+ RUBY_PLATFORM =~ /cygwin/
9
+ end
10
+ end
11
+
12
+ World(WinGui, SystemHelper)
data/lib/legacy.rb ADDED
@@ -0,0 +1,443 @@
1
+ # Legacy VCL-based code to be converted into new efficient Ruby code
2
+
3
+ module VCL
4
+
5
+ #type
6
+ # tDuplicates = [:dup_accept, :dup_ignore, :dup_replace]
7
+ # // ������� ����� "������" � ���������� ��������������� ������������ ���������
8
+ #type CustomList = class(tList)
9
+ # procedure clear; override;
10
+ # procedure freeitem(item: pointer); virtual; abstract;
11
+ # procedure freeall; virtual;
12
+ # procedure delete(index: longint); virtual;
13
+ # procedure remove(item: pointer); virtual;
14
+ # end;
15
+ class CustomList < Array
16
+
17
+ def clear
18
+ (0...size).each { freeitem(self[i]) }
19
+ super
20
+ end
21
+
22
+ def freeall
23
+ clear
24
+ end
25
+
26
+ def freeitem item
27
+ end
28
+
29
+ # Standard #delete_at instead of #delete
30
+
31
+ # Deletes ALL items from arr that are equal to obj.?
32
+ # No, we need to remove ONE item by "pointer"
33
+ def remove item #(item: pointer)
34
+ freeitem item
35
+ delete item
36
+ end
37
+ end # class CustomList
38
+
39
+ # // ������� ����� "������������� ������"
40
+ #type tSortedList = class(CustomList)
41
+ # fDuplicates : tDuplicates;
42
+ # constructor create;
43
+ # function checkitem(item: pointer): boolean; virtual; abstract;
44
+ # function compare(item1, item2: pointer): longint; virtual; abstract;
45
+ # function search(item: pointer; var index: longint): boolean; virtual;
46
+ # procedure add(item: pointer); virtual;
47
+ # procedure insert(index: longint; item: pointer); virtual;
48
+ # end;
49
+ class SortedList < CustomList
50
+
51
+ attr_accessor :duplicates
52
+
53
+ def initialize
54
+ @duplicates = :dup_accept
55
+ super
56
+ end
57
+
58
+ # Returns true and item's index if item is in the List
59
+ # Returns false and item's index if item not found
60
+ def search item #(item: pointer; var index: longint): boolean
61
+ result = false
62
+ l = 0
63
+ h = size - 1
64
+ while (l <= h) do
65
+ i = (l + h) >> 1
66
+ case compare(self[i], item)
67
+ when -1
68
+ l = i + 1
69
+ when 1
70
+ h = i - 1
71
+ when 0
72
+ h = i - 1
73
+ result = true
74
+ l = i if @duplicates == :dup_ignore || @duplicates == :dup_replace
75
+ end
76
+ end
77
+ index = l
78
+ [result, index]
79
+ end
80
+
81
+ def add item #(item: pointer)
82
+ if checkitem(item)
83
+ result, index = search(item)
84
+ if result
85
+ case @duplicates
86
+ when :dup_accept
87
+ insert(index, item)
88
+ when :dup_ignore
89
+ freeitem(item)
90
+ when :dup_replace
91
+ freeitem(self[index])
92
+ self[index] = item
93
+ end
94
+ else
95
+ insert(index, item)
96
+ end
97
+ else
98
+ freeitem(item)
99
+ end
100
+ end
101
+
102
+ def insert index, item #(index: longint; item: pointer)
103
+ if checkitem(item)
104
+ super index, item
105
+ end
106
+ end
107
+ end # class SortedList
108
+
109
+ # // ������ ������� �� ����
110
+ #type tOrderBook = class(tSortedList)
111
+ # private
112
+ # fisin_id : longint;
113
+ # fchanged : boolean;
114
+ # public
115
+ # procedure freeitem(item: pointer); override;
116
+ # function checkitem(item: pointer): boolean; override;
117
+ # function compare(item1, item2: pointer): longint; override;
118
+ #
119
+ # procedure add(item: pointer); override;
120
+ # procedure remove(item: pointer); override;
121
+ #
122
+ # property isin_id: longint read fisin_id;
123
+ # property changed: boolean read fchanged write fchanged;
124
+ # end;
125
+ class OrderBook < SortedList
126
+ attr_accessor :isin_id, :changed
127
+
128
+ def initialize isin_id
129
+ @isin_id = isin_id
130
+ super()
131
+ end
132
+
133
+ def checkitem item #(item: pointer): boolean
134
+ item.price > 0
135
+ end
136
+
137
+ def compare item1, item2 #(item1, item2: pointer): longint
138
+ item1.price <=> item2.price
139
+ end
140
+
141
+ def add item #(item: pointer)
142
+ super item
143
+ @changed = true
144
+ end
145
+
146
+ def remove item #(item: pointer)
147
+ super item
148
+ @changed = true
149
+ end
150
+ end # class OrderBook
151
+
152
+ # // ������ ��������
153
+ #type tPriceLists = class(tSortedList)
154
+ # private
155
+ # tmp_ordbook : tOrderBook;
156
+ # public
157
+ # destructor destroy; override;
158
+ # procedure freeitem(item: pointer); override;
159
+ # function checkitem(item: pointer): boolean; override;
160
+ # function compare(item1, item2: pointer): longint; override;
161
+ # function searchadditem(isin_id: longint): tOrderBook;
162
+ # end;
163
+ #
164
+ class OrderBookList < SortedList
165
+
166
+ def checkitem item #(item: pointer): boolean
167
+ item
168
+ end
169
+
170
+ def compare(item1, item2) #(item1, item2: pointer): longint
171
+ item1.isin_id <=> item2.isin_id;
172
+ end
173
+
174
+ def searchadditem(isin_id) #(isin_id: longint): OrderBook
175
+ order_book = OrderBook.new(isin_id)
176
+ exists, idx = search(order_book)
177
+ if exists
178
+ result = self[idx]
179
+ else
180
+ result = order_book
181
+ insert(idx, result)
182
+ end
183
+ result
184
+ end
185
+
186
+ end # class OrderBook
187
+
188
+ # // ����� ������� ���������
189
+ #type OrderList = class(tSortedList)
190
+ # fOrderBooks : tPriceLists;
191
+ # constructor create;
192
+ # destructor destroy; override;
193
+ # procedure freeitem(item: pointer); override;
194
+ # function checkitem(item: pointer): boolean; override;
195
+ # function compare(item1, item2: pointer): longint; override;
196
+ # function searchadditem(isin_id: longint): tOrderBook;
197
+ # function addrecord(isin_id: longint; const id, rev: int64; const price, volume: double; buysell: longint): boolean;
198
+ # function delrecord(const id: int64): boolean;
199
+ # procedure clearbyrev(const rev: int64);
200
+ # end;
201
+ class OrderList < SortedList
202
+ attr_accessor :order_books
203
+
204
+ def initialize
205
+ super
206
+ @order_books = OrderBookList.new
207
+ end
208
+
209
+ def freeitem item #(item: pointer)
210
+ item.order_book.remove(item) if item.order_book
211
+ end
212
+
213
+ def checkitem item #(item: pointer): boolean
214
+ item
215
+ end
216
+
217
+ def compare(item1, item2) #: pointer): longint
218
+ item1.id <=> item2.id
219
+ end
220
+
221
+ def searchadditem isin_id #(isin_id: longint): OrderBook
222
+ @order_books.searchadditem(isin_id)
223
+ end
224
+
225
+ def addrecord isin_id, id, rev, price, volume, buysell #(isin_id: longint; const id, rev: int64; const price, volume: double; buysell: longint): boolean
226
+ item = OrderBookItem.new
227
+ item.id = id
228
+ result, idx = search(item)
229
+ if result
230
+ item = self[idx]
231
+
232
+ if item.price != price # �������, ��� ���� ����������
233
+ item.order_book.remove(item) if item.order_book # ������� �� �������
234
+ if price > 0
235
+ item.order_book = searchadditem(isin_id) unless item.order_book
236
+ item.order_book.add(item) if item.order_book # ��������� � ������
237
+ else
238
+ item.order_book = nil;
239
+ end
240
+ end
241
+
242
+ item.rev = rev
243
+ item.price = price
244
+ item.volume = volume
245
+ item.buysell = buysell
246
+ else
247
+ item.rev = rev
248
+ item.price = price
249
+ item.volume = volume
250
+ item.buysell = buysell
251
+
252
+ if (item.price > 0)
253
+ item.order_book = searchadditem(isin_id)
254
+ item.order_book.add(item) if item.order_book # ��������� � ������
255
+ else
256
+ item.order_book = nil
257
+ end
258
+ insert(idx, item) # ��������� � ����� �������
259
+ end
260
+ end
261
+
262
+ def delrecord id #(const id: int64): boolean
263
+ item = OrderBookItem.new
264
+ item.id = id
265
+ result, idx = search(item)
266
+ delete_at(idx) if result # ������� �� ����� �������
267
+ end
268
+
269
+ # Delete all records with rev less than given
270
+ def clearbyrev rev #(const rev: int64)
271
+ (size-1).downto(0) do |i|
272
+ delete_at(i) if self[i].rev < rev # ������� �� ����� �������
273
+ end
274
+ end
275
+
276
+ end #class OrderList
277
+
278
+ # // ������� "������ � �������"
279
+ #type pOrderBookItem = ^tOrderBookItem;
280
+ # tOrderBookItem = record
281
+ # id : int64;
282
+ # rev : int64;
283
+ # price : double; // ����
284
+ # volume : double; // ���-��
285
+ # buysell : longint; // �������(1)/�������(2)
286
+ # order_book : tOrderBook;
287
+ # end;
288
+ class OrderBookItem
289
+ attr_accessor :id, :rev, :price, :volume, :buysell, :order_book
290
+
291
+ def inspect
292
+ "#{id}:#{price}>#{volume}#{buysell == 1 ? '+' : '-'}"
293
+ end
294
+
295
+ alias to_s inspect
296
+ end
297
+
298
+ #######################
299
+ # New hierarchy:
300
+ #######################
301
+
302
+ # Abstract (equivalent of SortedList)
303
+ # ������� ����� "������������� ������"
304
+ class SortedHash < Hash
305
+
306
+ def free item
307
+ end
308
+
309
+ def check item
310
+ true
311
+ end
312
+
313
+ def index item
314
+ item.object_id
315
+ end
316
+
317
+ # Adds new item only if it passes check...
318
+ # TODO: What to do with the item it should have replaced?!
319
+ def add item
320
+ self[index item] = item if check item
321
+ # check item ? super : free key # delete key
322
+ end
323
+
324
+ def remove item
325
+ free item
326
+ delete index item
327
+ end
328
+
329
+ def clear
330
+ each_value { |item| free item }
331
+ super
332
+ end
333
+ end # SortedHash
334
+
335
+ # Represents DOM (OrderBook) for one security
336
+ # ������ ������� �� ����
337
+ class DOM < SortedHash
338
+ attr_accessor :isin_id, :changed
339
+
340
+ def initialize isin_id
341
+ @isin_id = isin_id
342
+ @changed = false
343
+ super
344
+ end
345
+
346
+ def index item
347
+ item.price
348
+ end
349
+
350
+ def check item
351
+ item.price > 0
352
+ end
353
+
354
+ def add item
355
+ @changed = true # Marking DOM as changed
356
+ super
357
+ end
358
+
359
+ def remove item
360
+ @changed = true # Marking DOM as changed
361
+ super
362
+ end
363
+ end # class DOM
364
+
365
+
366
+ # Represents Hash of DOMs (OrderBooks) indexed by isin_id
367
+ # ������ ��������
368
+ class DOMHash < SortedHash
369
+
370
+ def index item
371
+ item.isin_id
372
+ end
373
+
374
+ # Always return DOM for isin_id, create one on spot if need be
375
+ def [] isin_id
376
+ super || add(DOM.new isin_id)
377
+ end
378
+ end # class DOMHash
379
+
380
+ # Represents Hash of all aggregated orders by (repl) id
381
+ # ����� ������� ���������
382
+ class OrderHash < SortedHash
383
+ attr_accessor :order_books
384
+
385
+ def index item
386
+ item.id
387
+ end
388
+
389
+ def initialize
390
+ super
391
+ @order_books = DOMHash.new
392
+ end
393
+
394
+ # We need to clear item from its order book before scrapping it
395
+ def free item
396
+ item.order_book.remove item if item.order_book
397
+ end
398
+
399
+ # Rebooks item to a correct order book, given its price
400
+ def rebook item, book
401
+ if (item.price > 0)
402
+ # item represents new aggr_order with price
403
+ item.order_book = book unless item.order_book
404
+ book.add item # ��������� � ������
405
+ else
406
+ # item clears previous aggr_order for given price
407
+ item.order_book = nil
408
+ end
409
+ end
410
+
411
+ # process_record
412
+ def addrecord isin_id, id, rev, price, volume, buysell
413
+ item = self[id] || OrderBookItem.new
414
+
415
+ price_changed = item.price != price # �������, ��� ���� ����������
416
+
417
+ item.id = id
418
+ item.rev = rev
419
+ item.price = price
420
+ item.volume = volume
421
+ item.buysell = buysell
422
+
423
+ if price_changed
424
+ if self[id] # item is already here
425
+ item.order_book.remove item if item.order_book # free item - ������� �� �������
426
+ else # new item
427
+ add item
428
+ end
429
+ rebook item, @order_books[isin_id]
430
+ end
431
+ end
432
+
433
+ def delrecord id
434
+ remove self[id] if self[id]
435
+ end
436
+
437
+ # Clear all records with rev less than given
438
+ def clearbyrev rev #(const rev: int64)
439
+ each_value { |item| remove item if item.rev < rev } # ������� �� ����� �������
440
+ end
441
+ end # class OrderHash
442
+
443
+ end # module