iron_warbler 2.0.7.19 → 2.0.7.21

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 (63) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascript/iron_warbler/application.js +2 -0
  3. data/app/assets/javascript/iron_warbler/gameui.js +9 -0
  4. data/app/assets/stylesheets/iron_warbler/application.css +13 -3
  5. data/app/assets/stylesheets/iron_warbler/positions.scss +24 -5
  6. data/app/assets/stylesheets/iron_warbler/purses_gameui.scss +214 -0
  7. data/app/assets/stylesheets/iron_warbler/purses_gameui.scss-bk +112 -0
  8. data/app/assets/stylesheets/iron_warbler/utils.scss +81 -0
  9. data/app/controllers/iro/api/stocks_controller.rb +87 -0
  10. data/app/controllers/iro/api_controller.rb +19 -0
  11. data/app/controllers/iro/positions_controller.rb +35 -4
  12. data/app/controllers/iro/purses_controller.rb +11 -4
  13. data/app/controllers/iro/strategies_controller.rb +7 -7
  14. data/app/helpers/iro/application_helper.rb +5 -2
  15. data/app/jobs/tda_job.rb +14 -0
  16. data/app/models/iro/datapoint.rb +48 -8
  17. data/app/models/iro/position.rb +55 -14
  18. data/app/models/iro/price_item.rb +51 -1
  19. data/app/models/iro/purse.rb +4 -0
  20. data/app/models/iro/stock.rb +5 -2
  21. data/app/models/iro/strategy.rb +84 -10
  22. data/app/models/iro/trash/position_covered_call.rb +4 -0
  23. data/app/models/iro/trash/position_debit_spread.rb +251 -0
  24. data/app/models/tda/option.rb +7 -7
  25. data/app/views/iro/_main_header.haml +18 -17
  26. data/app/views/iro/api/stocks/show.jbuilder +11 -0
  27. data/app/views/iro/positions/_form.haml +11 -38
  28. data/app/views/iro/positions/_formpart_4data.haml +46 -0
  29. data/app/views/iro/positions/_gameui_covered_call.haml +44 -0
  30. data/app/views/iro/positions/_gameui_covered_call.haml-bk +59 -0
  31. data/app/views/iro/positions/_gameui_long_debit_call_spread.haml +37 -0
  32. data/app/views/iro/positions/_gameui_short_debit_put_spread.haml +39 -0
  33. data/app/views/iro/positions/_header.haml +6 -0
  34. data/app/views/iro/positions/_header_covered_call.haml +6 -0
  35. data/app/views/iro/positions/_header_long_debit_call_spread.haml +14 -0
  36. data/app/views/iro/positions/_header_short_debit_put_spread.haml +1 -0
  37. data/app/views/iro/positions/_table.haml +120 -123
  38. data/app/views/iro/positions/roll.haml +83 -0
  39. data/app/views/iro/positions/trash/_header_short_debit_put_spread.haml +9 -0
  40. data/app/views/iro/purses/_form.haml +1 -0
  41. data/app/views/iro/purses/_form_extra_fields.haml +14 -0
  42. data/app/views/iro/purses/_header.haml +22 -0
  43. data/app/views/iro/purses/gameui.haml +19 -0
  44. data/app/views/iro/purses/gameui.haml-bk +44 -0
  45. data/app/views/iro/purses/gameui.haml-bk2 +89 -0
  46. data/app/views/iro/purses/show.haml +1 -7
  47. data/app/views/iro/stocks/_grid_is_long.haml +16 -0
  48. data/app/views/iro/stocks/_grid_is_short.haml +16 -0
  49. data/app/views/iro/strategies/_form.haml +12 -5
  50. data/app/views/iro/strategies/_show.haml +3 -2
  51. data/app/views/iro/strategies/_table.haml +16 -10
  52. data/app/views/iro/strategies/index.haml +8 -0
  53. data/app/views/layouts/iro/application.haml +1 -1
  54. data/config/routes.rb +15 -1
  55. data/lib/iro/engine.rb +2 -0
  56. data/lib/tasks/db_tasks.rake +9 -3
  57. metadata +31 -8
  58. data/app/assets/stylesheets/iron_warbler/alerts.css +0 -8
  59. data/app/assets/stylesheets/iron_warbler/datapoints.css +0 -0
  60. data/app/assets/stylesheets/iron_warbler/profiles.css +0 -4
  61. data/app/assets/stylesheets/iron_warbler/strategies.scss +0 -0
  62. data/app/assets/stylesheets/iron_warbler/utils.css +0 -44
  63. data/app/jobs/iro/application_job.rb-trash +0 -4
