fin 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/.gitignore +26 -0
- data/HISTORY +27 -0
- data/LICENSE +20 -0
- data/README.rdoc +36 -0
- data/Rakefile +25 -0
- data/VERSION +1 -0
- data/features/order_book.feature +9 -0
- data/features/step_definitions/order_book_steps.rb +0 -0
- data/features/support/env.rb +10 -0
- data/features/support/world.rb +12 -0
- data/lib/fin.rb +13 -0
- data/lib/fin/book.rb +50 -0
- data/lib/fin/book_manager.rb +42 -0
- data/lib/fin/changed_list.rb +49 -0
- data/lib/fin/container_list.rb +33 -0
- data/lib/fin/deal_list.rb +18 -0
- data/lib/fin/indexed_list.rb +74 -0
- data/lib/fin/models/deal.rb +75 -0
- data/lib/fin/models/instrument.rb +78 -0
- data/lib/fin/models/model.rb +39 -0
- data/lib/fin/models/money_limit.rb +81 -0
- data/lib/fin/models/order.rb +45 -0
- data/lib/fin/models/position.rb +57 -0
- data/lib/fin/order_list.rb +17 -0
- data/lib/legacy.rb +443 -0
- data/lib/version.rb +8 -0
- data/spec/fin/book_spec.rb +215 -0
- data/spec/fin/changed_list_spec.rb +16 -0
- data/spec/fin/container_list_spec.rb +63 -0
- data/spec/fin/deal_list_spec.rb +102 -0
- data/spec/fin/indexed_list_spec.rb +20 -0
- data/spec/fin/models/deal_spec.rb +140 -0
- data/spec/fin/models/instrument_spec.rb +54 -0
- data/spec/fin/models/model_spec.rb +109 -0
- data/spec/fin/models/money_limit_spec.rb +143 -0
- data/spec/fin/models/order_spec.rb +67 -0
- data/spec/fin/models/position_spec.rb +74 -0
- data/spec/fin/models/shared_examples.rb +5 -0
- data/spec/fin/order_list_spec.rb +140 -0
- data/spec/fin/shared_examples.rb +355 -0
- data/spec/spec_helper.rb +17 -0
- data/tasks/common.rake +18 -0
- data/tasks/doc.rake +14 -0
- data/tasks/gem.rake +40 -0
- data/tasks/git.rake +34 -0
- data/tasks/spec.rake +16 -0
- data/tasks/version.rake +71 -0
- metadata +155 -0
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fin/models/shared_examples'
|
3
|
+
|
4
|
+
describe Fin::Instrument do
|
5
|
+
|
6
|
+
it_behaves_like 'model'
|
7
|
+
|
8
|
+
describe '#new with empty initializer' do
|
9
|
+
subject { Fin::Instrument.new }
|
10
|
+
|
11
|
+
its (:id) {should == nil} # replId
|
12
|
+
its (:rev) {should == nil} # replRev
|
13
|
+
its (:isin_id) {should == nil}
|
14
|
+
its (:isin) {should == nil}
|
15
|
+
its (:short_isin) {should == nil}
|
16
|
+
its (:sess_id) {should == nil}
|
17
|
+
its (:session) {should == nil}
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
describe '#new with opts' do
|
22
|
+
subject { Fin::Instrument.new :id => 12,
|
23
|
+
:rev => 123,
|
24
|
+
:isin_id => 1234567,
|
25
|
+
:isin => 'symbolic isin',
|
26
|
+
:short_isin => 'short isin',
|
27
|
+
:name => 'name',
|
28
|
+
:sess_id => 1213,
|
29
|
+
}
|
30
|
+
|
31
|
+
its (:isin_id) {should == 1234567}
|
32
|
+
its (:isin) {should == 'symbolic isin'}
|
33
|
+
its (:short_isin) {should == 'short isin'}
|
34
|
+
its (:name) {should == 'name'}
|
35
|
+
its (:id) {should == 12}
|
36
|
+
its (:rev) {should == 123}
|
37
|
+
its (:sess_id) {should == 1213}
|
38
|
+
its (:sess) {should == 1213}
|
39
|
+
|
40
|
+
describe '#to_s, #inspect' do
|
41
|
+
it 'is just right' do
|
42
|
+
subject.to_s.should == "name:short isin[symbolic isin]"
|
43
|
+
subject.inspect.should == "name:short isin[symbolic isin]"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#index' do
|
48
|
+
it 'should be equal to isin_id' do
|
49
|
+
subject.index.should == subject.isin_id
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fin/models/shared_examples'
|
3
|
+
|
4
|
+
describe Fin::Model do
|
5
|
+
it_behaves_like 'model'
|
6
|
+
end
|
7
|
+
|
8
|
+
describe Fin::Model, "as a base class for BD models" do
|
9
|
+
let(:model_class) { Class.new(Fin::Model) }
|
10
|
+
let(:model_item) {model_class.new}
|
11
|
+
describe 'class macros' do
|
12
|
+
|
13
|
+
describe '.prop_reader' do
|
14
|
+
it 'creates attr_reader in a model class, given a String or Symbol' do
|
15
|
+
model_class.instance_eval do
|
16
|
+
prop_reader :foo, 'bar'
|
17
|
+
end
|
18
|
+
model_item.should respond_to :foo
|
19
|
+
model_item.should_not respond_to :foo=
|
20
|
+
model_item.should respond_to :bar
|
21
|
+
model_item.should_not respond_to :bar=
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'creates attr_reader with aliases in a model class, given an Array' do
|
25
|
+
model_class.instance_eval do
|
26
|
+
prop_reader [:foo, 'bar', :baz]
|
27
|
+
end
|
28
|
+
model_item.should_not respond_to :foo=
|
29
|
+
model_item.should_not respond_to :bar=
|
30
|
+
model_item.should_not respond_to :baz=
|
31
|
+
model_item.should respond_to :foo
|
32
|
+
model_item.should respond_to :bar
|
33
|
+
model_item.should respond_to :baz
|
34
|
+
model_item.instance_variable_set(:@foo, 1313)
|
35
|
+
model_item.foo.should == 1313
|
36
|
+
model_item.bar.should == 1313
|
37
|
+
model_item.baz.should == 1313
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'accepts a mix of Symbols and Arrays' do
|
41
|
+
model_class.instance_eval do
|
42
|
+
prop_reader :foo, ['bar', :baz]
|
43
|
+
end
|
44
|
+
model_item.should_not respond_to :foo=
|
45
|
+
model_item.should_not respond_to :bar=
|
46
|
+
model_item.should_not respond_to :baz=
|
47
|
+
model_item.should respond_to :foo
|
48
|
+
model_item.should respond_to :bar
|
49
|
+
model_item.should respond_to :baz
|
50
|
+
model_item.instance_variable_set(:@foo, 1313)
|
51
|
+
model_item.foo.should == 1313
|
52
|
+
model_item.bar.should_not == 1313
|
53
|
+
model_item.baz.should_not == 1313
|
54
|
+
model_item.instance_variable_set(:@bar, 42)
|
55
|
+
model_item.foo.should == 1313
|
56
|
+
model_item.bar.should == 42
|
57
|
+
model_item.baz.should == 42
|
58
|
+
end
|
59
|
+
end # describe '.prop_reader'
|
60
|
+
|
61
|
+
describe '.prop_accessor' do
|
62
|
+
it 'creates attr_accessor in a model class, given a String or Symbol' do
|
63
|
+
model_class.instance_eval do
|
64
|
+
prop_accessor :foo, 'bar'
|
65
|
+
end
|
66
|
+
model_item.should respond_to :foo
|
67
|
+
model_item.should respond_to :foo=
|
68
|
+
model_item.should respond_to :bar
|
69
|
+
model_item.should respond_to :bar=
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'creates attr_accessor with aliases in a model class, given an Array' do
|
73
|
+
model_class.instance_eval do
|
74
|
+
prop_accessor [:foo, 'bar', :baz]
|
75
|
+
end
|
76
|
+
model_item.should respond_to :foo=
|
77
|
+
model_item.should respond_to :bar=
|
78
|
+
model_item.should respond_to :baz=
|
79
|
+
model_item.should respond_to :foo
|
80
|
+
model_item.should respond_to :bar
|
81
|
+
model_item.should respond_to :baz
|
82
|
+
model_item.foo = 1313
|
83
|
+
model_item.foo.should == 1313
|
84
|
+
model_item.bar.should == 1313
|
85
|
+
model_item.baz.should == 1313
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'accepts a mix of Symbols and Arrays' do
|
89
|
+
model_class.instance_eval do
|
90
|
+
prop_accessor :foo, ['bar', :baz]
|
91
|
+
end
|
92
|
+
model_item.should respond_to :foo=
|
93
|
+
model_item.should respond_to :bar=
|
94
|
+
model_item.should respond_to :baz=
|
95
|
+
model_item.should respond_to :foo
|
96
|
+
model_item.should respond_to :bar
|
97
|
+
model_item.should respond_to :baz
|
98
|
+
model_item.foo = 1313
|
99
|
+
model_item.foo.should == 1313
|
100
|
+
model_item.bar.should_not == 1313
|
101
|
+
model_item.baz.should_not == 1313
|
102
|
+
model_item.bar = 42
|
103
|
+
model_item.foo.should == 1313
|
104
|
+
model_item.bar.should == 42
|
105
|
+
model_item.baz.should == 42
|
106
|
+
end
|
107
|
+
end # describe '.prop_accessor'
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fin/models/shared_examples'
|
3
|
+
|
4
|
+
describe Fin::MoneyLimit do
|
5
|
+
|
6
|
+
it_behaves_like 'model'
|
7
|
+
|
8
|
+
describe '#new with empty initializer' do
|
9
|
+
subject { Fin::MoneyLimit.new }
|
10
|
+
|
11
|
+
its (:repl_id) {should == nil} # replId
|
12
|
+
its (:repl_rev) {should == nil} # replRev
|
13
|
+
its (:client_code) {should == nil}
|
14
|
+
its (:money_old) {should == nil}
|
15
|
+
its (:money_amount) {should == nil}
|
16
|
+
its (:money_free) {should == nil}
|
17
|
+
its (:money_blocked) {should == nil}
|
18
|
+
its (:pledge_old) {should == nil}
|
19
|
+
its (:pledge_amount) {should == nil}
|
20
|
+
its (:pledge_free) {should == nil}
|
21
|
+
its (:pledge_blocked) {should == nil}
|
22
|
+
its (:vm_reserve) {should == nil}
|
23
|
+
its (:vm_intercl) {should == nil}
|
24
|
+
its (:fee) {should == nil}
|
25
|
+
its (:fee_reserve) {should == nil}
|
26
|
+
its (:limit_spot_buy) {should == nil}
|
27
|
+
its (:limit_spot_buy_used) {should == nil}
|
28
|
+
its (:coeff_go) {should == nil}
|
29
|
+
its (:coeff_liquidity) {should == nil}
|
30
|
+
its (:is_auto_update_limit) {should == nil}
|
31
|
+
its (:is_auto_update_spot_limit) {should == nil}
|
32
|
+
its (:no_fut_discount) {should == nil}
|
33
|
+
its (:limits_set) {should == nil}
|
34
|
+
its (:premium) {should == nil}
|
35
|
+
its (:premium_order_reserve) {should == nil}
|
36
|
+
|
37
|
+
# client_code c7 ��� �������
|
38
|
+
# money_old d26.2 ����� �� ������ ������
|
39
|
+
# money_amount d26.2 ����� �����
|
40
|
+
# money_free d26.2 �������� �����
|
41
|
+
# money_blocked d26.2 ������������� �����
|
42
|
+
#
|
43
|
+
# pledge_old d26.2 ������� �� ������ ������
|
44
|
+
# pledge_amount d26.2 ����� �������
|
45
|
+
# pledge_free d26.2 �������� �������
|
46
|
+
# pledge_blocked d26.2 ������������� �������
|
47
|
+
#
|
48
|
+
# vm_reserve d26.2 �����, ����������������� ��� ������������� ������������ �����
|
49
|
+
# vm_intercl d26.2 ������������ �����, ��������� ��� ���������� � ����. �������
|
50
|
+
#
|
51
|
+
# fee d26.2 ��������� ����
|
52
|
+
# fee_reserve d26.2 ��������������� ������ ����� ��� ������
|
53
|
+
#
|
54
|
+
# limit_spot_buy d26.2 ����� �� ������� ������.
|
55
|
+
# limit_spot_buy_used d26.2 �������������� ����� �� ������� ������
|
56
|
+
#
|
57
|
+
# coeff_go d16.5 ����������� ����������� ��
|
58
|
+
# coeff_liquidity d16.5 ����������� �����������
|
59
|
+
#
|
60
|
+
# is_auto_update_limit i1 ������� �������������� ��������� ������ �� ��������
|
61
|
+
# ������ ��� ������� ����� ��������: 0-���, 1-������.
|
62
|
+
# is_auto_update_spot_limit i1 ������� �������������� ��������� ������� �� ������
|
63
|
+
# (�� �������, � �� �������) ��� ������� ����� ��������:
|
64
|
+
# 0-���, 1-������.
|
65
|
+
# no_fut_discount i1 ���������� ������������� ������ �� ���������: 1-������, 0-���.
|
66
|
+
# limits_set i1 ������� ��������� �������. 0 � ������ �����������
|
67
|
+
# premium d26.2 ������
|
68
|
+
# premium_order_reserve f ������ ������ ��� ������
|
69
|
+
end
|
70
|
+
|
71
|
+
describe '#new with opts' do
|
72
|
+
subject { Fin::MoneyLimit.new :repl_id => 12,
|
73
|
+
:repl_rev => 123,
|
74
|
+
:client_code => '1234',
|
75
|
+
:money_old => 1234,
|
76
|
+
:money_amount => 12345,
|
77
|
+
:money_free => 123456,
|
78
|
+
:money_blocked => 1,
|
79
|
+
:pledge_old => 12,
|
80
|
+
:pledge_amount => 123,
|
81
|
+
:pledge_free => 1234,
|
82
|
+
:pledge_blocked => 12345,
|
83
|
+
:vm_reserve => 123456,
|
84
|
+
:vm_intercl => 1,
|
85
|
+
:fee => 12,
|
86
|
+
:fee_reserve => 123,
|
87
|
+
:limit_spot_buy => 1234,
|
88
|
+
:limit_spot_buy_used => 12345,
|
89
|
+
:coeff_go => 123456,
|
90
|
+
:coeff_liquidity => 1,
|
91
|
+
:is_auto_update_limit => 1,
|
92
|
+
:is_auto_update_spot_limit => 0,
|
93
|
+
:no_fut_discount => 1,
|
94
|
+
:limits_set => 1,
|
95
|
+
:premium => 123,
|
96
|
+
:premium_order_reserve => 1234,
|
97
|
+
}
|
98
|
+
|
99
|
+
its (:repl_id) {should == 12} # replId
|
100
|
+
its (:repl_rev) {should == 123} # replRev
|
101
|
+
its (:client_code) {should == '1234'}
|
102
|
+
its (:money_old) {should == 1234}
|
103
|
+
its (:money_amount) {should == 12345}
|
104
|
+
its (:money_free) {should == 123456}
|
105
|
+
its (:money_blocked) {should == 1}
|
106
|
+
its (:pledge_old) {should == 12}
|
107
|
+
its (:pledge_amount) {should == 123}
|
108
|
+
its (:pledge_free) {should == 1234}
|
109
|
+
its (:pledge_blocked) {should == 12345}
|
110
|
+
its (:vm_reserve) {should == 123456}
|
111
|
+
its (:vm_intercl) {should == 1}
|
112
|
+
its (:fee) {should == 12}
|
113
|
+
its (:fee_reserve) {should == 123}
|
114
|
+
its (:limit_spot_buy) {should == 1234}
|
115
|
+
its (:limit_spot_buy_used) {should == 12345}
|
116
|
+
its (:coeff_go) {should == 123456}
|
117
|
+
its (:coeff_liquidity) {should == 1}
|
118
|
+
its (:is_auto_update_limit) {should == 1}
|
119
|
+
its (:is_auto_update_spot_limit) {should == 0}
|
120
|
+
its (:no_fut_discount) {should == 1}
|
121
|
+
its (:limits_set) {should == 1}
|
122
|
+
its (:premium) {should == 123}
|
123
|
+
its (:premium_order_reserve) {should == 1234}
|
124
|
+
|
125
|
+
describe '#to_s, #inspect' do
|
126
|
+
it 'is just right' do
|
127
|
+
right = "Money: Old 1234 Amt 12345 Free 123456 Blck 1 " +
|
128
|
+
"Pledge: Old 12 Amt 123 Free 1234 Blck 12345 " +
|
129
|
+
"VM: Reserve 123456 Intercl 1 Fee: 12 Reserve 123 " +
|
130
|
+
"Limit Spot: Buy 1234 Used 12345"
|
131
|
+
subject.to_s.should == right
|
132
|
+
subject.inspect.should == right
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
describe '#index' do
|
137
|
+
it 'should be equal to repl_id' do
|
138
|
+
subject.index.should == subject.repl_id
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fin/models/shared_examples'
|
3
|
+
|
4
|
+
describe Fin::Order do
|
5
|
+
|
6
|
+
it_behaves_like 'model'
|
7
|
+
|
8
|
+
describe '#new with empty initializer' do
|
9
|
+
subject { Fin::Order.new }
|
10
|
+
|
11
|
+
its (:repl_id) {should == nil}
|
12
|
+
its (:rev) {should == nil}
|
13
|
+
its (:isin_id) {should == nil}
|
14
|
+
its (:isin) {should == nil}
|
15
|
+
its (:price) {should == nil}
|
16
|
+
its (:volume) {should == nil}
|
17
|
+
its (:dir) {should == nil}
|
18
|
+
its (:buysell) {should == nil}
|
19
|
+
its (:moment) {should == nil}
|
20
|
+
its (:book) {should == nil}
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#new with opts' do
|
24
|
+
subject { Fin::Order.new :isin => 1234567,
|
25
|
+
:repl_id => 12,
|
26
|
+
:rev => 123,
|
27
|
+
:price => 1234,
|
28
|
+
:volume => 12345,
|
29
|
+
:buysell => 1,
|
30
|
+
:moment => 'time',
|
31
|
+
:book => 123456
|
32
|
+
}
|
33
|
+
|
34
|
+
its (:repl_id) {should == 12}
|
35
|
+
its (:rev) {should == 123}
|
36
|
+
its (:isin_id) {should == 1234567}
|
37
|
+
its (:isin) {should == 1234567}
|
38
|
+
its (:price) {should == 1234}
|
39
|
+
its (:volume) {should == 12345}
|
40
|
+
its (:dir) {should == 1}
|
41
|
+
its (:buysell) {should == 1}
|
42
|
+
its (:moment) {should == 'time'}
|
43
|
+
its (:book) {should == 123456}
|
44
|
+
|
45
|
+
describe '#to_s, #inspect' do
|
46
|
+
it 'is just right' do
|
47
|
+
subject.to_s.should == "12:1234>12345+"
|
48
|
+
subject.inspect.should == "12:1234>12345+"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '#price=' do
|
53
|
+
it 'converts given price to Integer if it is integer' do
|
54
|
+
subject.price = 1313.0
|
55
|
+
subject.price.should == 1313
|
56
|
+
subject.price.should be_an Integer
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe '#index' do
|
61
|
+
it 'should be equal to replId' do
|
62
|
+
subject.index.should == subject.repl_id
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fin/models/shared_examples'
|
3
|
+
|
4
|
+
describe Fin::Position do
|
5
|
+
|
6
|
+
it_behaves_like 'model'
|
7
|
+
|
8
|
+
describe '#new with empty initializer' do
|
9
|
+
subject { Fin::Position.new }
|
10
|
+
|
11
|
+
its (:repl_id) {should == nil} # replId
|
12
|
+
its (:repl_rev) {should == nil} # replRev
|
13
|
+
its (:isin_id) {should == nil}
|
14
|
+
its (:client_code) {should == nil}
|
15
|
+
its (:open_qty) {should == nil}
|
16
|
+
its (:buys_qty) {should == nil}
|
17
|
+
its (:sells_qty) {should == nil}
|
18
|
+
its (:pos) {should == nil}
|
19
|
+
its (:net_volume_rur) {should == nil}
|
20
|
+
its (:last_deal_id) {should == nil}
|
21
|
+
|
22
|
+
# isin_id i4 ���������� �������� ������������� �����������
|
23
|
+
# client_code c7 ��� �������
|
24
|
+
# open_qty i4 ���������� ������� �� ������ ������
|
25
|
+
# buys_qty i4 ���������� ��������� ���������� � ���� ������
|
26
|
+
# sells_qty i4 ���������� ��������� ���������� � ���� ������
|
27
|
+
# pos i4 ������� �������
|
28
|
+
# net_volume_rur d26.2 �����-����� �����, � ������, �� ������� ���� ��������� ������.
|
29
|
+
# ������������� ����� � ������ ��������, ������������� � ������ �������������
|
30
|
+
# last_deal_id i8 ������������� ��������� ������
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '#new with opts' do
|
34
|
+
subject { Fin::Position.new :isin_id => 1234567,
|
35
|
+
:repl_id => 12,
|
36
|
+
:repl_rev => 123,
|
37
|
+
:client_code => 'fz1234',
|
38
|
+
:open_qty => 12345,
|
39
|
+
:buys_qty => 1212,
|
40
|
+
:sells_qty => 1213,
|
41
|
+
:pos => 12344,
|
42
|
+
:net_volume_rur => 123456,
|
43
|
+
:last_deal_id => 654321,
|
44
|
+
|
45
|
+
}
|
46
|
+
|
47
|
+
its (:isin_id) {should == 1234567}
|
48
|
+
its (:isin) {should == 1234567}
|
49
|
+
its (:id) {should == 12}
|
50
|
+
its (:rev) {should == 123}
|
51
|
+
its (:client_code) {should == 'fz1234'}
|
52
|
+
its (:open_qty) {should == 12345}
|
53
|
+
|
54
|
+
its (:buys_qty) {should == 1212}
|
55
|
+
its (:sells_qty) {should == 1213}
|
56
|
+
its (:pos) {should == 12344}
|
57
|
+
its (:net_volume_rur) {should == 123456}
|
58
|
+
its (:last_deal_id) {should == 654321}
|
59
|
+
|
60
|
+
describe '#to_s, #inspect' do
|
61
|
+
it 'is just right' do
|
62
|
+
subject.to_s.should == "12[1234567] 12344, open: 12345, buys: 1212, sells: 1213"
|
63
|
+
subject.inspect.should == "12[1234567] 12344, open: 12345, buys: 1212, sells: 1213"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe '#index' do
|
68
|
+
it 'should be equal to isin_id' do
|
69
|
+
subject.index.should == subject.isin_id
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|