Skip to content

Commit

Permalink
Order#algo_params,combo_params,leg_prices are now properly serialized…
Browse files Browse the repository at this point in the history
… in DB backend
  • Loading branch information
arvicco committed Jun 13, 2012
1 parent 5ed62c4 commit f679823
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 114 deletions.
6 changes: 3 additions & 3 deletions db/migrate/131_add_orders.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -83,9 +83,9 @@ def change
t.float :basis_points_type # double: EFP orders only t.float :basis_points_type # double: EFP orders only
t.string :algo_strategy t.string :algo_strategy


# t.string :algo_params # public Vector<TagValue> m_algoParams; ?! t.text :leg_prices # Vector<OrderComboLeg> m_orderComboLegs
# t.string :leg_prices # Vector<OrderComboLeg> m_orderComboLegs t.text :algo_params # public Vector<TagValue> m_algoParams; ?!
# t.string :combo_params # not used yet t.text :combo_params # not used yet


t.integer :scale_init_level_size # int: Size of the first (initial) order component. t.integer :scale_init_level_size # int: Size of the first (initial) order component.
t.integer :scale_subs_level_size # int: Order size of the subsequent scale order t.integer :scale_subs_level_size # int: Order size of the subsequent scale order
Expand Down
4 changes: 4 additions & 0 deletions db/schema.rb
Original file line number Original file line Diff line number Diff line change
@@ -1,3 +1,4 @@
# encoding: UTF-8
# This file is auto-generated from the current state of the database. Instead # This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to # of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition. # incrementally modify your database, and then regenerate this schema definition.
Expand Down Expand Up @@ -214,6 +215,9 @@
t.float "basis_points" t.float "basis_points"
t.float "basis_points_type" t.float "basis_points_type"
t.string "algo_strategy" t.string "algo_strategy"
t.text "leg_prices"
t.text "algo_params"
t.text "combo_params"
t.integer "scale_init_level_size" t.integer "scale_init_level_size"
t.integer "scale_subs_level_size" t.integer "scale_subs_level_size"
t.float "scale_price_increment" t.float "scale_price_increment"
Expand Down
1 change: 1 addition & 0 deletions lib/ib-ruby/models/model.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ def [] key
end end


def []= key, val def []= key, val
# p key, val
attributes[key.to_sym] = val attributes[key.to_sym] = val
end end


Expand Down
17 changes: 5 additions & 12 deletions lib/ib-ruby/models/order.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -222,9 +222,9 @@ class Order < Model.for(:order)
alias order_combo_legs leg_prices alias order_combo_legs leg_prices
alias smart_combo_routing_params combo_params alias smart_combo_routing_params combo_params


#serialize :leg_prices serialize :leg_prices
#serialize :algo_params serialize :algo_params, Hash
#serialize :combo_params serialize :combo_params


# Order is always placed for a contract. Here, we explicitly set this link. # Order is always placed for a contract. Here, we explicitly set this link.
belongs_to :contract belongs_to :contract
Expand Down Expand Up @@ -306,22 +306,15 @@ def default_attributes
:transmit => true, :transmit => true,
:what_if => false, :what_if => false,
:leg_prices => [], :leg_prices => [],
:algo_params => [], :algo_params => HashWithIndifferentAccess.new, #{},
:combo_params => [], :combo_params => HashWithIndifferentAccess.new, #{},
:order_state => IB::OrderState.new(:status => 'New', :order_state => IB::OrderState.new(:status => 'New',
:filled => 0, :filled => 0,
:remaining => 0, :remaining => 0,
:price => 0, :price => 0,
:average_price => 0) :average_price => 0)
end end


#after_initialize do #opts = {}
# #self.leg_prices = []
# #self.algo_params = {}
# #self.combo_params = {}
# #self.order_state ||= IB::OrderState.new :status => 'New'
#end

def serialize_algo def serialize_algo
if algo_strategy.nil? || algo_strategy.empty? if algo_strategy.nil? || algo_strategy.empty?
'' ''
Expand Down
234 changes: 135 additions & 99 deletions spec/ib-ruby/models/order_spec.rb
Original file line number Original file line Diff line number Diff line change
@@ -1,87 +1,87 @@
require 'model_helper' require 'model_helper'


