yfinrb 0.1.0 → 0.2.15

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,579 @@
1
+ require 'tulirb'
2
+
3
+ class Yfinrb
4
+ module PriceTechnical
5
+ extend ActiveSupport::Concern
6
+ include ActionView::Helpers::NumberHelper
7
+
8
+
9
+ def ad(df)
10
+ inputs = ['High', 'Low','Adj Close','Volume'].map{|col| Polars::Series.new(df[col]).to_a}
11
+ output = Tulirb.ad(inputs).first
12
+ Polars::Series.new("Accum-Distrib Ln", [nil]*(df.rows.length - output.length)+output)
13
+ end
14
+
15
+
16
+ def adosc(df, short_window: 2, long_window: 5)
17
+ inputs = ['High', 'Low','Adj Close','Volume'].map{|col| Polars::Series.new(df[col]).to_a}
18
+ output = Tulirb.adosc(inputs, short_period: short_window, long_period: long_window).first
19
+ Polars::Series.new("#{short_window}/#{long_window} Accum-Distrib Osc", [nil]*(df.rows.length - output.length)+output)
20
+ end
21
+
22
+
23
+ def adx(df, column: 'Adj Close', window: 5)
24
+ input = Polars::Series.new(df[column]).to_a
25
+ output = Tulirb.adx([input], period: window).first
26
+ Polars::Series.new("#{window}-day Avg Dir Movemt Idx for #{column}", [nil]*(df.rows.length - output.length)+output)
27
+ end
28
+
29
+ alias_method :avg_dir_index, :adx
30
+
31
+ def adxr(df, column: 'Adj Close', window: 5)
32
+ input = Polars::Series.new(df[column]).to_a
33
+ output = Tulirb.adxr([input], period: window).first
34
+ Polars::Series.new("#{window}-day Avg Dir Movemt Rating for #{column}", [nil]*(df.rows.length - output.length)+output) #)
35
+ end
36
+
37
+ alias_method :avg_dir_movement_rating, :adxr
38
+
39
+
40
+ def avg_daily_trading_volume(df, window: 20)
41
+ df.insert_at_idx(0, Polars::Series.new('idx', (1..df.length).to_a))
42
+ df = df.set_sorted('idx', descending: false)
43
+
44
+ adtv = df.group_by_rolling(index_column: 'idx', period: "#{window}i").
45
+ agg([Polars.mean('Volume').alias("ADTV(#{window})")]).to_series(1)
46
+ df = df.drop('idx')
47
+ adtv
48
+ end
49
+
50
+
51
+ def ao(df)
52
+ inputs = ['High', 'Low'].map{|col| Polars::Series.new(df[col]).to_a}
53
+ output = Tulirb.ao(inputs).first
54
+ Polars::Series.new("Accum-Distrib Ln", [nil]*(df.rows.length - output.length)+output) #)
55
+ end
56
+
57
+
58
+ def apo(df, column: 'Adj Close', short_window: 12, long_window: 29)
59
+ input = Polars::Series.new(df[column]).to_a
60
+ output = Tulirb.ao([input], short_period: short_window, long_period: long_window).first
61
+ Polars::Series.new("#{short_window}/#{long_window} Abs Price Osc for #{column}", [nil]*(df.rows.length - output.length)+output) #)
62
+ end
63
+
64
+
65
+ def aroon(df, window: 20)
66
+ inputs = ['High', 'Low'].map{|col| Polars::Series.new(df[col]).to_a}
67
+ output = Tulirb.aroon(inputs, period: window).first
68
+ Polars::Series.new("#{window} Aroon Ind", [nil]*(df.rows.length - output.length)+output) #)
69
+ end
70
+
71
+ def aroonosc(df, window: 20)
72
+ inputs = ['High', 'Low'].map{|col| Polars::Series.new(df[col]).to_a}
73
+ output = Tulirb.aroonosc(inputs, period: window).first
74
+ Polars::Series.new("#{window} Aroon Osc Ind", [nil]*(df.rows.length - output.length)+output) #)
75
+ end
76
+
77
+
78
+ def avg_price(df)
79
+ inputs = ['Open', 'High', 'Low', 'Adj Close'].map{|col| Polars::Series.new(df[col]).to_a}
80
+ output = Tulirb.avgprice(inputs).first
81
+ Polars::Series.new("Avg Price", [nil]*(df.rows.length - output.length)+output) #)
82
+ end
83
+
84
+ alias_method :avgprice, :avg_price
85
+
86
+ def atr(df, window: 20)
87
+ inputs = ['High', 'Low', 'Adj Close'].map{|col| Polars::Series.new(df[col]).to_a}
88
+ output = Tulirb.atr(inputs, period: window).first
89
+ Polars::Series.new("#{window}-day Avg True Range", [nil]*(df.rows.length - output.length)+output)#)
90
+ end
91
+
92
+ alias_method :avg_true_range, :atr
93
+
94
+ def bbands(df, column: 'Adj Close', window: 20, stddev: 1 )
95
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
96
+ output = Tulirb.bbands(inputs, period: window, stddev: stddev).first
97
+ Polars::Series.new("#{window}-day Boll Band for #{column}", [nil]*(df.rows.length - output.length)+output) #)
98
+ end
99
+
100
+
101
+ def bop(df)
102
+ inputs = ['Open', 'High', 'Low', 'Adj Close'].map{|col| Polars::Series.new(df[col]).to_a}
103
+ output = Tulirb.bop(inputs).first
104
+ Polars::Series.new("Bal of Power", [nil]*(df.rows.length - output.length)+output) #)
105
+ end
106
+
107
+
108
+ def cci(df, window: 20)
109
+ inputs = ['High', 'Low', 'Adj Close'].map{|col| Polars::Series.new(df[col]).to_a}
110
+ output = Tulirb.cci(inputs, period: window).first
111
+ Polars::Series.new("#{window}-day Comm Channel Idx", [nil]*(df.rows.length - output.length)+output) #)
112
+ end
113
+
114
+
115
+ def cmo(df, column: 'Adj Close', window: 20)
116
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
117
+ output = Tulirb.cmo(inputs, period: window).first
118
+ Polars::Series.new("#{window}-day Chande Mom Osc for #{column}", [nil]*(df.rows.length - output.length)+output) #)
119
+ end
120
+
121
+
122
+ def cvi(df, window: 20)
123
+ inputs = ['High', 'Low'].map{|col| Polars::Series.new(df[col]).to_a}
124
+ output = Tulirb.cvi(inputs, period: window).first
125
+ Polars::Series.new("#{window}-day Chaikins Volatility", [nil]*(df.rows.length - output.length)+output) #)
126
+ end
127
+
128
+
129
+ def dema(df, column: 'Adj Close', window: 20)
130
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
131
+ output = Tulirb.dema(inputs, period: window).first
132
+ Polars::Series.new("Dbl EMA(#{window})", [nil]*(df.rows.length - output.length)+output) #)
133
+ end
134
+
135
+
136
+ def di(df, window: 20)
137
+ inputs = ['High','Low','Close'].map{|col| Polars::Series.new(df[col]).to_a}
138
+ output = Tulirb.di(inputs, period: window).first
139
+ Polars::Series.new("#{window}-day Dir Idx", [nil]*(df.rows.length - output.length)+output) #)
140
+ end
141
+
142
+
143
+ def dm(df, window: 20)
144
+ inputs = ['High','Low'].map{|col| Polars::Series.new(df[col]).to_a}
145
+ output = Tulirb.dm(inputs, period: window).first
146
+ Polars::Series.new("#{window}-day Dir Movemt", [nil]*(df.rows.length - output.length)+output) #)
147
+ end
148
+
149
+
150
+ def dpo(df, column: 'Adj Close', window: 20)
151
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
152
+ output = Tulirb.dpo(inputs, period: window).first
153
+ Polars::Series.new("#{window}-day Detrend Price Osc of #{column}", [nil]*(df.rows.length - output.length)+output) #)
154
+ end
155
+
156
+
157
+ def dx(df, window: 20)
158
+ inputs = ['High','Low', 'Adj Close'].map{|col| Polars::Series.new(df[col]).to_a}
159
+ output = Tulirb.dx(inputs, period: window).first
160
+ Polars::Series.new("#{window}-day Dir Movemt Idx", [nil]*(df.rows.length - output.length)+output) #)
161
+ end
162
+
163
+
164
+ def ema(df, column: 'Adj Close', window: 5)
165
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
166
+ output = Tulirb.ema(inputs, period: window).first
167
+ Polars::Series.new("EMA(#{window}) for #{column}", [nil]*(df.rows.length - output.length)+output) #)
168
+ end
169
+
170
+
171
+ def emv(df)
172
+ inputs = ['High', 'Low', 'Volume'].map{|col| Polars::Series.new(df[col]).to_a}
173
+ output = Tulirb.emv(inputs).first
174
+ Polars::Series.new("Ease of Mvmt", [nil]*(df.rows.length - output.length)+output) #)
175
+ end
176
+
177
+
178
+ def fisher(df, window: 20)
179
+ inputs = ['High', 'Low'].map{|col| Polars::Series.new(df[col]).to_a}
180
+ output = Tulirb.fisher(inputs, period: window).first
181
+ Polars::Series.new("#{window}-day Fisher Xform", [nil]*(df.rows.length - output.length)+output) #)
182
+ end
183
+
184
+
185
+ def fosc(df, window: 20)
186
+ inputs = ['Adj Close'].map{|col| Polars::Series.new(df[col]).to_a}
187
+ output = Tulirb.fosc(inputs, period: window).first
188
+ Polars::Series.new("Fcast Osc", [nil]*(df.rows.length - output.length)+output) #)
189
+ end
190
+
191
+
192
+ def hma(df, column: 'Adj Close', window: 5)
193
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
194
+ output = Tulirb.ema(inputs, period: window).first
195
+ Polars::Series.new("EMA(#{window}) for #{column}", [nil]*(df.rows.length - output.length)+output) #)
196
+ end
197
+
198
+
199
+ def kama(df, column: 'Adj Close', window: 5)
200
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
201
+ output = Tulirb.kama(inputs, period: window).first
202
+ Polars::Series.new("KAMA(#{window}) for #{column}", [nil]*(df.rows.length - output.length)+output) #)
203
+ end
204
+
205
+
206
+ def kvo(df, short_window: 5, long_window: 20)
207
+ inputs = ['High', 'Low', 'Adj Close', 'Volume'].map{|col| Polars::Series.new(df[col]).to_a}
208
+ output = Tulirb.kvo(inputs, short_period: short_window, long_period: long_window).first
209
+ Polars::Series.new("#{short_window}/#{long_window} Klinger Vol Osc", [nil]*(df.rows.length - output.length)+output) #)
210
+ end
211
+
212
+
213
+ def linreg(df, column: 'Adj Close', window: 20)
214
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
215
+ output = Tulirb.linreg(inputs, period: window).first
216
+ Polars::Series.new("#{window}-day Lin Reg Est for #{column}", [nil]*(df.rows.length - output.length)+output) #)
217
+ end
218
+
219
+
220
+ def linregintercept(df, column: 'Adj Close', window: 20)
221
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
222
+ output = Tulirb.linregintercept(inputs, period: window).first
223
+ Polars::Series.new("#{window}-day Lin Reg Int for #{column}", [nil]*(df.rows.length - output.length)+output) #)
224
+ end
225
+
226
+
227
+ def linregslope(df, column: 'Adj Close', window: 20)
228
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
229
+ output = Tulirb.linregslope(inputs, period: window).first
230
+ Polars::Series.new("#{window}-day Lin Reg Slope for #{column}", [nil]*(df.rows.length - output.length)+output)
231
+ end
232
+
233
+
234
+ def macd(df, column: 'Adj Close', short_window: 12, long_window: 26, signal_window: 9)
235
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
236
+ output = Tulirb.macd(inputs, short_period: short_window, long_period: long_window, signal_period: signal_window).first
237
+ Polars::Series.new("#{short_window}/#{long_window}/#{signal_window} MACD for #{column}", [nil]*(df.rows.length - output.length)+output) #)
238
+ end
239
+
240
+
241
+ def marketfi(df)
242
+ inputs = ['High', 'Low', 'Volume'].map{|col| Polars::Series.new(df[col]).to_a}
243
+ output = Tulirb.marketfi(inputs).first
244
+ Polars::Series.new("Mkt Facilitation Idx", [nil]*(df.rows.length - output.length)+output) #)
245
+ end
246
+
247
+
248
+ def mass(df, window: 20)
249
+ inputs = ['High', 'Low'].map{|col| Polars::Series.new(df[col]).to_a}
250
+ output = Tulirb.mass(inputs, period: window).first
251
+ Polars::Series.new("#{window}-day Mass Idx", [nil]*(df.rows.length - output.length)+output) #)
252
+ end
253
+
254
+
255
+ def max(df, column: 'Adj Close', window: 20)
256
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
257
+ output = Tulirb.max(inputs, period: window).first
258
+ Polars::Series.new("Max of #{column} in #{window}-day pd", [nil]*(df.rows.length - output.length)+output) #)
259
+ end
260
+
261
+
262
+ def md(df, column: 'Adj Close', window: 20)
263
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
264
+ output = Tulirb.md(inputs, period: window).first
265
+ Polars::Series.new("Mean Dev of #{column} in #{window}-day pd", [nil]*(df.rows.length - output.length)+output) #)
266
+ end
267
+
268
+
269
+ def median_price(df)
270
+ inputs = ['High', 'Low'].map{|col| Polars::Series.new(df[col]).to_a}
271
+ output = Tulirb.medprice(inputs).first
272
+ Polars::Series.new("Med Price", [nil]*(df.rows.length - output.length)+output) #)
273
+ end
274
+
275
+ alias_method :medprice, :median_price
276
+
277
+ def mfi(df, window: 20)
278
+ inputs = ['High', 'Low', 'Adj Close'].map{|col| Polars::Series.new(df[col]).to_a}
279
+ output = Tulirb.mfi(inputs, period: window).first
280
+ Polars::Series.new("#{window}-day Money Flow Idx", [nil]*(df.rows.length - output.length)+output) #)
281
+ end
282
+
283
+
284
+ def min(df, column: 'Adj Close', window: 20)
285
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
286
+ output = Tulirb.min(inputs, period: window).first
287
+ Polars::Series.new("Min of #{column} in #{window}-day pd", [nil]*(df.rows.length - output.length)+output) #)
288
+ end
289
+
290
+
291
+ def mom(df, column: 'Adj Close', window: 5)
292
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
293
+ output = Tulirb.mom(inputs, period: window).first
294
+ Polars::Series.new("#{window}-day Momentum of #{column}", [nil]*(df.rows.length - output.length)+output) #)
295
+ end
296
+
297
+ alias_method :momentum, :mom
298
+
299
+ def moving_avgs(df, window: 20)
300
+ df.insert_at_idx(0, Polars::Series.new('idx', (1..df.length).to_a))
301
+ df = df.set_sorted('idx', descending: false)
302
+ s = df.group_by_rolling(index_column: 'idx', period: "#{window}i").agg([Polars.mean('Adj Close').alias("MA(#{window})")]).to_series(1) #)
303
+ df = df.drop('idx')
304
+ s
305
+ end
306
+
307
+ def natr(df, window: 20)
308
+ inputs = ['High', 'Low', 'Adj Close'].map{|col| Polars::Series.new(df[col]).to_a}
309
+ output = Tulirb.natr(inputs, period: window).firs
310
+ Polars::Series.new("#{window}-day Norm Avg True Range", [nil]*(df.rows.length - output.length)+output) #)
311
+ end
312
+
313
+ alias_method :normalized_avg_true_range, :natr
314
+
315
+
316
+ # def norm_momentum(period: '1y')
317
+ # df = history(period: period, interval: "1d")
318
+ # dat = df['Adj Close'].to_a
319
+ # mn = dat.sum.to_f / dat.count.to_f
320
+ # std = dat.map{|d| (d-mn)}.sum.to_f/dat.count.to_f
321
+ # all_times = df['Timestamps'].to_a
322
+ # min_time = all_times.min
323
+
324
+ # WINDOWS.each_with_index do |n, ndex|
325
+ # s = [nil] * all_times.length
326
+ # dat.length.times do |t_ndex|
327
+ # next if t_ndex < n
328
+ # later_row = df[t_ndex]
329
+ # earlier_row = df[t_ndex - n]
330
+ # s[t_ndex] = (later_row['Adj Close'][0]) - (earlier_row['Adj Close'][0])/std
331
+ # end
332
+ # next if s.all?(&:nil?)
333
+ # s = Polars::Series.new("#{n}-day Price Chg", s)
334
+ # df.insert_at_idx(df.columns.length, s)
335
+ # end
336
+
337
+ # min_win = WINDOWS.min
338
+ # df.drop_nulls(subset: ["#{min_win}-day Price Chg"])
339
+ # end
340
+
341
+
342
+
343
+ def nvi(df)
344
+ inputs = ['Adj Close', 'Volume'].map{|col| Polars::Series.new(df[col]).to_a}
345
+ output = Tulirb.nvi(inputs).first
346
+ Polars::Series.new("Neg Vol Idx", [nil]*(df.rows.length - output.length)+output) #)
347
+ end
348
+
349
+
350
+ def obv(df)
351
+ inputs = ['Adj Close', 'Volume'].map{|col| Polars::Series.new(df[col]).to_a}
352
+ output = Tulirb.obv(inputs).first
353
+ Polars::Series.new("On Bal Vol", [nil]*(df.rows.length - output.length)+output) #)
354
+ end
355
+
356
+
357
+ def ppo(df, column: 'Adj Close', short_window: 12, long_window: 26)
358
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
359
+ output = Tulirb.ppo(inputs, short_period: short_window, long_period: long_window).first
360
+ Polars::Series.new("#{short_window}/#{long_window} Pctage Price Osc of #{column}", [nil]*(df.rows.length - output.length)+output) #)
361
+ end
362
+
363
+
364
+ def psar(df, acceleration_factor_step: 0.2, acceleration_factor_maximum: 2)
365
+ inputs = ['High', 'Low'].map{|col| Polars::Series.new(df[col]).to_a}
366
+ output = Tulirb.psar(inputs, acceleration_factor_step, acceleration_factor_maximum).first
367
+ Polars::Series.new("Parabolic SAR w step #{acceleration_factor_step} and max #{acceleration_factor_maximum}", [nil]*(df.rows.length - output.length)+output) #)
368
+ end
369
+
370
+
371
+ def pvi(df)
372
+ inputs = ['Adj Close', 'Volume'].map{|col| Polars::Series.new(df[col]).to_a}
373
+ output = Tulirb.pvi(inputs).first
374
+ Polars::Series.new("Pos Vol Idx", [nil]*(df.rows.length - output.length)+output) #)
375
+ end
376
+
377
+
378
+ def qstick(df, window: 20)
379
+ inputs = ['Open', 'Close'].map{|col| Polars::Series.new(df[col]).to_a}
380
+ output = Tulirb.qstick(inputs, period: window).first
381
+ Polars::Series.new("#{window}-day Qstick", [nil]*(df.rows.length - output.length)+output) #)
382
+ end
383
+
384
+
385
+ def roc(df, column: 'Adj Close', window: 20)
386
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
387
+ output = Tulirb.roc(inputs, period: window).first
388
+ Polars::Series.new("Rate of Chg of #{column}", [nil]*(df.rows.length - output.length)+output) #)
389
+ end
390
+
391
+
392
+ def rocr(df, column: 'Adj Close', window: 20)
393
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
394
+ output = Tulirb.rocr(inputs, period: window).first
395
+ Polars::Series.new("Rate of Chg Ratio of #{column}", [nil]*(df.rows.length - output.length)+output) #)
396
+ end
397
+
398
+ def rsi(df, window: 20)
399
+ return nil if w == 1
400
+ inputs = ['Adj Close'].map{|col| Polars::Series.new(df[col]).to_a}
401
+ output = Tulirb.rsi(inputs, period: window).first
402
+ Polars::Series.new("#{window}-day RSI", [nil]*(df.rows.length - output.length)+output) #)
403
+ end
404
+
405
+ def sma(df, column: 'Adj Close', window: 20)
406
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
407
+ output = Tulirb.sma(inputs, period: window).first
408
+ Polars::Series.new("SMA(#{window}) of #{column}", [nil]*(df.rows.length - output.length)+output) #)
409
+ end
410
+
411
+
412
+ def stddev(df, column: 'Adj Close', window: 20)
413
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
414
+ output = Tulirb.stddev(inputs, period: window).first
415
+ Polars::Series.new("Rolling Stdev(#{window}) of #{column}", [nil]*(df.rows.length - output.length)+output) #)
416
+ end
417
+
418
+
419
+ def stderr(df, column: 'Adj Close', window: 20)
420
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
421
+ output = Tulirb.stderr(inputs, period: window).first
422
+ Polars::Series.new("Rolling Stderr(#{window}) of #{column}", [nil]*(df.rows.length - output.length)+output) #)
423
+ end
424
+
425
+
426
+ def stochrsi(df, column: 'Adj Close', window: 20)
427
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
428
+ output = Tulirb.stochrsi(inputs, period: window).first
429
+ Polars::Series.new("Stochastic RSI(#{window}) of #{column}", [nil]*(df.rows.length - output.length)+output) #)
430
+ end
431
+
432
+
433
+ def sum(df, column: 'Adj Close', window: 20)
434
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
435
+ output = Tulirb.sum(inputs, period: window).first
436
+ Polars::Series.new("Rolling #{window}-day Sum of #{column}", [nil]*(df.rows.length - output.length)+output) #)
437
+ end
438
+
439
+ def tema(df, column: 'Adj Close', window: 20)
440
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
441
+ output = Tulirb.tema(inputs, period: window).first
442
+ Polars::Series.new("TEMA(#{window}) of #{column}", [nil]*(df.rows.length - output.length)+output) #)
443
+ end
444
+
445
+
446
+ def tr(df, column: 'Adj Close')
447
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
448
+ output = Tulirb.tr(inputs).first
449
+ Polars::Series.new("True Range of #{column}", [nil]*(df.rows.length - output.length)+output) #)
450
+ end
451
+
452
+ alias_method :true_range, :tr
453
+
454
+ def trima(df, column: 'Adj Close', window: 20)
455
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
456
+ output = Tulirb.trima(inputs, period: window).first
457
+ Polars::Series.new("Triang MA(#{window}) of #{column}", [nil]*(df.rows.length - output.length)+output) #)
458
+ end
459
+
460
+
461
+ def trix(df, column: 'Adj Close', window: 20)
462
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
463
+ output = Tulirb.trix(inputs, period: window).first
464
+ Polars::Series.new("Trix(#{window}) of #{column}", [nil]*(df.rows.length - output.length)+output) #)
465
+ end
466
+
467
+
468
+ def tsf(df, column: 'Adj Close', window: 20)
469
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
470
+ output = Tulirb.tsf(inputs, period: window).first
471
+ Polars::Series.new("Time-series Fcast(#{window}) of #{window}", [nil]*(df.rows.length - output.length)+output) #)
472
+ end
473
+
474
+
475
+ def typical_price(df)
476
+ inputs = ['High', 'Low', 'Adj Close'].map{|col| Polars::Series.new(df[col]).to_a}
477
+ output = Tulirb.typprice(inputs).first
478
+ Polars::Series.new("Typical Price", [nil]*(df.rows.length - output.length)+output) #)
479
+ end
480
+
481
+ alias_method :typprice, :typical_price
482
+
483
+ def ultosc(df, short_window: 5, medium_window: 12, long_window: 26)
484
+ inputs = ['High', 'Low', 'Adj Close'].map{|col| Polars::Series.new(df[col]).to_a}
485
+ output = Tulirb.ultosc(inputs, short_period: short_window, medium_period: medium_window, long_period: long_window).first
486
+ Polars::Series.new("Ult Osc(#{short_window}, #{medium_window}, #{long_window})", [nil]*(df.rows.length - output.length)+output) #)
487
+ end
488
+
489
+ def weighted_close_price(df)
490
+ inputs = ['High', 'Low', 'Adj Close'].map{|col| Polars::Series.new(df[col]).to_a}
491
+ output = Tulirb.wcprice(inputs).first
492
+ Polars::Series.new("Wtd Close Price", [nil]*(df.rows.length - output.length)+output) #)
493
+ end
494
+
495
+
496
+ def var(df, column: 'Adj Close', window: 20)
497
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
498
+ output = Tulirb.var(inputs, period: window).first
499
+ Polars::Series.new("Var over Per(#{window}) of #{column}", [nil]*(df.rows.length - output.length)+output) #)
500
+ end
501
+
502
+
503
+ def vhf(df, column: 'Adj Close', window: 20)
504
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
505
+ output = Tulirb.vhf(inputs, period: window).first
506
+ Polars::Series.new("VHF(#{window}) of #{column}", [nil]*(df.rows.length - output.length)+output) #)
507
+ end
508
+
509
+
510
+ def vidya(df, column: 'Adj Close', short_window: 5, long_window: 20, alpha: 0.2)
511
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
512
+ output = Tulirb.vidya(inputs, short_period: short_window, long_period: long_window, alpha: alpha).first
513
+ Polars::Series.new("vidya(#{short_window},#{long_window},#{alpha}) of #{column}", [nil]*(df.rows.length - output.length)+output) #)
514
+ end
515
+
516
+
517
+ def volatility(df, column: 'Adj Close', window: 20)
518
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
519
+ output = Tulirb.volatility(inputs, period: window).first
520
+ Polars::Series.new("#{window}-day Volatility of #{column}", [nil]*(df.rows.length - output.length)+output) #)
521
+ end
522
+
523
+
524
+ def vosc(df, column: 'Adj Close', short_window: 5, long_window: 20)
525
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
526
+ output = Tulirb.vosc(inputs, short_period: short_window, long_period: long_window).first
527
+ Polars::Series.new("#{short_window}/#{long_window} Vol Osc of #{column}", [nil]*(df.rows.length - output.length)+output) #)
528
+ end
529
+
530
+ def vol_weighted_moving_avg(df, window: 20)
531
+ inputs = ['Adj Close','Volume'].map{|col| Polars::Series.new(df[col]).to_a}
532
+ output = Tulirb.vwma(inputs, period: window).first
533
+ Polars::Series.new("VWMA(#{window})", [nil]*(df.rows.length - output.length)+output) #)
534
+ end
535
+
536
+ alias_method :vwma, :vol_weighted_moving_avg
537
+
538
+ def wad(df)
539
+ inputs = ['High','Low','Close'].map{|col| Polars::Series.new(df[col]).to_a}
540
+ output = Tulirb.wad(inputs, period: window).first
541
+ Polars::Series.new("Wms Accum/Distrib", [nil]*(df.rows.length - output.length)+output) #)
542
+ end
543
+
544
+
545
+ def wcprice(df)
546
+ inputs = ['High','Low','Close'].map{|col| Polars::Series.new(df[col]).to_a}
547
+ output = Tulirb.stderr(inputs).first
548
+ Polars::Series.new("Wtd Close Price", [nil]*(df.rows.length - output.length)+output) #)
549
+ end
550
+
551
+
552
+ def wilders(df, column: 'Adj Close', window: 20)
553
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
554
+ output = Tulirb.wilders(inputs, period: window).first
555
+ Polars::Series.new("#{window}-day Wilders Smoothing of #{column}", [nil]*(df.rows.length - output.length)+output) #)
556
+ end
557
+
558
+
559
+ def willr(df, window: 20)
560
+ inputs = ['High','Low','Close'].map{|col| Polars::Series.new(df[col]).to_a}
561
+ output = Tulirb.willr(inputs, period: window).first
562
+ Polars::Series.new("#{window}-day Williams %R Ind", [nil]*(df.rows.length - output.length)+output) #)
563
+ end
564
+
565
+
566
+ def wma(df, column: 'Adj Close', window: 5)
567
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
568
+ output = Tulirb.wma(inputs, period: window).first
569
+ Polars::Series.new("WMA(#{window}) of #{column}", [nil]*(df.rows.length - output.length)+output) #)
570
+ end
571
+
572
+
573
+ def zlema(df, column: 'Adj Close', window: 5)
574
+ inputs = [column].map{|col| Polars::Series.new(df[col]).to_a}
575
+ output = Tulirb.zlema(inputs, period: window).first
576
+ Polars::Series.new("ZLEMA(#{window}) of #{column}", [nil]*(df.rows.length - output.length)+output) #)
577
+ end
578
+ end
579
+ end
data/lib/yfinrb/quote.rb CHANGED
@@ -1,5 +1,6 @@
1
+ require 'httparty'
1
2
 
