iron_warbler 2.0.7.25 → 2.0.7.26

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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/stylesheets/iron_warbler/Card.scss +6 -0
  3. data/app/assets/stylesheets/iron_warbler/positions.scss +1 -1
  4. data/app/assets/stylesheets/iron_warbler/purses_summary.scss +31 -19
  5. data/app/controllers/iro/application_controller.rb +6 -0
  6. data/app/controllers/iro/positions_controller.rb +183 -200
  7. data/app/controllers/iro/purses_controller.rb +3 -1
  8. data/app/controllers/iro/stocks_controller.rb +2 -2
  9. data/app/models/iro/option.rb +38 -150
  10. data/app/models/iro/option_black_scholes.rb +149 -0
  11. data/app/models/iro/position.rb +154 -209
  12. data/app/models/iro/purse.rb +34 -4
  13. data/app/models/iro/strategy.rb +49 -47
  14. data/app/views/iro/_main_header.haml +4 -2
  15. data/app/views/iro/options/_show_mini.haml +8 -0
  16. data/app/views/iro/positions/_form.haml +8 -3
  17. data/app/views/iro/positions/_formpart_4data.haml +41 -38
  18. data/app/views/iro/positions/_gameui_long_debit_call_spread.haml +4 -4
  19. data/app/views/iro/positions/_gameui_long_debit_call_spread.haml-trash +42 -0
  20. data/app/views/iro/positions/_gameui_short_debit_put_spread.haml +1 -0
  21. data/app/views/iro/positions/_gameui_short_debit_put_spread.haml-trash +40 -0
  22. data/app/views/iro/positions/_header.haml +2 -0
  23. data/app/views/iro/positions/_header_long_debit_call_spread.haml +43 -25
  24. data/app/views/iro/positions/_prepare_long_debit_call_spread.haml +2 -3
  25. data/app/views/iro/positions/_prepare_short_debit_put_spread.haml +2 -1
  26. data/app/views/iro/positions/_table.haml +25 -26
  27. data/app/views/iro/positions/prepare.haml +6 -4
  28. data/app/views/iro/positions/prepare2.haml +15 -4
  29. data/app/views/iro/purses/_form_extra_fields.haml +7 -3
  30. data/app/views/iro/purses/_header.haml +19 -5
  31. data/app/views/iro/purses/_summary.haml +69 -62
  32. data/app/views/iro/purses/show.haml +1 -1
  33. data/app/views/iro/strategies/_form.haml +26 -19
  34. data/app/views/iro/strategies/_show.haml +6 -4
  35. data/config/routes.rb +5 -3
  36. metadata +7 -2
  37. data/app/views/iro/positions/_gameui_short_debit_put_spread.haml +0 -40
@@ -1,23 +1,23 @@
1
- require 'distribution'
2
- N = Distribution::Normal
3
- # include Math
4
- # require 'business_time'
5
1
 
6
2
  class Iro::Option
7
3
  include Mongoid::Document
8
4
  include Mongoid::Timestamps
9
5
  include Mongoid::Paranoia
6
+ include Iro::OptionBlackScholes
10
7
  store_in collection: 'iro_options'
11
8
 
12
9
  attr_accessor :recompute
13
10
 
14
- field :ticker
15
- validates :ticker, presence: true
11
+ belongs_to :stock, class_name: 'Iro::Stock', inverse_of: :strategies
12
+ def ticker; stock.ticker; end
13
+ # field :ticker
14
+ # validates :ticker, presence: true
16
15
 
17
16
  field :symbol
18
- validates :symbol, uniqueness: true, presence: true
17
+ ## each option can be a leg in a position, no uniqueness
18
+ # validates :symbol, uniqueness: true, presence: true
19
19
 
20
- field :put_call, type: :string
20
+ field :put_call, type: :string # 'PUT' or 'CALL'
21
21
  validates :put_call, presence: true
22
22
 
23
23
  field :delta, type: :float
@@ -27,14 +27,29 @@ class Iro::Option
27
27
 
28
28
  field :expires_on, type: :date
29
29
  validates :expires_on, presence: true
30
+ def self.expirations_list full: false
31
+ [
32
+ [ nil, nil ],
33
+ [ 'Mar 22', '2024-03-22'.to_date ],
34
+ [ 'Mar 28', '2024-03-28'.to_date ],
35
+ [ 'Apr 5', '2024-04-05'.to_date ],
36
+ [ 'Mar 12', '2024-03-12'.to_date ],
37
+ [ 'Mar 19', '2024-03-19'.to_date ],
38
+ ]
39
+ end
30
40
 
31
- belongs_to :stock, class_name: 'Iro::Stock', inverse_of: :strategies
41
+ field :begin_price, type: :float
42
+ field :begin_delta, type: :float
43
+ field :end_price, type: :float
44
+ field :end_delta, type: :float
32
45
 
33
- has_one :outer, class_name: 'Iro::Position', invese_of: :outer
34
- has_one :inner, class_name: 'Iro::Position', invese_of: :inner
46
+
47
+ has_one :outer, class_name: 'Iro::Position', inverse_of: :outer
48
+ has_one :inner, class_name: 'Iro::Position', inverse_of: :inner
35
49
 
