orders 0.0.2

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/lib/orders.rb ADDED
@@ -0,0 +1,9 @@
1
+ require 'version'
2
+ require 'rubygems'
3
+ require 'bundler/setup'
4
+ Bundler.require(:default)
5
+
6
+ require 'orders/indexed_list'
7
+ require 'orders/order_book_item'
8
+ require 'orders/order_book'
9
+ require 'orders/order_list'
@@ -0,0 +1,44 @@
1
+ module Orders
2
+ # Abstract (equivalent of SortedList)
3
+ # ������� ����� "������������� ������"
4
+ class IndexedList < Hash
5
+
6
+ # Returns default list index for items
7
+ def index item
8
+ item.object_id
9
+ end
10
+
11
+ # Adds new item to the list (replaces item with the same index)
12
+ def add item
13
+ self[index item] = item
14
+ self
15
+ end
16
+
17
+ alias << add
18
+
19
+ # Removes item from the list
20
+ def remove item
21
+ delete index item
22
+ self
23
+ end
24
+
25
+ # Calls #remove for each item in list
26
+ def clear
27
+ each_value { |item| remove item }
28
+ end
29
+
30
+ # Yields list items in order of their index
31
+ def each
32
+ if block_given?
33
+ keys.sort.each { |key| yield self[key] }
34
+ else
35
+ ary = []
36
+ keys.sort.each { |key| ary << self[key] }
37
+ ary
38
+ end
39
+ end
40
+
41
+ # Make direct setter private
42
+ private :[]=
43
+ end
44
+ end
@@ -0,0 +1,33 @@
1
+ module Orders
2
+ # Represents DOM (OrderBook) for one security
3
+ # ������ ������� �� ����
4
+ class OrderBook < IndexedList
5
+
6
+ attr_accessor :isin_id, :changed
7
+
8
+ def initialize isin_id
9
+ @isin_id = isin_id
10
+ @changed = true
11
+ super()
12
+ end
13
+
14
+ def index item
15
+ item.price
16
+ end
17
+
18
+ def add item
19
+ if item.price > 0
20
+ @changed = true # Marking DOM as changed
21
+ super
22
+ else
23
+ self
24
+ end
25
+ end
26
+
27
+ # Does not call super!
28
+ def remove item
29
+ @changed = true if delete index item # Marking DOM as changed
30
+ self
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,19 @@
1
+ module Orders
2
+ # Represents single price level for OrderBook for one security
3
+ # (aggregate bid or ask with aggregate volume)
4
+ # // ������� "������ � �������"
5
+ # tOrderBookItem = record
6
+ # id : int64;
7
+ # rev : int64;
8
+ # price : double; // ����
9
+ # volume : double; // ���-��
10
+ # buysell : longint; // �������(1)/�������(2)
11
+ # order_book : tOrderBook;
12
+ class OrderBookItem
13
+ attr_accessor :isin_id, :id, :rev, :price, :volume, :buysell, :order_book
14
+
15
+ def initialize opts = {}
16
+ opts.each {|key, value| send "#{key}=", value}
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,23 @@
1
+ require 'orders/order_book'
2
+
3
+ module Orders
4
+ # Represents DOM (OrderBook) for one security
5
+ # ������ ������� �� ����
6
+ class OrderList < IndexedList
7
+ attr_accessor :order_books
8
+
9
+ def initialize
10
+ @order_books = {}
11
+ super
12
+ end
13
+
14
+ def index item
15
+ item.id
16
+ end
17
+
18
+ def add item
19
+ @order_books[item.isin_id] ||= Orders::OrderBook.new item.isin_id
20
+ super
21
+ end
22
+ end
23
+ end
data/lib/version.rb ADDED
@@ -0,0 +1,8 @@
1
+ require 'pathname'
2
+
3
+ module Orders
4
+
5
+ VERSION_FILE = Pathname.new(__FILE__).dirname + '../VERSION' # :nodoc:
6
+ VERSION = VERSION_FILE.exist? ? VERSION_FILE.read.strip : nil
7
+
8
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+ require 'orders/shared_examples.rb'
3
+
4
+ describe Orders::IndexedList do
5
+ subject { Orders::IndexedList.new }
6
+ let(:item_index) { @item.object_id }
7
+
8
+ before(:each) do
9
+ @item = Object.new
10
+ @item1 = Object.new
11
+ end
12
+
13
+ it_behaves_like 'index_list'
14
+ end
15
+
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ describe Orders::OrderBookItem do
4
+ describe '#new with empty initializer' do
5
+ subject { Orders::OrderBookItem.new }
6
+
7
+ its (:isin_id) {should == nil}
8
+ its (:id) {should == nil}
9
+ its (:rev) {should == nil}
10
+ its (:price) {should == nil}
11
+ its (:volume) {should == nil}
12
+ its (:buysell) {should == nil}
13
+ its (:order_book) {should == nil}
14
+ end
15
+
16
+ describe '#new with opts' do
17
+ subject { Orders::OrderBookItem.new :isin_id => 1234567,
18
+ :id => 12,
19
+ :rev => 123,
20
+ :price => 1234,
21
+ :volume => 12345,
22
+ :buysell => 1,
23
+ :order_book => 123456
24
+ }
25
+
26
+ its (:isin_id) {should == 1234567}
27
+ its (:id) {should == 12}
28
+ its (:rev) {should == 123}
29
+ its (:price) {should == 1234}
30
+ its (:volume) {should == 12345}
31
+ its (:buysell) {should == 1}
32
+ its (:order_book) {should == 123456}
33
+ end
34
+ end
35
+
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+ require 'orders/shared_examples.rb'
3
+
4
+ describe Orders::OrderBook do
5
+ subject { Orders::OrderBook.new 123456 }
6
+ let(:item_index) { @item.price }
7
+
8
+ before(:each) do
9
+ @item = Orders::OrderBookItem.new :id => 0, :price => 20
10
+ @item1 = Orders::OrderBookItem.new :id => 1, :price => 10
11
+ @zero_price_item = Orders::OrderBookItem.new :id => 2, :price => 0
12
+ end
13
+
14
+ it_behaves_like 'index_list'
15
+
16
+ its (:isin_id) {should == 123456}
17
+ its (:changed) {should == true}
18
+
19
+ describe 'adding item' do
20
+ before(:each) do
21
+ subject.add(@item).size.should == 1
22
+ subject.changed = false
23
+ end
24
+
25
+ context 'with zero price' do
26
+ it 'returns self' do
27
+ subject.add(@zero_price_item).should == subject
28
+ end
29
+
30
+ it 'does not add such item to the list' do
31
+ subject.add(@zero_price_item)
32
+ subject[subject.index @zero_price_item].should == nil
33
+ subject.size.should == 1
34
+ end
35
+
36
+ it 'does not set changed status to true' do
37
+ subject.add(@zero_price_item)
38
+ subject.changed.should == false
39
+ end
40
+ end
41
+
42
+ it 'sets changed status to true if item was added' do
43
+ subject.add(@item1)
44
+ subject.changed.should == true
45
+ end
46
+
47
+ end
48
+
49
+ describe 'removing item' do
50
+ before(:each) do
51
+ subject.add(@item).size.should == 1
52
+ subject.changed = false
53
+ end
54
+
55
+ it 'sets changed status to true if item was removed' do
56
+ subject.remove(@item)
57
+ subject.changed.should == true
58
+ end
59
+
60
+ context 'that is not in list' do
61
+
62
+ it 'returns self' do
63
+ subject.remove(@item1).should == subject
64
+ end
65
+
66
+ it 'does not set changed status to true' do
67
+ subject.remove(@item1)
68
+ subject.changed.should == false
69
+ end
70
+ end
71
+ end
72
+ end
73
+
@@ -0,0 +1,84 @@
1
+ require 'spec_helper'
2
+ require 'spec_helper'
3
+ require 'orders/shared_examples.rb'
4
+
5
+ #noinspection RubyResolve
6
+ describe Orders::OrderList do
7
+ subject { Orders::OrderList.new }
8
+ let(:item_index) { @item.id }
9
+
10
+ before(:each) do
11
+ @item = Orders::OrderBookItem.new :id => 0, :price => 20
12
+ @item1 = Orders::OrderBookItem.new :id => 1, :price => 10
13
+ @zero_price_item = Orders::OrderBookItem.new :id => 2, :price => 0
14
+ @repeat_zero_price_item = Orders::OrderBookItem.new :id => 0, :price => 0
15
+ end
16
+
17
+ it_behaves_like 'index_list'
18
+
19
+ specify { subject.order_books.should be_empty }
20
+
21
+ describe 'adding item' do
22
+ context 'to empty OrderList' do
23
+ it 'creates appropriate order book' do
24
+ subject.add(@item)
25
+ subject.order_books.should_not be_empty
26
+ subject.order_books[@item.isin_id].should be_an Orders::OrderBook
27
+ subject.order_books.should have(1).book
28
+ end
29
+
30
+ end
31
+
32
+ context 'to non-empty OrderList' do
33
+ before(:each) do
34
+ subject.add(@item).size.should == 1
35
+ end
36
+ end
37
+ # context 'with zero price' do
38
+ # it 'returns self' do
39
+ # subject.add(@zero_price_item).should == subject
40
+ # end
41
+ #
42
+ # it 'does not add such item to the list' do
43
+ # subject.add(@zero_price_item)
44
+ # subject[subject.index @zero_price_item].should == nil
45
+ # subject.size.should == 1
46
+ # end
47
+ #
48
+ # it 'does not set changed status to true' do
49
+ # subject.add(@zero_price_item)
50
+ # subject.changed.should == false
51
+ # end
52
+ # end
53
+ #
54
+ it 'sets changed status to true if item was added' do
55
+ subject.add(@item1)
56
+ end
57
+
58
+ end
59
+
60
+ describe 'removing item' do
61
+ # before(:each) do
62
+ # subject.add(@item).size.should == 1
63
+ ## @item.order_book?
64
+ # end
65
+ #
66
+ # it 'sets changed status to true if item was removed' do
67
+ # subject.remove(@item)
68
+ # subject.changed.should == true
69
+ # end
70
+ #
71
+ # context 'that is not in list' do
72
+ #
73
+ # it 'returns self' do
74
+ # subject.remove(@item1).should == subject
75
+ # end
76
+ #
77
+ # it 'does not set changed status to true' do
78
+ # subject.remove(@item1)
79
+ # subject.changed.should == false
80
+ # end
81
+ # end
82
+ end
83
+ end
84
+
@@ -0,0 +1,106 @@
1
+ shared_examples_for 'index_list' do
2
+
3
+ describe 'items get/set' do
4
+ it 'returns item from list by their index' do
5
+ subject.add(@item)[item_index].should == @item
6
+ end
7
+
8
+ it 'returns nil when item with requested index not in collection' do
9
+ subject[item_index].should == nil
10
+ end
11
+
12
+ it 'is not possible to add item into collection directly' do
13
+ expect { subject[item_index] = @item }.to raise_error NoMethodError
14
+ end
15
+ end
16
+
17
+ describe '#index' do
18
+ it 'indexes arbitrary items by their index (redefined in subclasses)' do
19
+ subject.index(@item).should == item_index
20
+ end
21
+ end
22
+
23
+ describe '#add' do
24
+ it 'returns self for easy method chaining' do
25
+ subject.add(@item).should == subject
26
+ end
27
+
28
+ it 'adds items to indexed list' do
29
+ subject.add(@item)
30
+ subject.values.should include @item
31
+ subject[item_index].should == @item
32
+ subject.size.should == 1
33
+ end
34
+
35
+ it 'adds items to using alias <<' do
36
+ subject << @item
37
+ subject.values.should include @item
38
+ subject[item_index].should == @item
39
+ subject.size.should == 1
40
+ end
41
+ end
42
+
43
+ describe '#remove' do
44
+ before(:each) { subject.add(@item).add(@item1).size.should == 2 }
45
+
46
+ it 'returns self for easy method chaining' do
47
+ subject.remove(@item).should == subject
48
+ end
49
+
50
+ it 'removes item from indexed list' do
51
+ subject.remove(@item)
52
+ subject.values.should_not include @item
53
+ subject[item_index].should == nil
54
+ subject.size.should == 1
55
+ end
56
+ end
57
+
58
+ describe '#clear' do
59
+ before(:each) { subject.add(@item).add(@item1) }
60
+
61
+ it 'removes all items from list' do
62
+ subject.clear
63
+ subject.should be_empty
64
+ end
65
+
66
+ it 'ensures that #remove method is called once for each item in list' do
67
+ subject.should_receive(:remove).twice
68
+ subject.clear
69
+ end
70
+ end
71
+
72
+ describe '#each' do
73
+ before(:each) { subject.add(@item).add(@item1) }
74
+
75
+ it 'yields items from list in index order' do
76
+ @count = 0
77
+ subject.each do |item|
78
+ @count += 1
79
+ case @count
80
+ when 1
81
+ if subject.index(@item) < subject.index(@item1)
82
+ item.should == @item
83
+ else
84
+ item.should == @item1
85
+ end
86
+ when 2
87
+ if subject.index(@item) < subject.index(@item1)
88
+ item.should == @item1
89
+ else
90
+ item.should == @item
91
+ end
92
+ end
93
+ end
94
+ @count.should == 2
95
+ end
96
+
97
+ it 'returns list item in array, sorted by their index, if no block given' do
98
+ if subject.index(@item) < subject.index(@item1)
99
+ subject.each.should == [@item, @item1]
100
+ else
101
+ subject.each.should == [@item1, @item]
102
+ end
103
+ end
104
+ end
105
+ end
106
+