2
- class Yfin
3
+ class Yfinrb
3
4
  module Quote
4
5
  extend ActiveSupport::Concern
5
6
 
@@ -46,7 +47,7 @@ class Yfin
46
47
  result = _fetch(['recommendationTrend']).parsed_response
47
48
  # Rails.logger.info { "#{__FILE__}:#{__LINE__} result = #{result.inspect}" }
48
49
  # if result.nil?
49
- # @recommendations = Utils.empty_df() #Polars::DataFrame()
50
+ # @recommendations = Yfinrb::Utils.empty_df() #Polars::DataFrame()
50
51
  # else
51
52
  begin
52
53
  data = result["quoteSummary"]["result"][0]["recommendationTrend"]["trend"]
@@ -69,7 +70,7 @@ class Yfin
69
70
  # Rails.logger.info { "#{__FILE__}:#{__LINE__} result = #{result.inspect}" }
70
71
 
71
72
  # if result.nil?
72
- # @upgrades_downgrades = Utils.empty_df() #Polars::DataFrame()
73
+ # @upgrades_downgrades = Yfinrb::Utils.empty_df() #Polars::DataFrame()
73
74
  # else
74
75
  begin
75
76
  data = result["quoteSummary"]["result"][0]["upgradeDowngradeHistory"]["history"]
