tastytrade 0.2.0 → 0.3.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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.claude/commands/plan.md +13 -0
  3. data/.claude/commands/release-pr.md +12 -0
  4. data/CHANGELOG.md +170 -0
  5. data/README.md +424 -3
  6. data/ROADMAP.md +17 -17
  7. data/lib/tastytrade/cli/history_formatter.rb +304 -0
  8. data/lib/tastytrade/cli/orders.rb +749 -0
  9. data/lib/tastytrade/cli/positions_formatter.rb +114 -0
  10. data/lib/tastytrade/cli.rb +701 -12
  11. data/lib/tastytrade/cli_helpers.rb +111 -14
  12. data/lib/tastytrade/client.rb +7 -0
  13. data/lib/tastytrade/file_store.rb +83 -0
  14. data/lib/tastytrade/instruments/equity.rb +42 -0
  15. data/lib/tastytrade/models/account.rb +160 -2
  16. data/lib/tastytrade/models/account_balance.rb +46 -0
  17. data/lib/tastytrade/models/buying_power_effect.rb +61 -0
  18. data/lib/tastytrade/models/live_order.rb +272 -0
  19. data/lib/tastytrade/models/order_response.rb +106 -0
  20. data/lib/tastytrade/models/order_status.rb +84 -0
  21. data/lib/tastytrade/models/trading_status.rb +200 -0
  22. data/lib/tastytrade/models/transaction.rb +151 -0
  23. data/lib/tastytrade/models.rb +6 -0
  24. data/lib/tastytrade/order.rb +191 -0
  25. data/lib/tastytrade/order_validator.rb +355 -0
  26. data/lib/tastytrade/session.rb +26 -1
  27. data/lib/tastytrade/session_manager.rb +43 -14
  28. data/lib/tastytrade/version.rb +1 -1
  29. data/lib/tastytrade.rb +43 -0
  30. data/spec/exe/tastytrade_spec.rb +1 -1
  31. data/spec/spec_helper.rb +72 -0
  32. data/spec/tastytrade/cli/positions_spec.rb +267 -0
  33. data/spec/tastytrade/cli_auth_spec.rb +5 -0
  34. data/spec/tastytrade/cli_env_login_spec.rb +199 -0
  35. data/spec/tastytrade/cli_helpers_spec.rb +3 -26
  36. data/spec/tastytrade/cli_orders_spec.rb +168 -0
  37. data/spec/tastytrade/cli_status_spec.rb +153 -164
  38. data/spec/tastytrade/file_store_spec.rb +126 -0
  39. data/spec/tastytrade/models/account_balance_spec.rb +103 -0
  40. data/spec/tastytrade/models/account_order_history_spec.rb +229 -0
  41. data/spec/tastytrade/models/account_order_management_spec.rb +271 -0
  42. data/spec/tastytrade/models/account_place_order_spec.rb +125 -0
  43. data/spec/tastytrade/models/account_spec.rb +86 -15
  44. data/spec/tastytrade/models/buying_power_effect_spec.rb +250 -0
  45. data/spec/tastytrade/models/live_order_json_spec.rb +144 -0
  46. data/spec/tastytrade/models/live_order_spec.rb +295 -0
  47. data/spec/tastytrade/models/order_response_spec.rb +96 -0
  48. data/spec/tastytrade/models/order_status_spec.rb +113 -0
  49. data/spec/tastytrade/models/trading_status_spec.rb +260 -0
  50. data/spec/tastytrade/models/transaction_spec.rb +236 -0
  51. data/spec/tastytrade/order_edge_cases_spec.rb +163 -0
  52. data/spec/tastytrade/order_spec.rb +201 -0
  53. data/spec/tastytrade/order_validator_spec.rb +347 -0
  54. data/spec/tastytrade/session_env_spec.rb +169 -0
  55. data/spec/tastytrade/session_manager_spec.rb +43 -33
  56. data/vcr_implementation_plan.md +403 -0
  57. data/vcr_implementation_research.md +330 -0
  58. metadata +50 -18
  59. data/lib/tastytrade/keyring_store.rb +0 -72
  60. data/spec/tastytrade/keyring_store_spec.rb +0 -168
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b4642b3bfaeb7906f2733b1da34c2bafea177177fb6670f2271b50b720673236
4
- data.tar.gz: d65a41b22c7eba317269b454e38188b1e19c504726771d140d72653aa7e7c617
3
+ metadata.gz: aa2b6fbe38925319fd0577393a7c12f9b852500c85185c51ad73da56b8724422
4
+ data.tar.gz: 5c650bdbceeb19a32ddcc6e4c610f63d5a0cb8212df4c3875c1544ef91714204
5
5
  SHA512:
6
- metadata.gz: 7dd6ac7a321ed6d7c6b9519f82988029f5e49515acfff9583d22bba99b2da2ab61666e9054ee232a71afdd3179bcc97c1765e071081722160251ef207340f2d2
7
- data.tar.gz: 20b1acf6efba69d72bee9448c39825178701a0e4a20be5de813f1607860fa201b5ed68d2269b2d465fa085bc817d7ffa0ff7f7d89dd68849d197f18463841d51
6
+ metadata.gz: 9c3a31572d50be8e5bf74aed909e08c0befa1882de0d671c40ad8b9de956ad9c62c1fbededb5bbc5ea883a96aeaee9e1a27c63616c3ef21eaef7e9888a1ea746
7
+ data.tar.gz: dcf15ae057baeb7aa067c21444efbe481ea6bdc23515ab9f286935d8a406b5fa5d91c0b2e439fa3103bba0c97b76996074d569253a5b7f6671172a0c8a9d4376
@@ -0,0 +1,13 @@
1
+ We will implement issue $ARGUMENTS. Please review the issues first to understand what we're doing. You will
2
+ then spawn multiple concurrent subagents in parallel to do the following:
3
+
4
+ - one will review the codebase to research the integration points for the new code or code to modify. If
5
+ the feature has already been implemented they will make note of that.
6
+ - one will review the tastytrade python SDK reference to compare the implementation to fully explain
7
+ what features we are copying.
8
+ - one will review the tastytrade python SDK cli tool reference to fully explain what features we are
9
+ trying to copy.
10
+
11
+ You will then take the output from the subagents to compile an implementation plan and update the todos
12
+ to fully encapsulate the work down to the smallest possible unit of work. You will not continue until I
13
+ approve the plan.
@@ -86,6 +86,18 @@ Create a release PR following Ruby gem best practices.
86
86
  After merging this PR:
87
87
  1. \`git checkout main && git pull\`
88
88
  2. \`bundle exec rake release\`
89
+ 3. Create a GitHub Release:
90
+ \`\`\`bash
91
+ gh release create v<VERSION> \\
92
+ --title "v<VERSION>" \\
93
+ --generate-notes \\
94
+ --draft
95
+ \`\`\`
96
+ 4. Edit the draft release to add a summary section at the top with key highlights
97
+ 5. Publish the release:
98
+ \`\`\`bash
99
+ gh release edit v<VERSION> --draft=false
100
+ \`\`\`
89
101
 
90
102
  Note: The rake release command will automatically create and push the git tag v<VERSION>"
91
103
  ```
data/CHANGELOG.md CHANGED
@@ -25,6 +25,176 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
25
25
  ### Security
26
26
  - Nothing yet
27
27
 