36
50
  field :last, type: :float
37
51
 
52
+ ## for TDA
38
53
  def symbol
39
54
  if !self[:symbol]
40
55
  p_c_ = put_call == 'PUT' ? 'P' : 'C'
@@ -46,146 +61,19 @@ class Iro::Option
46
61
  self[:symbol]
47
62
  end
48
63
 
49
- ##
50
- ## black-scholes pricing
51
- ##
52
-
53
- =begin
54
- ##
55
- ##
56
- ##
57
- annual to daily:
58
-
59
- AR = ((DR + 1)^365 – 1) x 100
60
-
61
- ##
62
- ##
63
- ##
64
- From: https://www.investopedia.com/articles/optioninvestor/07/options_beat_market.asp
65
-
66
- K :: strike price
67
- S_t :: last
68
- r :: risk-free rate
69
- t :: time to maturity
70
-
71
- C = S_t N( d1 ) - K e^-rt N( d2 )
72
-
73
- d1 = ln( St / K ) + (r + theta**2 / 2 )t
74
- /{ theta_s * sqrt( t ) }
75
-
76
- d2 = d1 - theta_s sqrt( t )
77
-
78
- ##
79
- ## From: https://en.wikipedia.org/wiki/Black%E2%80%93Scholes_model
80
- ##
81
-
82
- D :: e^(rt) # discount factor
83
- F :: e^(rt) S # forward price of underlying
84
-
85
- C(F,t) = D[ N(d1)F - N(d2)K ]
86
-
87
- d1 = ln(F/K) + stdev**2 t / 2
88
- /{ stdev sqrt(t) }
89
- d2 = d1 - stdev sqrt(t)
90
-
91
- ##
92
- ## From: https://www.daytrading.com/options-pricing-models
93
- ##
94
- C0 = S0N(d1) – Xe-rtN(d2)
95
-
96
- C0 = current call premium
97
- S0 = current stock price
98
- N(d1) = the probability that a value in a normal distribution will be less than d
99
- N(d2) = the probability that the option will be in the money by expiration
100
- X = strike price of the option
101
- T = time until expiration (expressed in years)
102
- r = risk-free interest rate
103
- e = 2.71828, the base of the natural logarithm
104
- ln = natural logarithm function
105
- σ = standard deviation of the stock’s annualized rate of return (compounded continuously)
106
- d1 = ln(S0/X) + (r + σ2/2)Tσ√T
107
-
108
- d2 = d1 – σ√T
109
-
110
- Note that:
111
-
112
- Xe-rt = X/ert = the present value of the strike price using a continuously compounded interest rate
113
-
114
- ##
115
- ## From: https://www.wallstreetmojo.com/black-scholes-model/
116
- ##
117
-
118
-
119
- ## init
120
- require 'distribution'
121
- N = Distribution::Normal
122
- stock = Iro::Stock.find_by ticker: 'NVDA'
123
- strike = 910.0
124
- r = Iro::Option.rate_daily
125
- stdev = 91.0
126
- t = 7.0
127
- expires_on = '2024-03-22'
128
-
129
- =end
130
- def d1
131
- last = stock.last
132
- r = self.class.rate_annual
133
-
134
- out = Math.log( last / strike ) + ( r + stdev**2 / 2 ) * t
135
- out = out /( stdev * Math.sqrt(t) )
136
- return out
137
- end
138
- def d2
139
- last = stock.last
140
- r = self.class.rate_annual
141
-
142
- out = d1 - stdev * Math.sqrt( t )
143
- return out
144
- end
145
- def t
146
- # t = 1.0 / 365 * Date.today.business_days_until( expires_on )
147
- t = 1.0 / 365 * (expires_on - Date.today).to_i
148
- end
149
- def stdev
150
- recompute = nil
151
- stock.stdev( recompute: recompute )
152
- end
153
- def call_price
154
- last = stock.last
155
- r = self.class.rate_annual
156
-
157
- out = N.cdf( d1 ) * last - N.cdf( d2 ) * strike * Math::E**( -1 * r * t )
158
- return out
64
+ def sync
65
+ out = Tda::Option.get_quote({
66
+ contractType: put_call,
67
+ strike: strike,
68
+ expirationDate: expires_on,
69
+ ticker: ticker,
70
+ })
71
+ puts! out, 'option sync'
72
+ self.end_price = ( out.bid + out.ask ) / 2 rescue 0
73
+ self.end_delta = out.delta
74
+ # self.save
159
75
  end
160
76
 
161
- def put_price
162
- last = stock.last
163
- r = self.class.rate_annual
164
-
165
- out = N.cdf(-d2) * strike * exp(-r*t) - N.cdf(-d1) * last
166
- return out
167
- end
168
-
169
-
170
- def self.rate_annual
171
- 0.05
172
- end
173
-
174
- =begin
175
- # test
176
-
177
- inn = 100
178
- n.times { inn = inn*(1.0+out) }
179
- inn
180
-
181
- =end
182
- def self.rate_daily
183
- n = 250.0 # days
184
- # n = 12 # months
185
-
186
- out = (1.0+self.rate_annual)**(1.0/n) - 1.0
187
- puts! out, 'rate_daily'
188
- return out
189
- end
77
+ before_save :sync
190
78
 