describe IB::Models::Order, describe IB::Models::Order,
:props => :props =>
{:local_id => 23, {:local_id => 23,
:order_ref => 'Test', :order_ref => 'Test',
:client_id => 1111, :client_id => 1111,
:perm_id => 173276893, :perm_id => 173276893,
:parent_id => 0, :parent_id => 0,
:side => :buy, :side => :buy,
:order_type => :market_if_touched, :order_type => :market_if_touched,
:limit_price => 0.1, :limit_price => 0.1,
:quantity => 100, :quantity => 100,
:tif => :good_till_cancelled, :tif => :good_till_cancelled,
:open_close => :close, :open_close => :close,
:oca_group => '', :oca_group => '',
:oca_type => :reduce_no_block, :oca_type => :reduce_no_block,
:origin => :firm, :origin => :firm,
:designated_location => "WHATEVER", :designated_location => "WHATEVER",
:exempt_code => 123, :exempt_code => 123,
:delta_neutral_order_type => :market, :delta_neutral_order_type => :market,
:transmit => false, :transmit => false,
:outside_rth => true, :outside_rth => true,
:what_if => true, :what_if => true,
:not_held => true}, :not_held => true},


# TODO: :presents => { Object => "Formatted"} # TODO: :presents => { Object => "Formatted"}
:human => "<Order: Test MIT GTC buy 100 New 0.1 #23/173276893 from 1111>", :human => "<Order: Test MIT GTC buy 100 New 0.1 #23/173276893 from 1111>",


:errors => {:side =>["should be buy/sell/short"]}, :errors => {:side =>["should be buy/sell/short"]},


:assigns => :assigns =>
{[:order_type, :delta_neutral_order_type] => codes_and_values_for(:order_type), {[:order_type, :delta_neutral_order_type] => codes_and_values_for(:order_type),


:open_close => :open_close =>
{[42, nil, 'Foo', :bar] => /should be same.open.close.unknown/, {[42, nil, 'Foo', :bar] => /should be same.open.close.unknown/,
['SAME', 'same', 'S', 's', :same, 0, '0'] => :same, ['SAME', 'same', 'S', 's', :same, 0, '0'] => :same,
['OPEN', 'open', 'O', 'o', :open, 1, '1'] => :open, ['OPEN', 'open', 'O', 'o', :open, 1, '1'] => :open,
['CLOSE', 'close', 'C', 'c', :close, 2, '2'] => :close, ['CLOSE', 'close', 'C', 'c', :close, 2, '2'] => :close,
['UNKNOWN', 'unknown', 'U', 'u', :unknown, 3, '3'] => :unknown, ['UNKNOWN', 'unknown', 'U', 'u', :unknown, 3, '3'] => :unknown,
}, },


[:what_if, :not_held, :outside_rth, :hidden, :transmit, :block_order, [:what_if, :not_held, :outside_rth, :hidden, :transmit, :block_order,
:sweep_to_fill, :override_percentage_constraints, :all_or_none, :sweep_to_fill, :override_percentage_constraints, :all_or_none,
:etrade_only, :firm_quote_only, :opt_out_smart_routing, :scale_auto_reset, :etrade_only, :firm_quote_only, :opt_out_smart_routing, :scale_auto_reset,
:scale_random_percent] => boolean_assigns, :scale_random_percent] => boolean_assigns,


[:local_id, :perm_id, :parent_id] => numeric_or_nil_assigns, [:local_id, :perm_id, :parent_id] => numeric_or_nil_assigns,
}, },


:aliases => :aliases =>
{[:side, :action] => buy_sell_short_assigns, {[:side, :action] => buy_sell_short_assigns,
[:quantity, :total_quantity] => numeric_or_nil_assigns, [:quantity, :total_quantity] => numeric_or_nil_assigns,
}, },


:collections => :collections =>
{:order_states =>[{:status => :Foo}, {:order_states =>[{:status => :Foo},
{:status => 'Bar'},], {:status => 'Bar'},],


:executions => :executions =>
[{:local_id => 23, [{:local_id => 23,
:client_id => 1111, :client_id => 1111,
:perm_id => 173276893, :perm_id => 173276893,
:exchange => "IDEALPRO", :exchange => "IDEALPRO",
:exec_id => "0001f4e8.4f5d48f1.01.01", :exec_id => "0001f4e8.4f5d48f1.01.01",
:price => 0.1, :price => 0.1,
:average_price => 0.1, :average_price => 0.1,
:shares => 40, :shares => 40,
:cumulative_quantity => 40, :cumulative_quantity => 40,
:side => :buy, :side => :buy,
:time => "20120312 15:41:09"}, :time => "20120312 15:41:09"},


{:local_id => 23, {:local_id => 23,
:client_id => 1111, :client_id => 1111,
:perm_id => 173276893, :perm_id => 173276893,
:exchange => "IDEALPRO", :exchange => "IDEALPRO",
:exec_id => "0001f4e8.4f5d48f1.01.02", :exec_id => "0001f4e8.4f5d48f1.01.02",
:price => 0.1, :price => 0.1,
:average_price => 0.1, :average_price => 0.1,
:shares => 60, :shares => 60,
:cumulative_quantity => 100, :cumulative_quantity => 100,
:side => :buy, :side => :buy,
:time => "20120312 15:41:10"}] :time => "20120312 15:41:10"}]
} do } do