28
+ ## [0.3.0] - 2025-08-08
29
+
30
+ ### Added
31
+ - Order time-in-force CLI support (#15)
32
+ - Added --time-in-force option to `order place` command
33
+ - Support for DAY and GTC (Good Till Cancelled) order durations
34
+ - Accepts shorthand aliases: "d" for DAY, "g" or "good_till_cancelled" for GTC
35
+ - Defaults to DAY order when not specified (backward compatible)
36
+ - Display time-in-force in order summaries and order history tables
37
+ - Added TIF column to order list and history displays
38
+ - Complete test coverage for time-in-force parameter handling
39
+ - Note: Core Order class already had full DAY/GTC support
40
+ - Comprehensive order validation framework (#14)
41
+ - OrderValidator class with multi-layer validation checks
42
+ - Symbol validation via Instruments API
43
+ - Quantity validation with min/max constraints (1-999,999)
44
+ - Price validation with tick size rounding
45
+ - Account permissions validation using TradingStatus
46
+ - Buying power validation via dry-run API calls
47
+ - Market hours validation with warnings
48
+ - Specific error classes (OrderValidationError, InvalidSymbolError, etc.)
49
+ - Integration into Account#place_order method
50
+ - Order#validate! and Order#dry_run helper methods
51
+ - CLI `order place` command with validation support
52
+ - Dry-run mode for testing orders without submission
53
+ - Confirmation prompts with buying power impact display
54
+ - Comprehensive test coverage for all validation scenarios
55
+ - Enhanced order status and history functionality (#13)
56
+ - Account#get_order_history method for retrieving orders beyond 24 hours
57
+ - Account#get_order method for fetching individual order details
58
+ - Date range filtering for order history with from/to parameters
59
+ - Pagination support for large order history queries
60
+ - JSON output format for all order CLI commands (--format json)
61
+ - LiveOrder#to_h method for JSON serialization
62
+ - `order history` CLI command with comprehensive filtering options
63
+ - `order get` CLI command for detailed single order information
64
+ - Enhanced display_order_details method showing fills and timestamps
65
+ - Complete test coverage for new order history methods
66
+ - Order cancellation and replacement functionality (#12)
67
+ - LiveOrder model for parsing existing orders from API
68
+ - OrderStatus module with status constants and validation helpers
69
+ - Account#get_live_orders method with status/symbol/time filtering
70
+ - Account#cancel_order method with proper error handling
71
+ - Account#replace_order method with partial fill support
72
+ - Custom exceptions for order operations (OrderNotCancellableError, OrderAlreadyFilledError, etc.)
73
+ - CLI `order` subcommands structure with list/cancel/replace operations
74
+ - `order list` command with real-time order display and status filtering
75
+ - `order cancel` command with confirmation prompt and order details
76
+ - `order replace` command with interactive price/quantity modification
77
+ - Partial fill tracking with filled/remaining quantity calculations
78
+ - Order status color coding in CLI output
79
+ - VCR test configuration with sensitive data filtering
80
+ - Comprehensive test coverage for all order management features
81
+ - Integration tests for complete order lifecycle (place, list, modify, cancel)
82
+ - Renamed existing `order` command to `place` for clarity
83
+ - Account trading status and permissions (#10)
84
+ - TradingStatus model with 35+ fields matching Python SDK structure
85
+ - Complete account state tracking (frozen, closed, margin call, PDT status)
86
+ - Trading permissions for options, futures, cryptocurrency, and short calls
87
+ - Options trading level parsing and validation
88
+ - Pattern Day Trader (PDT) status with reset dates and day trade counts
89
+ - Portfolio margin and risk-reducing mode indicators
90
+ - Account restrictions detection and listing
91
+ - Helper methods for permission checking (can_trade_options?, can_trade_futures?, etc.)
92
+ - CLI `trading_status` command with color-coded warnings
93
+ - Visual indicators for account restrictions and margin calls
94
+ - Display of fee schedule and margin calculation type
95
+ - Full test coverage for all trading status features
96
+ - Claude command for planning multi-issue implementations
97
+ - `.claude/commands/plan.md` command for structured issue planning
98
+ - Spawns concurrent subagents to research codebase, Python SDK, and CLI
99
+ - Compiles comprehensive implementation plans with detailed todos
100
+ - Requires user approval before proceeding with implementation
101
+ - Transaction history functionality (#8)
102
+ - Transaction model with comprehensive field support including fees and metadata
103
+ - Get all transactions with automatic pagination
104
+ - Filtering by date range, symbol, instrument type, and transaction types
105
+ - Manual pagination control with page_offset and per_page parameters
106
+ - Account#get_transactions convenience method
107
+ - CLI `history` command with table display and filtering options
108
+ - Grouping transactions by symbol, type, or date
109
+ - Transaction totals and summaries (credits, debits, fees, net cash flow)
110
+ - Interactive history menu with date and symbol filtering
111
+ - Full test coverage for Transaction model and API integration
112
+ - Buying power calculation and monitoring (#9)
113
+ - Extended AccountBalance model with buying power calculation methods
114
+ - Buying power usage percentage for equity, derivative, and day trading
115
+ - Check if sufficient buying power exists for orders
116
+ - Calculate buying power impact percentage for proposed orders
117
+ - BuyingPowerEffect model for dry-run order validation
118
+ - Dry-run orders now return detailed buying power impact information
119
+ - CLI `buying_power` command to display buying power status
120
+ - Buying power warnings when placing orders that use >80% of available BP
121
+ - Interactive confirmation for high buying power usage orders
122
+ - Integration with order placement workflow (both CLI and interactive)
123
+ - Comprehensive test coverage for all buying power calculations
124
+ - Order placement functionality for equities (#11)
125
+ - Order and OrderLeg classes for building orders programmatically
126
+ - Support for market and limit order types
127
+ - All four order actions: BUY_TO_OPEN, SELL_TO_CLOSE, SELL_TO_OPEN, BUY_TO_CLOSE
128
+ - Time in force options: DAY and GTC
129
+ - Automatic price-effect calculation (Debit for buys, Credit for sells)
130
+ - Account#place_order method for order submission
131
+ - OrderResponse model for parsing placement results
132
+ - Equity instrument class with build_leg helper method
133
+ - CLI `order` command with options for type, price, action, and dry-run
134
+ - Interactive order menu with vim navigation for order type and action
135
+ - Dry-run simulation capability for testing orders
136
+ - Improved error handling with helpful messages for common scenarios
137
+ - Comprehensive test coverage for all order functionality
138
+ - CLI positions command (#7)
139
+ - `positions` command to display account positions in table format
140
+ - Position filtering options: --symbol, --underlying-symbol, --include-closed
141
+ - Account selection with --account option
142
+ - Color-coded P/L display (green for profit, red for loss)
143
+ - Summary statistics showing total P/L and winners/losers count
144
+ - Option-specific display formatting (e.g., "AAPL 150C 1/19")
145
+ - Support for short positions with negative quantity display
146
+ - Integration with interactive mode and balance submenu
147
+ - Positions formatter for table display
148
+ - TTY::Table integration for professional formatting
149
+ - BigDecimal precision for monetary values
150
+ - Automatic symbol formatting for options
151
+ - Summary row with position statistics
152
+ - Environment variable authentication support
153
+ - Session.from_environment class method for creating sessions from env vars
154
+ - Support for TASTYTRADE_USERNAME, TASTYTRADE_PASSWORD (or TT_ prefixed)
155
+ - Optional TASTYTRADE_ENVIRONMENT for sandbox/production selection
156
+ - Optional TASTYTRADE_REMEMBER for automatic session refresh
157
+ - CLI automatically attempts env var login before prompting
158
+ - Fallback to interactive login if env var authentication fails
159
+ - Complete test coverage for all environment variable scenarios
160
+ - Enhanced CLI documentation
161
+ - Comprehensive login command help with environment variable examples
162
+ - README documentation for environment variable configuration
163
+ - Examples for CI/CD and automation use cases
164
+ - CLI login improvements
165
+ - Added --no-interactive flag to skip interactive mode after login
166
+ - Useful for scripting and CI/CD environments
167
+ - Correctly detects environment (sandbox/production) from env vars
168
+ - GitHub Release creation instructions in release workflow
169
+ - Added `gh release create` command to release-pr.md
170
+ - Automated release notes generation with --generate-notes flag
171
+ - Draft release workflow for review before publishing
172
+
173
+ ### Changed
174
+ - Session storage switched from keyring to secure file-based storage
175
+ - Sessions now stored in ~/.config/tastytrade/credentials/ with 0600 permissions
176
+ - More reliable across different systems without keyring dependencies
177
+ - Credentials directory created with 0700 permissions for security
178
+ - User data (email, username, external_id) now saved with sessions for validation
179
+
180
+ ### Fixed
181
+ - Session persistence issues between command invocations
182
+ - Fixed session corruption after first command execution
183
+ - Sessions now properly persist across multiple CLI commands
184
+ - Removed problematic session validation on load that was causing failures
185
+ - Removed stray error message "Failed to load current account" from positions/balance commands
186
+ - Error now only displays when DEBUG_SESSION environment variable is set
187
+ - Fixed all test failures related to file-based storage implementation
188
+ - Updated FileStore tests to properly mock temporary directories
189
+ - Fixed CLI auth tests to stub environment variable checks
190
+ - Added missing user attributes to test mocks
191
+ - Updated session manager tests for new user data saving/loading
192
+
193
+ ### Removed
194
+ - Keyring gem dependency and KeyringStore implementation
195
+ - Replaced with more reliable file-based credential storage
196
+ - Eliminates cross-platform keyring compatibility issues
197
+
28
198
  ## [0.2.0] - 2025-08-01
29
199
 
30
200
  ### Added
data/README.md CHANGED
@@ -20,9 +20,11 @@ This Ruby gem provides a simple interface to interact with the Tastytrade API, a
20
20
  - Secure authentication with Tastytrade API
21
21
  - Real-time market data access
22
22
  - Account management and portfolio tracking
23
- - Order placement and management
23
+ - Order placement and management with dry-run support
24
24
  - Position monitoring
25
- - Transaction history
25
+ - Transaction history with filtering and grouping
26
+ - Buying power calculations and monitoring
27
+ - CLI with interactive mode and rich formatting
26
28
 
27
29
  ## Roadmap
28
30
 
@@ -48,6 +50,30 @@ Or install it yourself as:
48
50
  gem install tastytrade
49
51
  ```
50
52
 
53
+ ## Configuration
54
+
55
+ ### Environment Variables
56
+
57
+ The tastytrade gem supports authentication via environment variables, which is recommended for automation and CI/CD environments:
58
+
59
+ ```bash
60
+ # Required for environment variable authentication
61
+ export TASTYTRADE_USERNAME="your_email@example.com"
62
+ export TASTYTRADE_PASSWORD="your_password"
63
+
64
+ # Optional environment variables
65
+ export TASTYTRADE_ENVIRONMENT="sandbox" # Use "sandbox" for test environment
66
+ export TASTYTRADE_REMEMBER="true" # Enable remember token
67
+
68
+ # Alternative shorter variable names
69
+ export TT_USERNAME="your_email@example.com"
70
+ export TT_PASSWORD="your_password"
71
+ export TT_ENVIRONMENT="sandbox"
72
+ export TT_REMEMBER="true"
73
+ ```
74
+
75
+ When environment variables are set, the CLI will automatically use them for authentication without prompting for credentials.
76
+
51
77
  ## Usage
52
78
 
53
79
  ### Authentication
@@ -75,19 +101,165 @@ session.authenticated? # => true
75
101
 
76
102
  The gem includes a command-line interface for common operations:
77
103
 
104
+ #### Authentication
105
+
78
106
  ```bash
79
- # Login to your account
107
+ # Login to your account interactively
80
108
  tastytrade login
81
109
 
82
110
  # Login with remember option for automatic session refresh
83
111
  tastytrade login --remember
84
112
 
113
+ # Login using environment variables (recommended for automation)
114
+ export TASTYTRADE_USERNAME="your_email@example.com"
115
+ export TASTYTRADE_PASSWORD="your_password"
116
+ tastytrade login
117
+
118
+ # Or use shorter variable names
119
+ export TT_USERNAME="your_email@example.com"
120
+ export TT_PASSWORD="your_password"
121
+ tastytrade login
122
+
123
+ # Use sandbox environment for testing
124
+ export TASTYTRADE_ENVIRONMENT="sandbox"
125
+ tastytrade login
126
+
127
+ # Enable remember token via environment
128
+ export TASTYTRADE_REMEMBER="true"
129
+ tastytrade login
130
+
131
+ ```
132
+
133
+ #### Account Operations
134
+
135
+ ```bash
85
136
  # View account balances
86
137
  tastytrade balance
87
138
 
88
139
  # View balances for all accounts
89
140
  tastytrade balance --all
90
141
 
142
+ # View account positions
143
+ tastytrade positions
144
+
145
+ # Filter positions by symbol
146
+ tastytrade positions --symbol AAPL
147
+
148
+ # Filter positions by underlying symbol (for options)
149
+ tastytrade positions --underlying-symbol SPY
150
+
151
+ # View trading status and permissions
152
+ tastytrade trading_status
153
+
154
+ # View status for specific account
155
+ tastytrade trading_status --account 5WT0001
156
+
157
+ # Include closed positions
158
+ tastytrade positions --include-closed
159
+ ```
160
+
161
+ #### Transaction History
162
+
163
+ ```bash
164
+ # View all transactions
165
+ tastytrade history
166
+
167
+ # Filter by date range
168
+ tastytrade history --start-date 2024-01-01 --end-date 2024-12-31
169
+
170
+ # Filter by symbol
171
+ tastytrade history --symbol AAPL
172
+
173
+ # Group transactions by symbol, type, or date
174
+ tastytrade history --group-by symbol
175
+ tastytrade history --group-by type
176
+ tastytrade history --group-by date
177
+
178
+ # Limit number of transactions
179
+ tastytrade history --limit 50
180
+
181
+ # Combine filters
182
+ tastytrade history --symbol AAPL --start-date 2024-01-01 --group-by date
183
+ ```
184
+
185
+ #### Buying Power Status
186
+
187
+ ```bash
188
+ # View buying power status
189
+ tastytrade buying_power
190
+
191
+ # View buying power for specific account
192
+ tastytrade buying_power --account 5WX12345
193
+ ```
194
+
195
+ #### Order Management
196
+
197
+ ##### Order Placement
198
+
199
+ ```bash
200
+ # Place a limit buy order
201
+ tastytrade order place --symbol AAPL --action buy_to_open --quantity 100 --price 150.50
202
+
203
+ # Place a market order
204
+ tastytrade order place --symbol SPY --action buy_to_open --quantity 10 --type market
205
+
206
+ # Sell to close a position
207
+ tastytrade order place --symbol AAPL --action sell_to_close --quantity 100 --price 155.00
208
+
209
+ # Dry-run validation (validate without placing)
210
+ tastytrade order place --symbol MSFT --action buy_to_open --quantity 50 --price 300 --dry-run
211
+
212
+ # Skip confirmation prompt
213
+ tastytrade order place --symbol TSLA --action buy_to_open --quantity 10 --price 200 --skip-confirmation
214
+
215
+ # Supported actions:
216
+ # - buy_to_open (bto)
217
+ # - sell_to_close (stc)
218
+ # - sell_to_open (sto)
219
+ # - buy_to_close (btc)
220
+
221
+ # Note: Orders that would use >80% of buying power will prompt for confirmation
222
+ ```
223
+
224
+ ##### Order Status and History
225
+
226
+ ```bash
227
+ # List all live orders (open + last 24 hours)
228
+ tastytrade order list
229
+
230
+ # List orders with filters
231
+ tastytrade order list --status Live
232
+ tastytrade order list --symbol AAPL
233
+ tastytrade order list --all # Show for all accounts
234
+
235
+ # Output orders in JSON format
236
+ tastytrade order list --format json
237
+
238
+ # Get historical orders (beyond 24 hours)
239
+ tastytrade order history
240
+ tastytrade order history --status Filled
241
+ tastytrade order history --symbol AAPL
242
+ tastytrade order history --from 2024-01-01 --to 2024-12-31
243
+ tastytrade order history --limit 100
244
+ tastytrade order history --format json
245
+
246
+ # Get details for a specific order
247
+ tastytrade order get ORDER_ID
248
+ tastytrade order get ORDER_ID --format json
249
+
250
+ # Cancel an order
251
+ tastytrade order cancel ORDER_ID
252
+ tastytrade order cancel ORDER_ID --account 5WX12345
253
+
254
+ # Replace/modify an order
255
+ tastytrade order replace ORDER_ID # Interactive prompts for new price/quantity
256
+ tastytrade order replace ORDER_ID --price 155.00
257
+ tastytrade order replace ORDER_ID --quantity 50
258
+ ```
259
+
260
+ #### Account Management
261
+
262
+ ```bash
91
263
  # List all accounts
92
264
  tastytrade accounts
93
265
 
@@ -129,11 +301,21 @@ balance.cash_balance # => BigDecimal("10000.50")
129
301
  balance.net_liquidating_value # => BigDecimal("42001.00")
130
302
  balance.equity_buying_power # => BigDecimal("20000.00")
131
303
  balance.available_trading_funds # => BigDecimal("12000.00")
304
+ balance.day_trading_buying_power # => BigDecimal("40000.00")
305
+ balance.derivative_buying_power # => BigDecimal("20000.00")
132
306
 
133
307
  # Check buying power usage
134
308
  balance.buying_power_usage_percentage # => BigDecimal("40.00")
309
+ balance.derivative_buying_power_usage_percentage # => BigDecimal("25.00")
135
310
  balance.high_buying_power_usage? # => false (checks if > 80%)
136
311
 
312
+ # Check if sufficient buying power for order
313
+ balance.sufficient_buying_power?(15000) # => true
314
+ balance.sufficient_buying_power?(15000, buying_power_type: :derivative) # => true
315
+
316
+ # Calculate buying power impact
317
+ balance.buying_power_impact_percentage(15000) # => BigDecimal("75.00")
318
+
137
319
  # Calculate totals
138
320
  balance.total_equity_value # => BigDecimal("30001.00")
139
321
  balance.total_derivative_value # => BigDecimal("4500.00")
@@ -168,6 +350,245 @@ positions.each do |position|
168
350
  end
169
351
  ```
170
352
 
353
+ ### Order Placement
354
+
355
+ ```ruby
356
+ # Create an order leg for buying stock
357
+ leg = Tastytrade::OrderLeg.new(
358
+ action: Tastytrade::OrderAction::BUY_TO_OPEN,
359
+ symbol: 'AAPL',
360
+ quantity: 100
361
+ )
362
+
363
+ # Create a market order
364
+ market_order = Tastytrade::Order.new(
365
+ type: Tastytrade::OrderType::MARKET,
366
+ legs: leg
367
+ )
368
+
369
+ # Create a limit order
370
+ limit_order = Tastytrade::Order.new(
371
+ type: Tastytrade::OrderType::LIMIT,
372
+ legs: leg,
373
+ price: 150.50 # Will be converted to BigDecimal
374
+ )
375
+
376
+ # Place the order
377
+ response = account.place_order(session, market_order)
378
+
379
+ # Dry run (simulate order without placing)
380
+ response = account.place_order(session, limit_order, dry_run: true)
381
+
382
+ # Check order response
383
+ puts response.order_id # => "123456"
384
+ puts response.status # => "Filled"
385
+
386
+ # Dry run orders return a BuyingPowerEffect object
387
+ if response.buying_power_effect.is_a?(Tastytrade::Models::BuyingPowerEffect)
388
+ bp_effect = response.buying_power_effect
389
+ puts bp_effect.buying_power_change_amount # => BigDecimal("15050.00")
390
+ puts bp_effect.buying_power_usage_percentage # => BigDecimal("75.25")
391
+ puts bp_effect.exceeds_threshold?(80) # => false
392
+ puts bp_effect.debit? # => true
393
+ else
394
+ puts response.buying_power_effect # => BigDecimal("-15050.00")
395
+ end
396
+
397
+ puts response.warnings # => [] or warning messages
398
+ ```
399
+
400
+ ### Order Management
401
+
402
+ ```ruby
403
+ # Get live orders (open orders + orders from last 24 hours)
404
+ orders = account.get_live_orders(session)
405
+
406
+ # Filter orders by status
407
+ live_orders = account.get_live_orders(session, status: "Live")
408
+ filled_orders = account.get_live_orders(session, status: "Filled")
409
+
410
+ # Filter orders by symbol
411
+ aapl_orders = account.get_live_orders(session, underlying_symbol: "AAPL")
412
+
413
+ # Filter by time range
414
+ recent_orders = account.get_live_orders(session,
415
+ from_time: Time.now - 86400, # Last 24 hours
416
+ to_time: Time.now
417
+ )
418
+
419
+ # Work with order details
420
+ orders.each do |order|
421
+ puts order.id # => "12345"
422
+ puts order.status # => "Live"
423
+ puts order.underlying_symbol # => "AAPL"
424
+ puts order.order_type # => "Limit"
425
+ puts order.price # => BigDecimal("150.50")
426
+
427
+ # Check order capabilities
428
+ puts order.cancellable? # => true
429
+ puts order.editable? # => true
430
+ puts order.terminal? # => false
431
+ puts order.working? # => true
432
+
433
+ # Check fill status
434
+ puts order.remaining_quantity # => 100
435
+ puts order.filled_quantity # => 0
436
+
437
+ # Work with order legs
438
+ order.legs.each do |leg|
439
+ puts leg.symbol # => "AAPL"
440
+ puts leg.action # => "Buy"
441
+ puts leg.quantity # => 100
442
+ puts leg.remaining_quantity # => 100
443
+ puts leg.partially_filled? # => false
444
+ end
445
+ end
446
+
447
+ # Cancel an order
448
+ account.cancel_order(session, "12345")
449
+
450
+ # Replace an order with new parameters
451
+ new_order = Tastytrade::Order.new(
452
+ type: Tastytrade::OrderType::LIMIT,
453
+ legs: leg,
454
+ price: 155.00 # New price
455
+ )
456
+ response = account.replace_order(session, "12345", new_order)
457
+ ```
458
+
459
+ ### Order Validation
460
+
461
+ The SDK includes comprehensive order validation to prevent submission errors and ensure orders meet all requirements before reaching the API.
462
+
463
+ #### Validation Features
464
+
465
+ ```ruby
466
+ # Orders are automatically validated before submission
467
+ order = Tastytrade::Order.new(
468
+ type: Tastytrade::OrderType::LIMIT,
469
+ legs: leg,
470
+ price: 150.00
471
+ )
472
+
473
+ # Validation happens automatically when placing orders
474
+ begin
475
+ response = account.place_order(session, order)
476
+ rescue Tastytrade::OrderValidationError => e
477
+ puts "Validation failed:"
478
+ e.errors.each { |error| puts " - #{error}" }
479
+ end
480
+
481
+ # You can also validate manually
482
+ order.validate!(session, account) # Raises if invalid
483
+
484
+ # Or perform a dry-run validation
485
+ dry_run_response = order.dry_run(session, account)
486
+ puts dry_run_response.buying_power_effect
487
+ puts dry_run_response.warnings
488
+ ```
489
+
490
+ #### Validation Rules
491
+
492
+ The following validations are performed:
493
+
494
+ 1. **Symbol Validation**
495
+ - Verifies symbol exists and is tradeable
496
+ - Checks instrument type compatibility
497
+
498
+ 2. **Quantity Validation**
499
+ - Minimum quantity: 1
500
+ - Maximum quantity: 999,999
501
+ - No fractional shares (whole numbers only)
502
+
503
+ 3. **Price Validation**
504
+ - Price must be positive for limit orders
505
+ - Price is rounded to appropriate tick size
506
+ - Price reasonableness checks
507
+
508
+ 4. **Account Permissions**
509
+ - Validates trading permissions for instrument type
510
+ - Checks for account restrictions (frozen, closing-only, etc.)
511
+ - Verifies options/futures permissions if applicable
512
+
513
+ 5. **Buying Power Validation**
514
+ - Ensures sufficient buying power via dry-run
515
+ - Warns if order uses >50% of available buying power
516
+ - Checks margin requirements
517
+
518
+ 6. **Market Hours Validation**
519
+ - Warns about market orders outside regular hours
520
+ - Alerts for weekend submissions
521
+
522
+ #### Validation Errors
523
+
524
+ ```ruby
525
+ # Specific validation error types
526
+ Tastytrade::OrderValidationError # General validation failure
527
+ Tastytrade::InvalidSymbolError # Symbol doesn't exist
528
+ Tastytrade::InsufficientBuyingPowerError # Not enough buying power
529
+ Tastytrade::AccountRestrictedError # Account has restrictions
530
+ Tastytrade::InvalidQuantityError # Quantity out of range
531
+ Tastytrade::InvalidPriceError # Price validation failure
532
+ Tastytrade::MarketClosedError # Market is closed
533
+ ```
534
+
535
+ #### Using the OrderValidator
536
+
537
+ ```ruby
538
+ # Direct use of OrderValidator for custom validation
539
+ validator = Tastytrade::OrderValidator.new(session, account, order)
540
+
541
+ # Perform full validation
542
+ validator.validate! # Raises if invalid
543
+
544
+ # Or just dry-run validation
545
+ dry_run_response = validator.dry_run_validate!
546
+
547
+ # Check warnings and errors
548
+ puts validator.warnings # Array of warning messages
549
+ puts validator.errors # Array of error messages
550
+ ```
551
+
552
+ #### Skip Validation (Use with Caution)
553
+
554
+ ```ruby
555
+ # Skip validation when you're certain the order is valid
556
+ response = account.place_order(session, order, skip_validation: true)
557
+ ```
558
+
559
+ ### Transaction History
560
+
561
+ ```ruby
562
+ # Get all transactions
563
+ transactions = account.get_transactions(session)
564
+
565
+ # Filter transactions
566
+ transactions = account.get_transactions(session,
567
+ start_date: Date.new(2024, 1, 1),
568
+ end_date: Date.new(2024, 12, 31),
569
+ symbol: 'AAPL',
570
+ transaction_types: ['Trade'],
571
+ per_page: 100
572
+ )
573
+
574
+ # Work with transactions
575
+ transactions.each do |transaction|
576
+ puts transaction.symbol # => "AAPL"
577
+ puts transaction.transaction_type # => "Trade"
578
+ puts transaction.transaction_sub_type # => "Buy"
579
+ puts transaction.quantity # => BigDecimal("100")
580
+ puts transaction.price # => BigDecimal("150.00")
581
+ puts transaction.value # => BigDecimal("-15000.00")
582
+ puts transaction.net_value # => BigDecimal("-15007.00")
583
+ puts transaction.executed_at # => Time object
584
+
585
+ # Fee breakdown
586
+ puts transaction.commission # => BigDecimal("5.00")
587
+ puts transaction.clearing_fees # => BigDecimal("1.00")
588
+ puts transaction.regulatory_fees # => BigDecimal("0.50")
589
+ end
590
+ ```
591
+
171
592
  ## Development
172
593
 
173
594
  After checking out the repo, run `bin/setup` to install dependencies and verify your environment is configured correctly.