data/lib/yfinrb/ticker.rb CHANGED
@@ -1,10 +1,9 @@
1
-
2
- class Yfin
1
+ class Yfinrb
3
2
  class Ticker
4
3
  ROOT_URL = 'https://finance.yahoo.com'.freeze
5
4
  BASE_URL = 'https://query2.finance.yahoo.com'.freeze
6
5
 
7
- include YfConnection
6
+ include Yfinrb::YfConnection
8
7
 
9
8
  attr_accessor :tz, :proxy, :isin, :timeout
10
9
  attr_reader :error_message, :ticker
@@ -28,17 +27,17 @@ class Yfin
28
27
  @expirations = {}
29
28
  @underlying = {}
30
29
 
31
- @ticker = (Utils.is_isin(ticker.upcase) ? Utils.get_ticker_by_isin(ticker.upcase, nil, @session) : ticker).upcase
30
+ @ticker = (Yfinrb::Utils.is_isin(ticker.upcase) ? Yfinrb::Utils.get_ticker_by_isin(ticker.upcase, nil, @session) : ticker).upcase
32
31
 
33
32
  yfconn_initialize
34
33
  end
35
34
 
36
- include PriceHistory
37
- include Analysis
38
- include Fundamentals
39
- include Holders
40
- include Quote
41
- include Financials
35
+ include Yfinrb::PriceHistory
36
+ include Yfinrb::Analysis
37
+ include Yfinrb::Fundamentals
38
+ include Yfinrb::Holders
39
+ include Yfinrb::Quote
40
+ include Yfinrb::Financials
42
41
 