it_behaves_like 'Self-equal Model' it_behaves_like 'Self-equal Model'
it_behaves_like 'Model with invalid defaults' it_behaves_like 'Model with invalid defaults'
Expand Down Expand Up @@ -173,53 +173,89 @@


it 'is not equal for Orders with different limit price' do it 'is not equal for Orders with different limit price' do
order1 = IB::Order.new :quantity => 100, order1 = IB::Order.new :quantity => 100,
:limit_price => 1, :limit_price => 1,
:action => 'BUY' :action => 'BUY'


order2 = IB::Order.new :total_quantity => 100, order2 = IB::Order.new :total_quantity => 100,
:limit_price => 2, :limit_price => 2,
:action => 'BUY' :action => 'BUY'
order1.should_not == order2 order1.should_not == order2
order2.should_not == order1 order2.should_not == order1
end end


it 'is not equal for Orders with different total_quantity' do it 'is not equal for Orders with different total_quantity' do
order1 = IB::Order.new :quantity => 20000, order1 = IB::Order.new :quantity => 20000,
:limit_price => 1, :limit_price => 1,
:action => 'BUY' :action => 'BUY'


order2 = IB::Order.new :total_quantity => 100, order2 = IB::Order.new :total_quantity => 100,
:action => 'BUY', :action => 'BUY',
:limit_price => 1 :limit_price => 1
order1.should_not == order2 order1.should_not == order2
order2.should_not == order1 order2.should_not == order1
end end


it 'is not equal for Orders with different action/side' do it 'is not equal for Orders with different action/side' do
order1 = IB::Order.new :quantity => 100, order1 = IB::Order.new :quantity => 100,
:limit_price => 1, :limit_price => 1,
:action => 'SELL' :action => 'SELL'


order2 = IB::Order.new :quantity => 100, order2 = IB::Order.new :quantity => 100,
:action => 'BUY', :action => 'BUY',
:limit_price => 1 :limit_price => 1
order1.should_not == order2 order1.should_not == order2
order2.should_not == order1 order2.should_not == order1
end end


it 'is not equal for Orders with different order_type' do it 'is not equal for Orders with different order_type' do
order1 = IB::Order.new :quantity => 100, order1 = IB::Order.new :quantity => 100,
:limit_price => 1, :limit_price => 1,
:action => 'BUY', :action => 'BUY',
:order_type => 'LMT' :order_type => 'LMT'


order2 = IB::Order.new :quantity => 100, order2 = IB::Order.new :quantity => 100,
:action => 'BUY', :action => 'BUY',
:limit_price => 1, :limit_price => 1,
:order_type => 'MKT' :order_type => 'MKT'
order1.should_not == order2 order1.should_not == order2
order2.should_not == order1 order2.should_not == order1
end end
end end


context 'DB-backed serialization of properties', :db => true do
let(:serializable_props) do
{
:algo_strategy => "ArrivalPx",
:algo_params => { "maxPctVol" => "0.01",
"riskAversion" => "Passive",
"startTime" => "9:00:00 EST",
"endTime" => "15:00:00 EST",
"forceCompletion" => "0",
"allowPastEndTime" => "1"},
:combo_params => {"NonGuaranteed" => "1",
"LeginPrio" => "0"},
:leg_prices => [1,2,3],
}
end

subject { IB::Order.new(props.merge(serializable_props)) }

after(:all) { DatabaseCleaner.clean }

it 'is saved to DB with serializable_props' do
subject.save.should be_true
end

it 'is loaded from DB with serializable_props' do
models = described_class.find(:all)
models.should have_exactly(1).model
order = models.first
order.algo_strategy.should == serializable_props[:algo_strategy]
order.algo_params.should == serializable_props[:algo_params]
order.combo_params.should == serializable_props[:combo_params]
order.leg_prices.should == serializable_props[:leg_prices]
p order.combo_params
end
end # DB

end # describe IB::Order end # describe IB::Order

0 comments on commit f679823

Please sign in to comment.