@@ -3,11 +3,6 @@ class Iro::StrategiesController < Iro::ApplicationController
3
3
 
4
4
  before_action :set_lists
5
5
 
6
- def new
7
- @strategy = Iro::Strategy.new
8
- authorize! :new, @posision
9
- end
10
-
11
6
  def create
12
7
  @strategy = Iro::Strategy.new params[:strategy].permit!
13
8
  authorize! :create, @strategy
@@ -37,7 +32,12 @@ class Iro::StrategiesController < Iro::ApplicationController
37
32
  def index
38
33
  authorize! :index, Iro::Strategy
39
34
  @strategies = Iro::Strategy.all
40
- render '_table'
35
+ # render '_table'
36
+ end
37
+
38
+ def new
39
+ @strategy = Iro::Strategy.new
40
+ authorize! :new, @posision
41
41
  end
42
42
 
43
43
  def update
@@ -60,7 +60,7 @@ class Iro::StrategiesController < Iro::ApplicationController
60
60
 
61
61
  def set_lists
62
62
  @strategies_list = Iro::Strategy.list
63
- @tickers_list = Iro::Stock.tickers_list
63
+ @tickers_list = Iro::Stock.list
64
64
  end
65
65
 
66
66
  end
@@ -1,4 +1,7 @@
1
- module Iro
2
- module ApplicationHelper
1
+ module Iro::ApplicationHelper
2
+
3
+ def pp_delta delta
4
+ '%.2f' % delta rescue '-'
3
5
  end
6
+
4
7
  end
@@ -0,0 +1,14 @@
1
+
2
+ # require 'net/scp'
3
+ # require 'open3'
4
+ require 'sidekiq'
5
+
6
+ class Iro::TdaJob
7
+ include Sidekiq::Job
8
+ sidekiq_options queue: 'iro_wor_rb'
9
+
10
+ def perform
11
+
12
+ end
13
+
14
+ end
@@ -5,15 +5,34 @@ class Iro::Datapoint
5
5
  include Mongoid::Timestamps
6
6
  store_in collection: 'iro_datapoints'
7
7
 
8
- field :date
8
+ field :kind ## PUT, CALL, STOCK, CURRENCY, CRYPTO
9
+ validates :kind, presence: true
10
+ index({ kind: -1 })
11
+
12
+ field :symbol ## ticker, but use 'symbol' ONLY
13
+
14
+ field :date, type: Date ## @obsolete, use quote_at
9
15
  index({ kind: -1, date: -1 })
10
16
 
17
+ field :quote_at, type: DateTime
18
+ index({ kind: -1, quote_at: -1 })
19
+ validates :quote_at, uniqueness: { scope: [ :kind, :symbol ] }
20
+
21
+ field :open, type: Float
22
+ field :high, type: Float
23
+ field :low, type: Float
24
+
11
25
  field :value, type: Float
12
26
  validates :value, presence: true
27
+ def close
28
+ value
29
+ end
30
+ def close= a
31
+ value= a
32
+ end
33
+
34
+ field :volume, type: Integer
13
35
 
14
- field :kind
15
- validates :kind, presence: true
16
- index({ kind: -1 })
17
36
 
18
37
  def self.test_0trash
19
38
  add_fields = { '$addFields': {
@@ -21,10 +40,10 @@ class Iro::Datapoint
21
40
  '$dateToString': { 'format': "%Y-%m-%d", 'date': "$created_at" }
22
41
  }
23
42
  } }