191
79
  end
@@ -0,0 +1,149 @@
1
+
2
+ require 'distribution'
3
+ N = Distribution::Normal
4
+
5
+ module Iro::OptionBlackScholes
6
+
7
+ ##
8
+ ## black-scholes pricing
9
+ ##
10
+
11
+ =begin
12
+ ##
13
+ ##
14
+ ##
15
+ annual to daily:
16
+
17
+ AR = ((DR + 1)^365 – 1) x 100
18
+
19
+ ##
20
+ ##
21
+ ##
22
+ From: https://www.investopedia.com/articles/optioninvestor/07/options_beat_market.asp
23
+
24
+ K :: strike price
25
+ S_t :: last
26
+ r :: risk-free rate
27
+ t :: time to maturity
28
+
29
+ C = S_t N( d1 ) - K e^-rt N( d2 )
30
+
31
+ d1 = ln( St / K ) + (r + theta**2 / 2 )t
32
+ /{ theta_s * sqrt( t ) }
33
+
34
+ d2 = d1 - theta_s sqrt( t )
35
+
36
+ ##
37
+ ## From: https://en.wikipedia.org/wiki/Black%E2%80%93Scholes_model
38
+ ##
39
+
40
+ D :: e^(rt) # discount factor
41
+ F :: e^(rt) S # forward price of underlying
42
+
43
+ C(F,t) = D[ N(d1)F - N(d2)K ]
44
+
45
+ d1 = ln(F/K) + stdev**2 t / 2
46
+ /{ stdev sqrt(t) }
47
+ d2 = d1 - stdev sqrt(t)
48
+
49
+ ##
50
+ ## From: https://www.daytrading.com/options-pricing-models
51
+ ##
52
+ C0 = S0N(d1) – Xe-rtN(d2)
53
+
54
+ C0 = current call premium
55
+ S0 = current stock price
56
+ N(d1) = the probability that a value in a normal distribution will be less than d
57
+ N(d2) = the probability that the option will be in the money by expiration
58
+ X = strike price of the option
59
+ T = time until expiration (expressed in years)
60
+ r = risk-free interest rate
61
+ e = 2.71828, the base of the natural logarithm
62
+ ln = natural logarithm function
63
+ σ = standard deviation of the stock’s annualized rate of return (compounded continuously)
64
+ d1 = ln(S0/X) + (r + σ2/2)Tσ√T
65
+
66
+ d2 = d1 – σ√T
67
+
68
+ Note that:
69
+
70
+ Xe-rt = X/ert = the present value of the strike price using a continuously compounded interest rate
71
+
72
+ ##
73
+ ## From: https://www.wallstreetmojo.com/black-scholes-model/
74
+ ##
75
+
76
+
77
+ ## init
78
+ require 'distribution'
79
+ N = Distribution::Normal
80
+ stock = Iro::Stock.find_by ticker: 'NVDA'
81
+ strike = 910.0
82
+ r = Iro::Option.rate_daily
83
+ stdev = 91.0
84
+ t = 7.0
85
+ expires_on = '2024-03-22'
86
+
87
+ =end
88
+ def d1
89
+ last = stock.last
90
+ r = self.class.rate_annual
91
+
92
+ out = Math.log( last / strike ) + ( r + stdev**2 / 2 ) * t
93
+ out = out /( stdev * Math.sqrt(t) )
94
+ return out
95
+ end
96
+ def d2
97
+ last = stock.last
98
+ r = self.class.rate_annual
99
+
100
+ out = d1 - stdev * Math.sqrt( t )
101
+ return out
102
+ end
103
+ def t
104
+ # t = 1.0 / 365 * Date.today.business_days_until( expires_on )
105
+ t = 1.0 / 365 * (expires_on - Date.today).to_i
106
+ end
107
+ def stdev
108
+ recompute = nil
109
+ stock.stdev( recompute: recompute )
110
+ end
111
+ def call_price
112
+ last = stock.last
113
+ r = self.class.rate_annual
114
+
115
+ out = N.cdf( d1 ) * last - N.cdf( d2 ) * strike * Math::E**( -1 * r * t )
116
+ return out
117
+ end
118
+
119
+ def put_price
120
+ last = stock.last
121
+ r = self.class.rate_annual
122
+
123
+ out = N.cdf(-d2) * strike * exp(-r*t) - N.cdf(-d1) * last
124
+ return out
125
+ end
126
+
127
+
128
+ def self.rate_annual
129
+ 0.05
130
+ end
131
+
132
+ =begin
133
+ # test
134
+
135
+ inn = 100
136
+ n.times { inn = inn*(1.0+out) }
137
+ inn
138
+
139
+ =end
140
+ def self.rate_daily
141
+ n = 250.0 # days
142
+ # n = 12 # months
143
+
144
+ out = (1.0+self.rate_annual)**(1.0/n) - 1.0
145
+ puts! out, 'rate_daily'
146
+ return out
147
+ end
148
+
149
+ end