iron_warbler 2.0.7.19 → 2.0.7.21

Sign up to get free protection for your applications and to get access to all the features.
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