24
- group = { '$group': {
25
- '_id': "$date_string",
26
- 'my_doc': { '$first': "$$ROOT" }
27
- } }
43
+ # group = { '$group': {
44
+ # '_id': "$date_string",
45
+ # 'my_doc': { '$first': "$$ROOT" }
46
+ # } }
28
47
  group = { '$group': {
29
48
  '_id': "$date",
30
49
  'my_doc': { '$first': "$$ROOT" }
@@ -113,4 +132,25 @@ class Iro::Datapoint
113
132
  # puts! outs.to_a, 'result'
114
133
  end
115
134
 
135
+ def self.import_stock symbol:, path:
136
+ csv = CSV.read(path, headers: true)
137
+ csv.each do |row|
138
+ flag = create({
139
+ kind: 'STOCK',
140
+ symbol: symbol,
141
+ date: row['date'],
142
+ quote_at: row['date'],
143
+
144
+ volume: row['volume'],
145
+
146
+ open: row['open'],
147
+ high: row['high'],
148
+ low: row['low'],
149
+ value: row['close'],
150
+ })
151
+ print '.' if flag.persisted?
152
+ end
153
+ puts 'ok'
154
+ end
155
+
116
156
  end
@@ -4,6 +4,8 @@ class Iro::Position
4
4
  include Mongoid::Timestamps
5
5
  store_in collection: 'iro_positions'
6
6
 
7
+ attr_accessor :gain_loss_amount
8
+
7
9
  STATUS_ACTIVE = 'active'
8
10
  STATUS_PROPOSED = 'proposed'
9
11
  STATUSES = [ nil, 'active', 'inactive', 'proposed' ]
@@ -12,34 +14,48 @@ class Iro::Position
12
14
  scope :active, ->{ where( status: 'active' ) }
13
15
 
14
16
  belongs_to :purse, class_name: 'Iro::Purse', inverse_of: :positions
17
+ index({ purse_id: 1, ticker: 1 })
18
+
19
+ belongs_to :stock, class_name: 'Iro::Stock', inverse_of: :positions
20
+ def ticker
21
+ stock&.ticker || '-'
22
+ end
23
+
15
24
  belongs_to :strategy, class_name: 'Iro::Strategy', inverse_of: :positions
16
25
 
17
- field :ticker
18
- validates :ticker, presence: true
19
- index({ purse_id: 1, ticker: 1 })
26
+ # field :ticker
27
+ # validates :ticker, presence: true
20
28
 
21
- KINDS = [ nil, 'covered_call', 'credit_put_spread', 'credit_call_spread' ]
22
- field :kind
29
+ field :outer_strike, type: :float
30
+ # validates :outer_strike, presence: true
23
31
 
24
- field :strike, type: :float
25
- validates :strike, presence: true
32
+ field :inner_strike, type: :float
33
+ validates :inner_strike, presence: true
26
34
 
27
35
  field :expires_on
28
36
  validates :expires_on, presence: true
29
37
 
30
38
  field :quantity, type: :integer
31
39
  validates :quantity, presence: true
40
+ def q; quantity; end
32
41
 
33
42
  field :begin_on
34
- field :begin_price, type: :float
35
- field :begin_delta, type: :float
43
+ field :begin_outer_price, type: :float
44
+ field :begin_outer_delta, type: :float
45
+
46
+ field :begin_inner_price, type: :float
47
+ field :begin_inner_delta, type: :float
36
48
 
37
49
  field :end_on
38
- field :end_price, type: :float
39
- field :end_delta, type: :float
50
+ field :end_outer_price, type: :float
51
+ field :end_outer_delta, type: :float
40
52
 
41
- field :net_amount
42
- field :net_percent
53
+ field :end_inner_price, type: :float
54
+ field :end_inner_delta, type: :float
55
+
56
+ def breakeven
57
+ strategy.breakeven(self)
58
+ end
43
59
 
44
60
  def current_underlying_strike
45
61
  Iro::Stock.find_by( ticker: ticker ).last
@@ -59,6 +75,19 @@ class Iro::Position
59
75
  print '_'
60
76
  end
61
77
 
78
+ def net_percent
79
+ net_amount / max_gain
80
+ end
81
+ def net_amount # each
82
+ strategy.send("net_amount_#{strategy.kind}", self)
83
+ end
84
+ def max_gain # each
85
+ strategy.send("max_gain_#{strategy.kind}", self)
86
+ end
87
+ def max_loss # each
88
+ strategy.send("max_loss_#{strategy.kind}", self)
89
+ end
90
+
62
91
 
63
92
  field :next_delta, type: :float
64
93
  field :next_outcome, type: :float
@@ -67,6 +96,10 @@ class Iro::Position
67
96
  field :next_reasons, type: :array, default: []
68
97
  field :should_rollp, type: :float
69
98
 
99
+ ##
100
+ ## decisions
101
+ ##
102
+
70
103
  def should_roll?
71
104
  puts! 'shold_roll?'
72
105
 
@@ -83,7 +116,7 @@ class Iro::Position
83
116
  if end_delta < strategy.threshold_delta
84
117
  next_reasons.push "delta is lower than threshold"
85
118
  out = 0.91
86
- elsif 1 - end_price/begin_price > strategy.threshold_netp
119
+ elsif 1 - end_outer_price/begin_outer_price > strategy.threshold_netp
87
120
  next_reasons.push "made enough percent profit (dubious)"
88
121
  out = 0.61
89
122
  else
@@ -219,4 +252,12 @@ class Iro::Position
219
252
  return out
220
253
  end
221
254
 
255
+ def to_s
256
+ out = "#{stock} (#{q}) #{expires_on.to_datetime.strftime('%b %d')} #{strategy.kind_short} ["
257
+ if outer_strike
258
+ out = out + "$#{outer_strike}->"
259
+ end
260
+ out = out + "$#{inner_strike}] "
261
+ return out
262
+ end
222
263
  end
@@ -4,6 +4,7 @@ class Iro::PriceItem
4
4
  include Mongoid::Timestamps
5
5
  store_in collection: 'iro_price_items'
6
6
 
7
+ ## PUT, CALL, STOCK
7
8
  field :putCall, type: String
8
9
  field :symbol, type: String
9
10
  field :ticker, type: String
@@ -15,9 +16,9 @@ class Iro::PriceItem
15
16
  field :last, type: Float
16
17
 
17
18
  field :openPrice, type: Float
18
- field :closePrice, type: Float
19
19
  field :lowPrice, type: Float
20
20
  field :highPrice, type: Float
21
+ field :closePrice, type: Float
21
22
 
22
23
  field :quoteTimeInLong, type: Integer
23
24
  field :timestamp, type: Integer
@@ -26,4 +27,53 @@ class Iro::PriceItem
26
27
  field :exchangeName, type: String
27
28
  field :volatility, type: Float
28
29
 
30
+ def self.my_find props={}
31
+ lookup = { '$lookup': {
32
+ 'from': 'iro_price_items',
33
+ 'localField': 'date',
34
+ 'foreignField': 'date',
35
+ 'pipeline': [
36
+ { '$sort': { 'value': -1 } },
37
+ ],
38
+ 'as': 'dates',
39
+ } }
40
+ lookup_merge = { '$replaceRoot': {
41
+ 'newRoot': { '$mergeObjects': [
42
+ { '$arrayElemAt': [ "$dates", 0 ] }, "$$ROOT"
43
+ ] }
44
+ } }
45
+
46
+
47
+ match = { '$match': {
48
+ 'date': {
49
+ '$gte': props[:begin_on],
50
+ '$lte': props[:end_on],
51
+ }
52
+ } }
53
+
54
+ group = { '$group': {
55
+ '_id': "$date",
56
+ 'my_doc': { '$first': "$$ROOT" }
57
+ } }
58
+
59
+ outs = Iro::Date.collection.aggregate([
60
+ match,
61
+
62
+ lookup,
63
+ lookup_merge,
64
+
65
+ group,
66
+ { '$replaceRoot': { 'newRoot': "$my_doc" } },
67
+ # { '$replaceRoot': { 'newRoot': "$my_doc" } },
68
+
69
+
70
+ { '$project': { '_id': 0, 'date': 1, 'value': 1 } },
71
+ { '$sort': { 'date': 1 } },
72
+ ])
73
+
74
+ puts! 'result'
75
+ pp outs.to_a
76
+ # puts! outs.to_a, 'result'
77
+ end
78
+
29
79
  end
@@ -10,6 +10,10 @@ class Iro::Purse
10
10
 
11
11
  has_many :positions, class_name: 'Iro::Position', inverse_of: :purse
12
12
 
13
+ field :unit, type: :integer
14
+ field :height, type: :integer
15
+ field :mark_every_n_usd, type: :float
16
+
13
17
  def to_s
14
18
  slug
15
19
  end
@@ -18,13 +18,16 @@ class Iro::Stock
18
18
 
19
19
  field :last, type: :float
20
20
 
21
-
22
- # has_many :strategies, class_name: 'Iro::Strategy', inverse_of: :stock
21
+ has_many :positions, class_name: 'Iro::Position', inverse_of: :stock
22
+ has_many :strategies, class_name: 'Iro::Strategy', inverse_of: :stock
23
23
 
24
24
  def to_s
25
25
  ticker
26
26
  end
27
27
  def self.list
28
+ [[nil,nil]] + all.map { |sss| [ sss.ticker, sss.id ] }
29
+ end
30
+ def self.tickers_list
28
31
  [[nil,nil]] + all.map { |sss| [ sss.ticker, sss.ticker ] }
29
32
  end
30
33
  end
@@ -7,17 +7,43 @@ class Iro::Strategy
7
7
  field :slug
8
8
  validates :slug, presence: true, uniqueness: true
9
9
 
10
+ LONG = 'is_long'
11
+ SHORT = 'is_short'
12
+ field :long_or_short, type: :string
13
+ validates :long_or_short, presence: true
14
+
15
+ field :description
16
+
10
17
  has_many :positions, class_name: 'Iro::Position', inverse_of: :strategy
11
18
 
12
- ## multiple strategies per ticker
13
- field :ticker
14
- validates :ticker, presence: true
15
- index({ ticker: 1 })
16
- # belongs_to :stock, class_name: 'Iro::Stock', inverse_of: :strategies
19
+ belongs_to :stock, class_name: 'Iro::Stock', inverse_of: :strategies
17
20
 
21
+ KIND_COVERED_CALL = 'covered_call'
22
+ KIND_LONG_DEBIT_CALL_SPREAD = 'long_debit_call_spread'
23
+ KIND_SHORT_DEBIT_PUT_SPREAD = 'long_debit_call_spread'
24
+ KINDS = [ nil,
25
+ KIND_COVERED_CALL,
26
+ KIND_LONG_DEBIT_CALL_SPREAD,
27
+ KIND_SHORT_DEBIT_PUT_SPREAD,
28
+ ]
29
+ field :kind
30
+
31
+ def kind_short
32
+ case kind
33
+ when KIND_COVERED_CALL
34
+ 'cc'
35
+ when KIND_LONG_DEBIT_CALL_SPREAD
36
+ 'long-spread'
37
+ when KIND_SHORT_DEBIT_PUT_SPREAD
38
+ 'short-spread'
39
+ else
40
+ '@TODO-zez'
41
+ end
42
+ end
18
43
 
19
44
  field :buffer_above_water, type: :float
20
- field :next_max_delta, type: :float
45
+ field :next_max_inner_delta, type: :float
46
+ field :next_max_outer_delta, type: :float
21
47
  field :next_min_strike, type: :float
22
48
  field :threshold_delta, type: :float
23
49
  field :threshold_netp, type: :float
@@ -26,13 +52,61 @@ class Iro::Strategy
26
52
  where( ticker: ticker )
27
53
  end
28
54
 
55
+ def breakeven p
56
+ p.inner_strike - p.begin_outer_price + p.begin_inner_price
57
+ end
29
58
 
30
- def to_s
31
- slug
59
+ def breakeven p
60
+ p.inner_strike + p.begin_inner_price
32
61
  end
33
62
 
34
- def self.list
35
- [[nil,nil]] + all.map { |ttt| [ ttt.slug, ttt.id ] }
63
+ def max_gain_covered_call p
64
+ # return p.begin_inner_price
65
+ p.begin_inner_price * 100 - 0.66
66
+ end
67
+ def max_gain_long_debit_call_spread p
68
+ ## 100 * disalloed for gameui
69
+ ( p.inner_strike - p.outer_strike - p.begin_outer_price + p.begin_inner_price ) # - 2*0.66
70
+ end
71
+ def max_gain_short_debit_put_spread p
72
+ ## 100 * disalloed for gameui
73
+ ( p.outer_strike - p.inner_strike - p.begin_outer_price + p.begin_inner_price ) # - 2*0.66
74
+ end
75
+
76
+ def max_loss_covered_call p
77
+ return 'infinity'
78
+ end
79
+ def max_loss_long_debit_call_spread p
80
+ out = 100 * ( p.outer_strike - p.inner_strike )
81
+ end
82
+ def max_loss_short_debit_put_spread p
83
+ out = -100 * ( p.outer_strike - p.inner_strike )
36
84
  end
37
85
 
86
+ def net_amount_covered_call p
87
+ ( p.begin_inner_price - p.end_inner_price ) * 100
88
+ end
89
+ def net_amount_long_debit_call_spread p
90
+ outer = p.end_outer_price - p.begin_outer_price
91
+ inner = p.begin_inner_price - p.end_inner_price
92
+ out = ( outer + inner ) * 100
93
+ end
94
+ alias_method :net_amount_short_debit_put_spread, :net_amount_long_debit_call_spread
95
+
96
+
97
+ def net_amount_long_debit_call_spread p
98
+ outer = p.end_outer_price - p.begin_outer_price
99
+ inner = p.begin_inner_price - p.end_inner_price
100
+ out = ( outer + inner ) * 100
101
+ end
102
+
103
+
104
+
105
+ def to_s
106
+ slug
107
+ end
108
+ def self.list long_or_short = nil
109
+ these = long_or_short ? where( long_or_short: long_or_short ) : all
110
+ [[nil,nil]] + these.map { |ttt| [ ttt.slug, ttt.id ] }
111
+ end
38
112
  end
@@ -0,0 +1,4 @@
1
+
2
+ class Iro::PositionCoveredCall < Iro::Position
3
+
4
+ end