schwab_rb 0.2.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.
- checksums.yaml +7 -0
- data/.copilotignore +4 -0
- data/.rspec +2 -0
- data/.rspec_status +292 -0
- data/.rubocop.yml +41 -0
- data/.rubocop_todo.yml +105 -0
- data/CHANGELOG.md +28 -0
- data/LICENSE.txt +23 -0
- data/README.md +271 -0
- data/Rakefile +12 -0
- data/doc/notes/data_objects_analysis.md +223 -0
- data/doc/notes/data_objects_refactoring_plan.md +82 -0
- data/examples/fetch_account_numbers.rb +49 -0
- data/examples/fetch_user_preferences.rb +49 -0
- data/lib/schwab_rb/account.rb +9 -0
- data/lib/schwab_rb/auth/auth_context.rb +23 -0
- data/lib/schwab_rb/auth/init_client_easy.rb +45 -0
- data/lib/schwab_rb/auth/init_client_login.rb +201 -0
- data/lib/schwab_rb/auth/init_client_token_file.rb +30 -0
- data/lib/schwab_rb/auth/login_flow_server.rb +55 -0
- data/lib/schwab_rb/auth/token.rb +24 -0
- data/lib/schwab_rb/auth/token_manager.rb +105 -0
- data/lib/schwab_rb/clients/async_client.rb +122 -0
- data/lib/schwab_rb/clients/base_client.rb +887 -0
- data/lib/schwab_rb/clients/client.rb +97 -0
- data/lib/schwab_rb/configuration.rb +39 -0
- data/lib/schwab_rb/constants.rb +7 -0
- data/lib/schwab_rb/data_objects/account.rb +281 -0
- data/lib/schwab_rb/data_objects/account_numbers.rb +68 -0
- data/lib/schwab_rb/data_objects/instrument.rb +156 -0
- data/lib/schwab_rb/data_objects/market_hours.rb +275 -0
- data/lib/schwab_rb/data_objects/option.rb +147 -0
- data/lib/schwab_rb/data_objects/option_chain.rb +95 -0
- data/lib/schwab_rb/data_objects/option_expiration_chain.rb +134 -0
- data/lib/schwab_rb/data_objects/order.rb +186 -0
- data/lib/schwab_rb/data_objects/order_leg.rb +68 -0
- data/lib/schwab_rb/data_objects/order_preview.rb +237 -0
- data/lib/schwab_rb/data_objects/position.rb +100 -0
- data/lib/schwab_rb/data_objects/price_history.rb +187 -0
- data/lib/schwab_rb/data_objects/quote.rb +276 -0
- data/lib/schwab_rb/data_objects/transaction.rb +132 -0
- data/lib/schwab_rb/data_objects/user_preferences.rb +129 -0
- data/lib/schwab_rb/market_hours.rb +13 -0
- data/lib/schwab_rb/movers.rb +35 -0
- data/lib/schwab_rb/option.rb +64 -0
- data/lib/schwab_rb/orders/builder.rb +202 -0
- data/lib/schwab_rb/orders/destination.rb +19 -0
- data/lib/schwab_rb/orders/duration.rb +9 -0
- data/lib/schwab_rb/orders/equity_instructions.rb +10 -0
- data/lib/schwab_rb/orders/errors.rb +5 -0
- data/lib/schwab_rb/orders/instruments.rb +35 -0
- data/lib/schwab_rb/orders/option_instructions.rb +10 -0
- data/lib/schwab_rb/orders/order.rb +77 -0
- data/lib/schwab_rb/orders/price_link_basis.rb +15 -0
- data/lib/schwab_rb/orders/price_link_type.rb +9 -0
- data/lib/schwab_rb/orders/session.rb +14 -0
- data/lib/schwab_rb/orders/special_instruction.rb +10 -0
- data/lib/schwab_rb/orders/stop_price_link_basis.rb +15 -0
- data/lib/schwab_rb/orders/stop_price_link_type.rb +9 -0
- data/lib/schwab_rb/orders/stop_type.rb +11 -0
- data/lib/schwab_rb/orders/tax_lot_method.rb +13 -0
- data/lib/schwab_rb/price_history.rb +55 -0
- data/lib/schwab_rb/quote.rb +13 -0
- data/lib/schwab_rb/transaction.rb +23 -0
- data/lib/schwab_rb/utils/enum_enforcer.rb +73 -0
- data/lib/schwab_rb/utils/logger.rb +70 -0
- data/lib/schwab_rb/utils/redactor.rb +104 -0
- data/lib/schwab_rb/version.rb +5 -0
- data/lib/schwab_rb.rb +48 -0
- data/sig/schwab_rb.rbs +4 -0
- metadata +289 -0
@@ -0,0 +1,129 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SchwabRb
|
4
|
+
module DataObjects
|
5
|
+
class UserPreferences
|
6
|
+
attr_reader :accounts, :streamer_info, :offers
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def build(data)
|
10
|
+
new(data)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(data)
|
15
|
+
@accounts = data[:accounts]&.map { |account_data| UserAccount.new(account_data) } || []
|
16
|
+
@streamer_info = data[:streamerInfo]&.map { |streamer_data| StreamerInfo.new(streamer_data) } || []
|
17
|
+
@offers = data[:offers]&.map { |offer_data| Offer.new(offer_data) } || []
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_h
|
21
|
+
{
|
22
|
+
accounts: @accounts.map(&:to_h),
|
23
|
+
streamerInfo: @streamer_info.map(&:to_h),
|
24
|
+
offers: @offers.map(&:to_h)
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
def primary_account
|
29
|
+
@accounts.find(&:primary_account?)
|
30
|
+
end
|
31
|
+
|
32
|
+
def find_account_by_number(account_number)
|
33
|
+
@accounts.find { |account| account.account_number == account_number }
|
34
|
+
end
|
35
|
+
|
36
|
+
def account_numbers
|
37
|
+
@accounts.map(&:account_number)
|
38
|
+
end
|
39
|
+
|
40
|
+
def brokerage_accounts
|
41
|
+
@accounts.select { |account| account.type == 'BROKERAGE' }
|
42
|
+
end
|
43
|
+
|
44
|
+
def has_level2_permissions?
|
45
|
+
@offers.any?(&:level2_permissions?)
|
46
|
+
end
|
47
|
+
|
48
|
+
class UserAccount
|
49
|
+
attr_reader :account_number, :primary_account, :type, :nick_name, :display_acct_id,
|
50
|
+
:auto_position_effect, :account_color, :lot_selection_method
|
51
|
+
|
52
|
+
def initialize(data)
|
53
|
+
@account_number = data[:accountNumber]
|
54
|
+
@primary_account = data[:primaryAccount]
|
55
|
+
@type = data[:type]
|
56
|
+
@nick_name = data[:nickName]
|
57
|
+
@display_acct_id = data[:displayAcctId]
|
58
|
+
@auto_position_effect = data[:autoPositionEffect]
|
59
|
+
@account_color = data[:accountColor]
|
60
|
+
@lot_selection_method = data[:lotSelectionMethod]
|
61
|
+
end
|
62
|
+
|
63
|
+
def primary_account?
|
64
|
+
@primary_account
|
65
|
+
end
|
66
|
+
|
67
|
+
def auto_position_effect?
|
68
|
+
@auto_position_effect
|
69
|
+
end
|
70
|
+
|
71
|
+
def to_h
|
72
|
+
{
|
73
|
+
accountNumber: @account_number,
|
74
|
+
primaryAccount: @primary_account,
|
75
|
+
type: @type,
|
76
|
+
nickName: @nick_name,
|
77
|
+
displayAcctId: @display_acct_id,
|
78
|
+
autoPositionEffect: @auto_position_effect,
|
79
|
+
accountColor: @account_color,
|
80
|
+
lotSelectionMethod: @lot_selection_method
|
81
|
+
}
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
class StreamerInfo
|
86
|
+
attr_reader :streamer_socket_url, :schwab_client_customer_id, :schwab_client_correl_id,
|
87
|
+
:schwab_client_channel, :schwab_client_function_id
|
88
|
+
|
89
|
+
def initialize(data)
|
90
|
+
@streamer_socket_url = data[:streamerSocketUrl]
|
91
|
+
@schwab_client_customer_id = data[:schwabClientCustomerId]
|
92
|
+
@schwab_client_correl_id = data[:schwabClientCorrelId]
|
93
|
+
@schwab_client_channel = data[:schwabClientChannel]
|
94
|
+
@schwab_client_function_id = data[:schwabClientFunctionId]
|
95
|
+
end
|
96
|
+
|
97
|
+
def to_h
|
98
|
+
{
|
99
|
+
streamerSocketUrl: @streamer_socket_url,
|
100
|
+
schwabClientCustomerId: @schwab_client_customer_id,
|
101
|
+
schwabClientCorrelId: @schwab_client_correl_id,
|
102
|
+
schwabClientChannel: @schwab_client_channel,
|
103
|
+
schwabClientFunctionId: @schwab_client_function_id
|
104
|
+
}
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
class Offer
|
109
|
+
attr_reader :level2_permissions, :mkt_data_permission
|
110
|
+
|
111
|
+
def initialize(data)
|
112
|
+
@level2_permissions = data[:level2Permissions]
|
113
|
+
@mkt_data_permission = data[:mktDataPermission]
|
114
|
+
end
|
115
|
+
|
116
|
+
def level2_permissions?
|
117
|
+
@level2_permissions
|
118
|
+
end
|
119
|
+
|
120
|
+
def to_h
|
121
|
+
{
|
122
|
+
level2Permissions: @level2_permissions,
|
123
|
+
mktDataPermission: @mkt_data_permission
|
124
|
+
}
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SchwabRb
|
4
|
+
class Movers
|
5
|
+
module Indexes
|
6
|
+
DJI = '$DJI'
|
7
|
+
COMPX = '$COMPX'
|
8
|
+
SPX = '$SPX'
|
9
|
+
NYSE = 'NYSE'
|
10
|
+
NASDAQ = 'NASDAQ'
|
11
|
+
OTCBB = 'OTCBB'
|
12
|
+
INDEX_ALL = 'INDEX_ALL'
|
13
|
+
EQUITY_ALL = 'EQUITY_ALL'
|
14
|
+
OPTION_ALL = 'OPTION_ALL'
|
15
|
+
OPTION_PUT = 'OPTION_PUT'
|
16
|
+
OPTION_CALL = 'OPTION_CALL'
|
17
|
+
end
|
18
|
+
|
19
|
+
module SortOrders
|
20
|
+
VOLUME = 'VOLUME'
|
21
|
+
TRADES = 'TRADES'
|
22
|
+
PERCENT_CHANGE_UP = 'PERCENT_CHANGE_UP'
|
23
|
+
PERCENT_CHANGE_DOWN = 'PERCENT_CHANGE_DOWN'
|
24
|
+
end
|
25
|
+
|
26
|
+
module Frequencies
|
27
|
+
ZERO = 0
|
28
|
+
ONE = 1
|
29
|
+
FIVE = 5
|
30
|
+
TEN = 10
|
31
|
+
THIRTY = 30
|
32
|
+
SIXTY = 60
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SchwabRb
|
4
|
+
class Option
|
5
|
+
module ContractTypes
|
6
|
+
CALL = "CALL"
|
7
|
+
PUT = "PUT"
|
8
|
+
ALL = "ALL"
|
9
|
+
end
|
10
|
+
|
11
|
+
module Strategies
|
12
|
+
SINGLE = "SINGLE"
|
13
|
+
ANALYTICAL = "ANALYTICAL"
|
14
|
+
COVERED = "COVERED"
|
15
|
+
VERTICAL = "VERTICAL"
|
16
|
+
CALENDAR = "CALENDAR"
|
17
|
+
STRANGLE = "STRANGLE"
|
18
|
+
STRADDLE = "STRADDLE"
|
19
|
+
BUTTERFLY = "BUTTERFLY"
|
20
|
+
CONDOR = "CONDOR"
|
21
|
+
DIAGONAL = "DIAGONAL"
|
22
|
+
COLLAR = "COLLAR"
|
23
|
+
ROLL = "ROLL"
|
24
|
+
end
|
25
|
+
|
26
|
+
module StrikeRanges
|
27
|
+
IN_THE_MONEY = "ITM"
|
28
|
+
NEAR_THE_MONEY = "NTM"
|
29
|
+
OUT_OF_THE_MONEY = "OTM"
|
30
|
+
STRIKES_ABOVE_MARKET = "SAK"
|
31
|
+
STRIKES_BELOW_MARKET = "SBK"
|
32
|
+
STRIKES_NEAR_MARKET = "SNK"
|
33
|
+
ALL = "ALL"
|
34
|
+
end
|
35
|
+
|
36
|
+
module Types
|
37
|
+
STANDARD = "S"
|
38
|
+
NON_STANDARD = "NS"
|
39
|
+
ALL = "ALL"
|
40
|
+
end
|
41
|
+
|
42
|
+
module ExpirationMonths
|
43
|
+
JANUARY = "JAN"
|
44
|
+
FEBRUARY = "FEB"
|
45
|
+
MARCH = "MAR"
|
46
|
+
APRIL = "APR"
|
47
|
+
MAY = "MAY"
|
48
|
+
JUNE = "JUN"
|
49
|
+
JULY = "JUL"
|
50
|
+
AUGUST = "AUG"
|
51
|
+
SEPTEMBER = "SEP"
|
52
|
+
OCTOBER = "OCT"
|
53
|
+
NOVEMBER = "NOV"
|
54
|
+
DECEMBER = "DEC"
|
55
|
+
ALL = "ALL"
|
56
|
+
end
|
57
|
+
|
58
|
+
module Entitlements
|
59
|
+
PAYING_PRO = "PP"
|
60
|
+
NON_PRO = "NP"
|
61
|
+
NON_PAYING_PRO = "PN"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,202 @@
|
|
1
|
+
require_relative '../utils/enum_enforcer'
|
2
|
+
|
3
|
+
module SchwabRb::Orders
|
4
|
+
class Builder
|
5
|
+
# Helper class to create arbitrarily complex orders. Note this class simply
|
6
|
+
# implements the order schema defined in the `documentation
|
7
|
+
# <https://developer.schwabmeritrade.com/account-access/apis/post/accounts/
|
8
|
+
# %7BaccountId%7D/orders-0>`__, with no attempts to validate the result.
|
9
|
+
# Orders created using this class may be rejected or may never fill. Use at
|
10
|
+
# your own risk.
|
11
|
+
|
12
|
+
include EnumEnforcer
|
13
|
+
|
14
|
+
class << self
|
15
|
+
def build(obj)
|
16
|
+
case obj
|
17
|
+
when String, Integer, Float
|
18
|
+
obj
|
19
|
+
when Hash
|
20
|
+
obj.each_with_object({}) do |(key, val), acc|
|
21
|
+
acc[camel_case(key)] = build(val)
|
22
|
+
end
|
23
|
+
when Array
|
24
|
+
obj.map { |i| build(i) }
|
25
|
+
else
|
26
|
+
ret = {}
|
27
|
+
obj.instance_variables.each do |var|
|
28
|
+
value = obj.instance_variable_get(var)
|
29
|
+
next if value.nil?
|
30
|
+
|
31
|
+
name = var.to_s[1..-1]
|
32
|
+
ret[camel_case(name)] = build(value)
|
33
|
+
end
|
34
|
+
ret
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def camel_case(snake_str)
|
39
|
+
camel_case_str = snake_str.split('_').map(&:capitalize).join
|
40
|
+
camel_case_str[0].downcase + camel_case_str[1..]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def initialize(enforce_enums: true)
|
45
|
+
@session = nil
|
46
|
+
@account_number = nil
|
47
|
+
@duration = nil
|
48
|
+
@order_type = nil
|
49
|
+
@complex_order_strategy_type = nil
|
50
|
+
@quantity = nil
|
51
|
+
@destination_link_name = nil
|
52
|
+
@stop_price = nil
|
53
|
+
@stop_price_link_basis = nil
|
54
|
+
@stop_price_link_type = nil
|
55
|
+
@stop_price_offset = nil
|
56
|
+
@stop_type = nil
|
57
|
+
@price_link_basis = nil
|
58
|
+
@price_link_type = nil
|
59
|
+
@price = nil
|
60
|
+
@order_leg_collection = nil
|
61
|
+
@activation_price = nil
|
62
|
+
@special_instruction = nil
|
63
|
+
@order_strategy_type = nil
|
64
|
+
@child_order_strategies = nil
|
65
|
+
end
|
66
|
+
|
67
|
+
def set_session(session)
|
68
|
+
@session = convert_enum(session, SchwabRb::Orders::Session)
|
69
|
+
end
|
70
|
+
|
71
|
+
def clear_session
|
72
|
+
@session = nil
|
73
|
+
end
|
74
|
+
|
75
|
+
def set_account_number(account_number)
|
76
|
+
@account_number = account_number
|
77
|
+
end
|
78
|
+
|
79
|
+
def clear_account_number
|
80
|
+
@account_number = nil
|
81
|
+
end
|
82
|
+
|
83
|
+
def set_duration(duration)
|
84
|
+
@duration = convert_enum(duration, SchwabRb::Orders::Duration)
|
85
|
+
end
|
86
|
+
|
87
|
+
def clear_duration
|
88
|
+
@duration = nil
|
89
|
+
end
|
90
|
+
|
91
|
+
def set_order_type(order_type)
|
92
|
+
@order_type = convert_enum(order_type, SchwabRb::Order::Types)
|
93
|
+
end
|
94
|
+
|
95
|
+
def clear_order_type
|
96
|
+
@order_type = nil
|
97
|
+
end
|
98
|
+
|
99
|
+
def set_quantity(quantity)
|
100
|
+
raise "quantity must be positive" if quantity <= 0
|
101
|
+
|
102
|
+
@quantity = quantity
|
103
|
+
end
|
104
|
+
|
105
|
+
def clear_quantity
|
106
|
+
@quantity = nil
|
107
|
+
end
|
108
|
+
|
109
|
+
def set_price(price)
|
110
|
+
@price = price
|
111
|
+
end
|
112
|
+
|
113
|
+
def clear_price
|
114
|
+
@price = nil
|
115
|
+
end
|
116
|
+
|
117
|
+
def set_stop_price(stop_price)
|
118
|
+
@stop_price = stop_price.is_a?(String) ? stop_price : truncate_float(stop_price)
|
119
|
+
end
|
120
|
+
|
121
|
+
def copy_stop_price(stop_price)
|
122
|
+
@stop_price = stop_price
|
123
|
+
end
|
124
|
+
|
125
|
+
def clear_stop_price
|
126
|
+
@stop_price = nil
|
127
|
+
end
|
128
|
+
|
129
|
+
def set_order_strategy_type(order_strategy_type = "SINGLE")
|
130
|
+
@order_strategy_type = order_strategy_type
|
131
|
+
end
|
132
|
+
|
133
|
+
def clear_order_strategy_type
|
134
|
+
@order_strategy_type = nil
|
135
|
+
end
|
136
|
+
|
137
|
+
def set_complex_order_strategy_type(complex_order_strategy_type)
|
138
|
+
@complex_order_strategy_type = convert_enum(
|
139
|
+
complex_order_strategy_type,
|
140
|
+
SchwabRb::Order::ComplexOrderStrategyTypes
|
141
|
+
)
|
142
|
+
end
|
143
|
+
|
144
|
+
def clear_complex_order_strategy_type
|
145
|
+
@complex_order_strategy_type = nil
|
146
|
+
end
|
147
|
+
|
148
|
+
def add_child_order_strategy(child_order_strategy)
|
149
|
+
raise "child order must be OrderBuilder or Hash" unless [Builder, Hash].any? do |type|
|
150
|
+
child_order_strategy.is_a? type
|
151
|
+
end
|
152
|
+
|
153
|
+
@child_order_strategies ||= []
|
154
|
+
@child_order_strategies << child_order_strategy
|
155
|
+
end
|
156
|
+
|
157
|
+
def clear_child_order_strategies
|
158
|
+
@child_order_strategies = nil
|
159
|
+
end
|
160
|
+
|
161
|
+
def add_option_leg(instruction, symbol, quantity)
|
162
|
+
raise "quantity must be positive" if quantity <= 0
|
163
|
+
|
164
|
+
@order_leg_collection ||= []
|
165
|
+
@order_leg_collection << {
|
166
|
+
"instruction" => convert_enum(instruction, SchwabRb::Orders::OptionInstructions),
|
167
|
+
"instrument" => SchwabRb::Orders::OptionInstrument.new(symbol),
|
168
|
+
"quantity" => quantity,
|
169
|
+
}
|
170
|
+
end
|
171
|
+
|
172
|
+
def add_equity_leg(instruction, symbol, quantity)
|
173
|
+
raise "quantity must be positive" if quantity <= 0
|
174
|
+
|
175
|
+
@order_leg_collection ||= []
|
176
|
+
@order_leg_collection << {
|
177
|
+
"instruction" => convert_enum(instruction, SchwabRb::Orders::EquityInstructions),
|
178
|
+
"instrument" => SchwabRb::Orders::EquityInstrument.new(symbol),
|
179
|
+
"quantity" => quantity
|
180
|
+
}
|
181
|
+
end
|
182
|
+
|
183
|
+
def clear_order_legs
|
184
|
+
@order_leg_collection = nil
|
185
|
+
self
|
186
|
+
end
|
187
|
+
|
188
|
+
def build
|
189
|
+
Builder.build(self)
|
190
|
+
end
|
191
|
+
|
192
|
+
private
|
193
|
+
|
194
|
+
def truncate_float(flt)
|
195
|
+
if flt.abs < 1 && flt != 0.0
|
196
|
+
format('%.4f', (flt * 10000).to_i / 10000.0)
|
197
|
+
else
|
198
|
+
format('%.2f', (flt * 100).to_i / 100.0)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module SchwabRb
|
2
|
+
module Orders
|
3
|
+
module Destination
|
4
|
+
# Destinations for when you want to request a specific destination for your order.
|
5
|
+
INET = 'INET'
|
6
|
+
ECN_ARCA = 'ECN_ARCA'
|
7
|
+
CBOE = 'CBOE'
|
8
|
+
AMEX = 'AMEX'
|
9
|
+
PHLX = 'PHLX'
|
10
|
+
ISE = 'ISE'
|
11
|
+
BOX = 'BOX'
|
12
|
+
NYSE = 'NYSE'
|
13
|
+
NASDAQ = 'NASDAQ'
|
14
|
+
BATS = 'BATS'
|
15
|
+
C2 = 'C2'
|
16
|
+
AUTO = 'AUTO'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module SchwabRb::Orders::Duration
|
2
|
+
DAY = 'DAY'
|
3
|
+
GOOD_TILL_CANCEL = 'GOOD_TILL_CANCEL'
|
4
|
+
FILL_OR_KILL = 'FILL_OR_KILL'
|
5
|
+
IMMEDIATE_OR_CANCEL = 'IMMEDIATE_OR_CANCEL'
|
6
|
+
END_OF_WEEK = 'END_OF_WEEK'
|
7
|
+
END_OF_MONTH = 'END_OF_MONTH'
|
8
|
+
NEXT_END_OF_MONTH = 'NEXT_END_OF_MONTH'
|
9
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module SchwabRb
|
2
|
+
module Orders
|
3
|
+
class Instrument
|
4
|
+
module Projections
|
5
|
+
SYMBOL_SEARCH = 'symbol-search'
|
6
|
+
SYMBOL_REGEX = 'symbol-regex'
|
7
|
+
DESCRIPTION_SEARCH = 'desc-search'
|
8
|
+
DESCRIPTION_REGEX = 'desc-regex'
|
9
|
+
SEARCH = 'search'
|
10
|
+
FUNDAMENTAL = 'fundamental'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class BaseInstrument
|
15
|
+
def initialize(asset_type, symbol)
|
16
|
+
@asset_type = asset_type
|
17
|
+
@symbol = symbol
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_reader :asset_type, :symbol
|
21
|
+
end
|
22
|
+
|
23
|
+
class EquityInstrument < BaseInstrument
|
24
|
+
def initialize(symbol)
|
25
|
+
super('EQUITY', symbol)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class OptionInstrument < BaseInstrument
|
30
|
+
def initialize(symbol)
|
31
|
+
super('OPTION', symbol)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module SchwabRb
|
2
|
+
class Order
|
3
|
+
module Statuses
|
4
|
+
AWAITING_PARENT_ORDER = "AWAITING_PARENT_ORDER"
|
5
|
+
AWAITING_CONDITION = "AWAITING_CONDITION"
|
6
|
+
AWAITING_STOP_CONDITION = "AWAITING_STOP_CONDITION"
|
7
|
+
AWAITING_MANUAL_REVIEW = "AWAITING_MANUAL_REVIEW"
|
8
|
+
ACCEPTED = "ACCEPTED"
|
9
|
+
AWAITING_UR_OUT = "AWAITING_UR_OUT"
|
10
|
+
PENDING_ACTIVATION = "PENDING_ACTIVATION"
|
11
|
+
QUEUED = "QUEUED"
|
12
|
+
WORKING = "WORKING"
|
13
|
+
REJECTED = "REJECTED"
|
14
|
+
PENDING_CANCEL = "PENDING_CANCEL"
|
15
|
+
CANCELED = "CANCELED"
|
16
|
+
PENDING_REPLACE = "PENDING_REPLACE"
|
17
|
+
REPLACED = "REPLACED"
|
18
|
+
FILLED = "FILLED"
|
19
|
+
EXPIRED = "EXPIRED"
|
20
|
+
NEW = "NEW"
|
21
|
+
AWAITING_RELEASE_TIME = "AWAITING_RELEASE_TIME"
|
22
|
+
PENDING_ACKNOWLEDGEMENT = "PENDING_ACKNOWLEDGEMENT"
|
23
|
+
PENDING_RECALL = "PENDING_RECALL"
|
24
|
+
UNKNOWN = "UNKNOWN"
|
25
|
+
end
|
26
|
+
|
27
|
+
module Types
|
28
|
+
# Execute the order immediately at the best-available price.
|
29
|
+
# More Info <https://www.investopedia.com/terms/m/marketorder.asp>
|
30
|
+
MARKET = "MARKET"
|
31
|
+
LIMIT = "LIMIT"
|
32
|
+
STOP = "STOP"
|
33
|
+
STOP_LIMIT = "STOP_LIMIT"
|
34
|
+
TRAILING_STOP = "TRAILING_STOP"
|
35
|
+
CABINET = "CABINET"
|
36
|
+
NON_MARKETABLE = "NON_MARKETABLE"
|
37
|
+
MARKET_ON_CLOSE = "MARKET_ON_CLOSE"
|
38
|
+
EXERCISE = "EXERCISE"
|
39
|
+
TRAILING_STOP_LIMIT = "TRAILING_STOP_LIMIT"
|
40
|
+
NET_DEBIT = "NET_DEBIT"
|
41
|
+
NET_CREDIT = "NET_CREDIT"
|
42
|
+
NET_ZERO = "NET_ZERO"
|
43
|
+
LIMIT_ON_CLOSE = "LIMIT_ON_CLOSE"
|
44
|
+
end
|
45
|
+
|
46
|
+
module ComplexOrderStrategyTypes
|
47
|
+
# Explicit order strategies for executing multi-leg options orders.
|
48
|
+
|
49
|
+
# No complex order strategy. This is the default.
|
50
|
+
NONE = "NONE"
|
51
|
+
COVERED = "COVERED"
|
52
|
+
VERTICAL = "VERTICAL"
|
53
|
+
BACK_RATIO = "BACK_RATIO"
|
54
|
+
CALENDAR = "CALENDAR"
|
55
|
+
DIAGONAL = "DIAGONAL"
|
56
|
+
STRADDLE = "STRADDLE"
|
57
|
+
STRANGLE = "STRANGLE"
|
58
|
+
COLLAR_SYNTHETIC = "COLLAR_SYNTHETIC"
|
59
|
+
BUTTERFLY = "BUTTERFLY"
|
60
|
+
CONDOR = "CONDOR"
|
61
|
+
IRON_CONDOR = "IRON_CONDOR"
|
62
|
+
VERTICAL_ROLL = "VERTICAL_ROLL"
|
63
|
+
COLLAR_WITH_STOCK = "COLLAR_WITH_STOCK"
|
64
|
+
DOUBLE_DIAGONAL = "DOUBLE_DIAGONAL"
|
65
|
+
UNBALANCED_BUTTERFLY = "UNBALANCED_BUTTERFLY"
|
66
|
+
UNBALANCED_CONDOR = "UNBALANCED_CONDOR"
|
67
|
+
UNBALANCED_IRON_CONDOR = "UNBALANCED_IRON_CONDOR"
|
68
|
+
UNBALANCED_VERTICAL_ROLL = "UNBALANCED_VERTICAL_ROLL"
|
69
|
+
|
70
|
+
# Mutual fund swap
|
71
|
+
MUTUAL_FUND_SWAP = "MUTUAL_FUND_SWAP"
|
72
|
+
|
73
|
+
# A custom multi-leg order strategy.
|
74
|
+
CUSTOM = "CUSTOM"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module SchwabRb::Orders::Session
|
2
|
+
# Normal market hours, from 9:30am to 4:00pm Eastern.
|
3
|
+
NORMAL = 'NORMAL'
|
4
|
+
|
5
|
+
# Premarket session, from 8:00am to 9:30am Eastern.
|
6
|
+
AM = 'AM'
|
7
|
+
|
8
|
+
# After-market session, from 4:00pm to 8:00pm Eastern.
|
9
|
+
PM = 'PM'
|
10
|
+
|
11
|
+
# Orders are active during all trading sessions except the overnight
|
12
|
+
# session. This is the union of ``NORMAL``, ``AM``, and ``PM``.
|
13
|
+
SEAMLESS = 'SEAMLESS'
|
14
|
+
end
|