43
42
  alias_method :symbol, :ticker
44
43
 
@@ -50,13 +49,13 @@ class Yfin
50
49
  # Rails.logger.info { "#{__FILE__}:#{__LINE__} start = #{start.inspect}, fin = #{fin.inspect}" }
51
50
 
52
51
  if start
53
- start_ts = Utils.parse_user_dt(start, tz)
52
+ start_ts = Yfinrb::Utils.parse_user_dt(start, tz)
54
53
  # Rails.logger.info { "#{__FILE__}:#{__LINE__} start_ts = #{start_ts}" }
55
54
  start = Time.at(start_ts).in_time_zone(tz)
56
55
  # Rails.logger.info { "#{__FILE__}:#{__LINE__} start = #{start.inspect}, fin = #{fin.inspect}" }
57
56
  end
58
57
  if fin
59
- end_ts = Utils.parse_user_dt(fin, tz)
58
+ end_ts = Yfinrb::Utils.parse_user_dt(fin, tz)
60
59
  # Rails.logger.info { "#{__FILE__}:#{__LINE__} end_ts = #{end_ts}" }
61
60
  fin = Time.at(end_ts).in_time_zone(tz)
62
61
  # Rails.logger.info { "#{__FILE__}:#{__LINE__} start = #{start.inspect}, fin = #{fin.inspect}" }
@@ -1,6 +1,4 @@
1
- require 'set'
2
-
3
- class Yfin
1
+ class Yfinrb
4
2
  class Tickers
5
3
  def initialize(tickers, session = nil)
6
4
  tickers = tickers.is_a?(Array) ? tickers : tickers.split(',')