finalytics 0.3.1__tar.gz → 0.4.1__tar.gz

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 (47) hide show
  1. {finalytics-0.3.1 → finalytics-0.4.1}/PKG-INFO +18 -35
  2. {finalytics-0.3.1 → finalytics-0.4.1}/README.md +19 -94
  3. {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/Cargo.toml +5 -7
  4. {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/analytics/fundamentals.rs +21 -21
  5. {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/analytics/performance.rs +54 -19
  6. {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/analytics/sentiment.rs +6 -4
  7. {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/analytics/statistics.rs +1 -1
  8. {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/analytics/stochastics.rs +2 -2
  9. {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/charts/portfolio.rs +51 -25
  10. {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/charts/ticker.rs +68 -38
  11. finalytics-0.4.1/finalytics/src/data/config.rs +393 -0
  12. finalytics-0.4.1/finalytics/src/data/mod.rs +2 -0
  13. {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/data/ticker.rs +118 -264
  14. finalytics-0.4.1/finalytics/src/lib.rs +79 -0
  15. {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/models/portfolio.rs +8 -8
  16. {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/models/ticker.rs +24 -25
  17. {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/utils/web_utils.rs +16 -3
  18. {finalytics-0.3.1 → finalytics-0.4.1}/pyproject.toml +1 -1
  19. {finalytics-0.3.1 → finalytics-0.4.1}/python/Cargo.toml +1 -1
  20. finalytics-0.4.1/python/README.md +58 -0
  21. {finalytics-0.3.1 → finalytics-0.4.1}/python/conf.py +2 -2
  22. finalytics-0.4.1/python/index.rst +198 -0
  23. {finalytics-0.3.1 → finalytics-0.4.1}/python/src/ffi.rs +18 -15
  24. {finalytics-0.3.1 → finalytics-0.4.1}/python/src/lib.rs +0 -3
  25. {finalytics-0.3.1 → finalytics-0.4.1}/python/src/portfolio.rs +41 -48
  26. {finalytics-0.3.1 → finalytics-0.4.1}/python/src/ticker.rs +104 -270
  27. finalytics-0.4.1/python/test.py +36 -0
  28. finalytics-0.3.1/finalytics/src/data/db.rs +0 -257
  29. finalytics-0.3.1/finalytics/src/data/keys.rs +0 -479
  30. finalytics-0.3.1/finalytics/src/data/mod.rs +0 -3
  31. finalytics-0.3.1/finalytics/src/data/sqlite/symbols.db +0 -0
  32. finalytics-0.3.1/finalytics/src/data/symbols.rs +0 -170
  33. finalytics-0.3.1/finalytics/src/lib.rs +0 -57
  34. finalytics-0.3.1/python/README.md +0 -77
  35. finalytics-0.3.1/python/index.rst +0 -380
  36. finalytics-0.3.1/python/src/symbols.rs +0 -52
  37. finalytics-0.3.1/python/test.py +0 -40
  38. {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/analytics/mod.rs +0 -0
  39. {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/analytics/optimization.rs +0 -0
  40. {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/analytics/technicals.rs +0 -0
  41. {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/charts/mod.rs +0 -0
  42. {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/models/mod.rs +0 -0
  43. {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/utils/chart_utils.rs +0 -0
  44. {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/utils/date_utils.rs +0 -0
  45. {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/utils/mod.rs +0 -0
  46. {finalytics-0.3.1 → finalytics-0.4.1}/python/Cargo.lock +0 -0
  47. {finalytics-0.3.1 → finalytics-0.4.1}/python/build.sh +0 -0
@@ -1,12 +1,14 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: finalytics
3
- Version: 0.3.1
3
+ Version: 0.4.1
4
4
  Classifier: Programming Language :: Rust
5
5
  Classifier: Programming Language :: Python :: Implementation :: CPython
6
6
  Classifier: Programming Language :: Python :: Implementation :: PyPy
7
7
  Requires-Dist: polars ==0.19.12
8
8
  Requires-Dist: pyarrow ==14.0.0
9
- Requires-Dist: ipython ==8.18.0
9
+ Requires-Dist: plotly ==5.22.0
10
+ Requires-Dist: notebook >=5.3
11
+ Requires-Dist: ipywidgets >=7.5
10
12
  Requires-Python: >=3.7
11
13
  Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
12
14
 
@@ -19,7 +21,6 @@ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
19
21
  ![Platform](https://img.shields.io/badge/Platform-Windows%20%7C%20Linux%20%7C%20MacOS-brightgreen)
20
22
  ![Python Version](https://img.shields.io/badge/Python-3.7%20%7C%203.8%20%7C%203.9%20%7C%203.10%20%7C%203.11%20%7C%203.12-blue)
21
23
  ![PePy](https://static.pepy.tech/personalized-badge/finalytics?period=total&units=international_system&left_color=black&right_color=blue&left_text=Downloads)
22
- [![CodeFactor](https://www.codefactor.io/repository/github/nnamdi-sys/finalytics-py/badge)](https://www.codefactor.io/repository/github/nnamdi-sys/finalytics-py)
23
24
 
24
25
 
25
26
 
@@ -36,39 +37,20 @@ pip install finalytics
36
37
  View Library documentation on readthedocs [here](https://finalytics.readthedocs.io/en/latest/)
37
38
 
38
39
 
39
- ### Symbol Search
40
-
41
- ```python
42
- from finalytics import get_symbols
43
-
44
- print(get_symbols(query="Apple", asset_class="Equity"))
45
- print(get_symbols(query="Bitcoin", asset_class="Crypto"))
46
- print(get_symbols(query="S&P 500", asset_class="Index"))
47
- print(get_symbols(query="EURUSD", asset_class="Currency"))
48
- print(get_symbols(query="SPY", asset_class="ETF"))
49
- ```
50
-
51
40
  ### Security Analysis
52
41
 
53
42
  ```python
54
43
  from finalytics import Ticker
55
44
 
56
- ticker = Ticker(symbol="AAPL")
57
- print(ticker.get_current_price())
58
- print(ticker.get_summary_stats())
59
- print(ticker.get_price_history(start="2023-01-01", end="2023-10-31", interval="1d"))
60
- print(ticker.get_options_chain())
61
- print(ticker.get_news(compute_sentiment=True))
62
- print(ticker.get_income_statement())
63
- print(ticker.get_balance_sheet())
64
- print(ticker.get_cashflow_statement())
65
- print(ticker.get_financial_ratios())
66
- print(ticker.compute_performance_stats(start="2023-01-01", end="2023-10-31", interval="1d", benchmark="^GSPC",
67
- confidence_level=0.95, risk_free_rate=0.02))
68
- ticker.display_performance_chart(start="2023-01-01", end="2023-10-31", interval="1d", benchmark="^GSPC",
69
- confidence_level=0.95, risk_free_rate=0.02, display_format="notebook")
70
- ticker.display_candlestick_chart(start="2023-01-01", end="2023-10-31", interval="1d", display_format="html")
71
- ticker.display_options_chart(risk_free_rate=0.02, chart_type="surface", display_format="png")
45
+ ticker = Ticker(symbol="AAPL",
46
+ start="2023-01-01",
47
+ end="2023-10-31",
48
+ interval="1d",
49
+ confidence_level=0.95,
50
+ risk_free_rate=0.02)
51
+
52
+ print(ticker.performance_stats())
53
+ ticker.performance_chart().show()
72
54
  ```
73
55
 
74
56
  ### Portfolio Optimization
@@ -76,12 +58,13 @@ ticker.display_options_chart(risk_free_rate=0.02, chart_type="surface", display_
76
58
  ```python
77
59
  from finalytics import Portfolio
78
60
 
79
- portfolio = Portfolio(ticker_symbols=["AAPL", "GOOG", "MSFT", "BTC-USD"],
80
- benchmark_symbol="^GSPC", start_date="2020-01-01", end_date="2022-01-01", interval="1d",
81
- confidence_level=0.95, risk_free_rate=0.02, max_iterations=1000,
61
+ portfolio = Portfolio(ticker_symbols=["AAPL", "GOOG", "MSFT", "BTC-USD"],
62
+ benchmark_symbol="^GSPC", start_date="2020-01-01", end_date="2022-01-01", interval="1d",
63
+ confidence_level=0.95, risk_free_rate=0.02, max_iterations=1000,
82
64
  objective_function="max_sharpe")
65
+
83
66
  print(portfolio.get_optimization_results())
84
- portfolio.display_portfolio_charts("performance", "html")
67
+ portfolio.portfolio_chart("performance").show()
85
68
  ```
86
69
 
87
70
 
@@ -14,7 +14,7 @@ Add the following to your `Cargo.toml` file:
14
14
 
15
15
  ```toml
16
16
  [dependencies]
17
- finalytics = {version = "0.4.0", features = ["kaleido"]}
17
+ finalytics = {version = "0.5.0", features = ["kaleido"]}
18
18
  ```
19
19
 
20
20
  Or run the following command:
@@ -38,86 +38,22 @@ use finalytics::prelude::*;
38
38
  async fn main() -> Result<(), Box<dyn Error>> {
39
39
 
40
40
  // Instantiate the Ticker Object
41
- let ticker = TickerBuilder::new().ticker("AAPL")?
41
+ let ticker = TickerBuilder::new()
42
+ .ticker("AAPL")
42
43
  .start_date("2023-01-01")
43
44
  .end_date("2023-02-01")
44
45
  .interval(Interval::OneDay)
45
46
  .benchmark_symbol("^GSPC")
46
47
  .confidence_level(0.95)
47
48
  .risk_free_rate(0.02)
48
- .build()?;
49
-
50
- // Fetch Ticker Data
51
- let quote = ticker.get_quote().await?;
52
- let stats = ticker.get_ticker_stats().await?;
53
- let chart = ticker.get_chart().await?;
54
- let options = ticker.get_options().await?;
55
-
56
- println!("{:?}", quote);
57
- println!("{:?}", stats);
58
- println!("{:?}", chart);
59
- println!("{:?}", options);
60
-
61
- // Fundamental Analysis
62
- let income_statement = ticker.income_statement().await?;
63
- let balance_sheet = ticker.balance_sheet().await?;
64
- let cash_flow = ticker.cashflow_statement().await?;
65
- let financial_ratios = ticker.financial_ratios().await?;
49
+ .build();
50
+
51
+ // Display the Security Analysis Results
66
52
  let performance_stats = ticker.performance_stats().await?;
67
- let volatility_surface = ticker.volatility_surface().await?;
68
-
69
- println!("{:?}", income_statement);
70
- println!("{:?}", balance_sheet);
71
- println!("{:?}", cash_flow);
72
- println!("{:?}", financial_ratios);
73
53
  println!("{:?}", performance_stats);
74
- println!("{:?}", volatility_surface);
75
-
76
- // Technical Analysis
77
- let sma = ticker.sma(50).await?;
78
- let ema = ticker.ema(3).await?;
79
- let macd = ticker.macd(12, 26, 9).await?;
80
- let rsi = ticker.rsi(14).await?;
81
- let fs = ticker.fs(14).await?;
82
- let ss = ticker.ss(7, 3).await?;
83
- let ppo = ticker.ppo(12, 26, 9).await?;
84
- let roc = ticker.roc(1).await?;
85
- let mfi = ticker.mfi(14).await?;
86
- let bb = ticker.bb(20, 2.0).await?;
87
- let sd = ticker.sd(20).await?;
88
- let mad = ticker.mad(20).await?;
89
- let atr = ticker.atr(14).await?;
90
- let max = ticker.max(20).await?;
91
- let min = ticker.min(20).await?;
92
- let obv = ticker.obv().await?;
93
-
94
- println!("SMA:{:?}\nEMA:{:?}\nMACD:{:?}\nRSI:{:?}\nFS:{:?}\nSS:{:?}\nPPO:{:?}\nROC:{:?}\nMFI:{:?}\
95
- \nBB:{:?}\nSD:{:?}\nMAD:{:?}\nATR:{:?}\nMAX:{:?}\nMIN:{:?}\nOBV:{:?}\n",
96
- sma, ema, macd, rsi, fs, ss, ppo, roc, mfi, bb, sd, mad, atr, max, min, obv);
97
-
98
- // News Sentiment Analysis
99
- let news_sentiment = ticker.get_news(true).await?;
100
- println!("{:?}", news_sentiment);
101
-
102
- // Display Ticker Charts
103
- let candlestick_chart = ticker.candlestick_chart().await?;
54
+
104
55
  let performance_chart = ticker.performance_chart().await?;
105
- let volatility_charts = ticker.volatility_charts().await?;
106
- let summary_stats_table = ticker.summary_stats_table().await?;
107
- let performance_stats_table = ticker.performance_stats_table().await?;
108
- let financials_tables = ticker.financials_tables().await?;
109
-
110
- candlestick_chart.show();
111
56
  performance_chart.show();
112
- summary_stats_table.show();
113
- performance_stats_table.show();
114
- volatility_charts["Volatility Surface"].show();
115
- volatility_charts["Volatility Smile"].show();
116
- volatility_charts["Volatility Term Structure"].show();
117
- financials_tables["Income Statement"].show();
118
- financials_tables["Balance Sheet"].show();
119
- financials_tables["Cashflow Statement"].show();
120
- financials_tables["Financial Ratios"].show();
121
57
 
122
58
  Ok(())
123
59
 
@@ -132,6 +68,7 @@ use finalytics::prelude::*;
132
68
 
133
69
  #[tokio::main]
134
70
  async fn main() -> Result<(), Box<dyn Error>> {
71
+
135
72
  // Construct the Portfolio Object
136
73
  let ticker_symbols = Vec::from(["NVDA", "BRK-A", "AAPL", "ZN=F"]);
137
74
  let portfolio = PortfolioBuilder::new().ticker_symbols(ticker_symbols)
@@ -147,12 +84,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
147
84
 
148
85
  // Display Portfolio Optimization Results
149
86
  println!("{:?}", portfolio.performance_stats);
150
-
151
- // Display Portfolio Analytics Charts
152
- portfolio.optimization_chart()?.show();
153
87
  portfolio.performance_chart()?.show();
154
- portfolio.asset_returns_chart()?.show();
155
- portfolio.performance_stats_table()?.show();
156
88
 
157
89
  Ok(())
158
90
  }
@@ -181,7 +113,6 @@ The Finalytics Telegram Bot allows you to perform security analysis, portfolio o
181
113
  ![Platform](https://img.shields.io/badge/Platform-Windows%20%7C%20Linux%20%7C%20MacOS-brightgreen)
182
114
  ![Python Version](https://img.shields.io/badge/Python-3.7%20%7C%203.8%20%7C%203.9%20%7C%203.10%20%7C%203.11%20%7C%203.12-blue)
183
115
  ![PePy](https://static.pepy.tech/personalized-badge/finalytics?period=total&units=international_system&left_color=black&right_color=blue&left_text=Downloads)
184
- [![CodeFactor](https://www.codefactor.io/repository/github/nnamdi-sys/finalytics-py/badge)](https://www.codefactor.io/repository/github/nnamdi-sys/finalytics-py)
185
116
 
186
117
 
187
118
  ## Installation
@@ -200,22 +131,15 @@ View Library documentation on readthedocs [here](https://finalytics.readthedocs.
200
131
  ```python
201
132
  from finalytics import Ticker
202
133
 
203
- ticker = Ticker(symbol="AAPL")
204
- print(ticker.get_current_price())
205
- print(ticker.get_summary_stats())
206
- print(ticker.get_price_history(start="2023-01-01", end="2023-10-31", interval="1d"))
207
- print(ticker.get_options_chain())
208
- print(ticker.get_news(compute_sentiment=True))
209
- print(ticker.get_income_statement())
210
- print(ticker.get_balance_sheet())
211
- print(ticker.get_cashflow_statement())
212
- print(ticker.get_financial_ratios())
213
- print(ticker.compute_performance_stats(start="2023-01-01", end="2023-10-31", interval="1d", benchmark="^GSPC",
214
- confidence_level=0.95, risk_free_rate=0.02))
215
- ticker.display_performance_chart(start="2023-01-01", end="2023-10-31", interval="1d", benchmark="^GSPC",
216
- confidence_level=0.95, risk_free_rate=0.02, display_format="notebook")
217
- ticker.display_candlestick_chart(start="2023-01-01", end="2023-10-31", interval="1d", display_format="html")
218
- ticker.display_options_chart(risk_free_rate=0.02, chart_type="surface", display_format="png")
134
+ ticker = Ticker(symbol="AAPL",
135
+ start="2023-01-01",
136
+ end="2023-10-31",
137
+ interval="1d",
138
+ confidence_level=0.95,
139
+ risk_free_rate=0.02)
140
+
141
+ print(ticker.performance_stats())
142
+ ticker.performance_chart().show()
219
143
  ```
220
144
 
221
145
  ### Portfolio Optimization
@@ -227,8 +151,9 @@ portfolio = Portfolio(ticker_symbols=["AAPL", "GOOG", "MSFT", "BTC-USD"],
227
151
  benchmark_symbol="^GSPC", start_date="2020-01-01", end_date="2022-01-01", interval="1d",
228
152
  confidence_level=0.95, risk_free_rate=0.02, max_iterations=1000,
229
153
  objective_function="max_sharpe")
154
+
230
155
  print(portfolio.get_optimization_results())
231
- portfolio.display_portfolio_charts("performance", "html")
156
+ portfolio.portfolio_chart(chart_type="performance").show()
232
157
  ```
233
158
 
234
159
 
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "finalytics"
3
- version = "0.4.0"
3
+ version = "0.5.1"
4
4
  authors = ["Nnamdi Olisaeloka <nnamdiolisaeloka@gmail.com>"]
5
5
  edition = "2021"
6
6
  homepage = "https://finalytics.rs/"
@@ -24,21 +24,19 @@ chrono = "0.4.37"
24
24
  select = "0.6.0"
25
25
  scraper = "0.19.0"
26
26
  sentiment = "0.1.1"
27
- polars = { version = "0.33.2", default-features = false, features = ["lazy", "dtype-datetime", "rows"] }
27
+ polars = { version = "0.33.2", default-features = false, features = ["lazy", "dtype-datetime", "rows", "fmt_no_tty"] }
28
28
  ta = "0.5.0"
29
29
  num-format = "0.4.4"
30
30
  smartcore = "0.3.2"
31
- statrs = "0.16.0"
31
+ statrs = "0.17.1"
32
32
  rand = "0.8.5"
33
33
  ndarray = "0.15.6"
34
34
  rand_distr = "0.4.3"
35
35
  optimization = "0.2.0"
36
- rusqlite = { version = "0.31.0", features = ["bundled"] }
37
- lazy_static = "1.4.0"
38
- r2d2 = "0.8.10"
39
- r2d2_sqlite = "0.24.0"
40
36
  html-escape = "0.2.13"
41
37
  plotly = { version = "0.8.4", package = "plotly-fork"}
38
+ once_cell = "1.19.0"
39
+ futures = "0.3.30"
42
40
 
43
41
  [features]
44
42
  kaleido = ["plotly/kaleido"]
@@ -24,27 +24,27 @@ impl Financials for Ticker {
24
24
 
25
25
  let df = df!(
26
26
  "date" => *&income_statement.column("asOfDate")?,
27
- "gross_profit_margin" => *&income_statement.column("GrossProfit")? / *&income_statement.column("TotalRevenue")?,
28
- "operating_profit_margin" => *&income_statement.column("EBIT")? / *&income_statement.column("TotalRevenue")?,
29
- "net_profit_margin" => *&income_statement.column("NetIncome")? / *&income_statement.column("TotalRevenue")?,
30
- "return_on_assets" => *&income_statement.column("NetIncome")? / *&balance_sheet.column("TotalAssets")?,
31
- "return_on_equity" => *&income_statement.column("NetIncome")? / *&balance_sheet.column("TotalEquityGrossMinorityInterest")?,
32
- "quick_ratio" => *&balance_sheet.column("CurrentAssets")? / *&balance_sheet.column("CurrentLiabilities")?,
33
- "current_ratio" => *&balance_sheet.column("CurrentAssets")? / *&balance_sheet.column("CurrentLiabilities")?,
34
- "debt_to_equity" => *&balance_sheet.column("TotalLiabilitiesNetMinorityInterest")? / *&balance_sheet.column("TotalEquityGrossMinorityInterest")?,
35
- "debt_to_assets" => *&balance_sheet.column("TotalLiabilitiesNetMinorityInterest")? / *&balance_sheet.column("TotalAssets")?,
36
- "interest_coverage" => *&income_statement.column("EBIT")? / *&income_statement.column("InterestExpense")?,
37
- "asset_turnover" => *&income_statement.column("TotalRevenue")? / *&balance_sheet.column("TotalAssets")?,
38
- "inventory_turnover" => *&income_statement.column("CostOfRevenue")? / *&balance_sheet.column("Inventory")?,
39
- "days_receivable" => *&balance_sheet.column("AccountsReceivable")? / *&income_statement.column("TotalRevenue")? * 365.0,
40
- "days_inventory" => *&balance_sheet.column("Inventory")? / *&income_statement.column("CostOfRevenue")? * 365.0,
41
- "days_payable" => *&balance_sheet.column("AccountsPayable")? / *&income_statement.column("CostOfRevenue")? * 365.0,
42
- "earnings_per_share" => *&income_statement.column("DilutedEPS")?,
43
- "price_to_earnings" => *&balance_sheet.column("TotalCapitalization")? / *&income_statement.column("NetIncome")?,
44
- "price_to_book" => *&balance_sheet.column("TotalCapitalization")? / *&balance_sheet.column("TotalEquityGrossMinorityInterest")?,
45
- "price_to_sales" => *&balance_sheet.column("TotalCapitalization")? / *&income_statement.column("TotalRevenue")?,
46
- "price_to_cash_flow" => *&balance_sheet.column("TotalCapitalization")? / *&cash_flow.column("OperatingCashFlow")?,
47
- "price_to_free_cash_flow" => *&balance_sheet.column("TotalCapitalization")? / *&cash_flow.column("FreeCashFlow")?,
27
+ "Gross Profit Margin" => *&income_statement.column("GrossProfit")? / *&income_statement.column("TotalRevenue")?,
28
+ "Operating Profit Margin" => *&income_statement.column("EBIT")? / *&income_statement.column("TotalRevenue")?,
29
+ "Net Profit Margin" => *&income_statement.column("NetIncome")? / *&income_statement.column("TotalRevenue")?,
30
+ "Return on Assets" => *&income_statement.column("NetIncome")? / *&balance_sheet.column("TotalAssets")?,
31
+ "Return on Equity" => *&income_statement.column("NetIncome")? / *&balance_sheet.column("TotalEquityGrossMinorityInterest")?,
32
+ "Quick Ratio" => *&balance_sheet.column("CurrentAssets")? / *&balance_sheet.column("CurrentLiabilities")?,
33
+ "Current Ratio" => *&balance_sheet.column("CurrentAssets")? / *&balance_sheet.column("CurrentLiabilities")?,
34
+ "Debt to Equity" => *&balance_sheet.column("TotalLiabilitiesNetMinorityInterest")? / *&balance_sheet.column("TotalEquityGrossMinorityInterest")?,
35
+ "Debt to Assets" => *&balance_sheet.column("TotalLiabilitiesNetMinorityInterest")? / *&balance_sheet.column("TotalAssets")?,
36
+ "Interest Coverage" => *&income_statement.column("EBIT")? / *&income_statement.column("InterestExpense")?,
37
+ "Asset Turnover" => *&income_statement.column("TotalRevenue")? / *&balance_sheet.column("TotalAssets")?,
38
+ "Inventory Turnover" => *&income_statement.column("CostOfRevenue")? / *&balance_sheet.column("Inventory")?,
39
+ "Days Receivable" => *&balance_sheet.column("AccountsReceivable")? / *&income_statement.column("TotalRevenue")? * 365.0,
40
+ "Days Inventory" => *&balance_sheet.column("Inventory")? / *&income_statement.column("CostOfRevenue")? * 365.0,
41
+ "Days Payable" => *&balance_sheet.column("AccountsPayable")? / *&income_statement.column("CostOfRevenue")? * 365.0,
42
+ "Earnings per Share" => *&income_statement.column("DilutedEPS")?,
43
+ "Price to Earnings" => *&balance_sheet.column("TotalCapitalization")? / *&income_statement.column("NetIncome")?,
44
+ "Price to Book" => *&balance_sheet.column("TotalCapitalization")? / *&balance_sheet.column("TotalEquityGrossMinorityInterest")?,
45
+ "Price to Sales" => *&balance_sheet.column("TotalCapitalization")? / *&income_statement.column("TotalRevenue")?,
46
+ "Price to Cashflow" => *&balance_sheet.column("TotalCapitalization")? / *&cash_flow.column("OperatingCashFlow")?,
47
+ "Price to Free Cashflow" => *&balance_sheet.column("TotalCapitalization")? / *&cash_flow.column("FreeCashFlow")?,
48
48
  )?;
49
49
 
50
50
  // Transpose the DataFrame
@@ -1,7 +1,8 @@
1
1
  use polars::prelude::*;
2
2
  use std::error::Error;
3
+ use futures::future::join_all;
3
4
 
4
- use crate::data::ticker::Interval;
5
+ use crate::data::config::Interval;
5
6
  use crate::models::ticker::{Ticker, TickerBuilder};
6
7
  use crate::analytics::technicals::TechnicalIndicators;
7
8
  use crate::analytics::optimization::{ObjectiveFunction, portfolio_optimization};
@@ -38,15 +39,15 @@ impl TickerPerformance for Ticker {
38
39
  let security_prices = security_df.column("close")?.clone();
39
40
  let security_returns = DataFrame::new(vec![
40
41
  security_df.column("timestamp")?.clone(),
41
- security_df.column("roc-1")?.clone().with_name(&*self.ticker.symbol)
42
+ security_df.column("roc-1")?.clone().with_name(&*self.ticker)
42
43
  ])?;
43
- let benchmark_ticker = TickerBuilder::new().ticker(&self.benchmark_symbol.clone())?
44
+ let benchmark_ticker = TickerBuilder::new().ticker(&self.benchmark_symbol.clone())
44
45
  .start_date(&self.start_date.clone())
45
46
  .end_date(&self.end_date.clone())
46
47
  .interval(self.interval.clone())
47
48
  .confidence_level(self.confidence_level)
48
49
  .risk_free_rate(self.risk_free_rate)
49
- .build()?;
50
+ .build();
50
51
  let benchmark_returns = benchmark_ticker.roc(1).await?;
51
52
  let benchmark_returns = benchmark_returns.join(
52
53
  &security_returns,
@@ -58,12 +59,12 @@ impl TickerPerformance for Ticker {
58
59
  let benchmark_returns = benchmark_returns.fill_null(FillNullStrategy::Forward(None))?;
59
60
  let benchmark_returns = benchmark_returns.fill_null(FillNullStrategy::Backward(None))?;
60
61
  let benchmark_returns = benchmark_returns.column("roc-1")?.clone();
61
- let security_returns = security_returns.column(&*self.ticker.symbol)?.clone();
62
+ let security_returns = security_returns.column(&*self.ticker)?.clone();
62
63
  let performance_stats = PerformanceStats::compute_stats(
63
64
  security_returns.clone(), benchmark_returns.clone(),
64
65
  self.risk_free_rate, self.confidence_level, self.interval)?;
65
66
  Ok(TickerPerformanceStats {
66
- ticker_symbol: self.ticker.symbol.clone(),
67
+ ticker_symbol: self.ticker.clone(),
67
68
  benchmark_symbol: self.benchmark_symbol.clone(),
68
69
  start_date: self.start_date.clone(),
69
70
  end_date: self.end_date.clone(),
@@ -131,21 +132,55 @@ impl PortfolioPerformanceStats {
131
132
  max_iterations: u64,
132
133
  objective_function: ObjectiveFunction
133
134
  ) -> Result<PortfolioPerformanceStats, Box<dyn Error>> {
134
- let mut dfs: Vec<DataFrame> = Vec::new();
135
- for ticker_symbol in ticker_symbols.iter() {
136
- let ticker = TickerBuilder::new().ticker(ticker_symbol)?
135
+ let mut futures = Vec::new();
136
+
137
+ for ticker_symbol in ticker_symbols.clone().into_iter() {
138
+ let ticker = TickerBuilder::new().ticker(&ticker_symbol)
137
139
  .start_date(start_date)
138
140
  .end_date(end_date)
139
141
  .interval(interval)
140
142
  .confidence_level(confidence_level)
141
143
  .risk_free_rate(risk_free_rate)
142
- .build()?;
143
- let security_df = ticker.roc(1).await?;
144
- let security_returns_df = DataFrame::new(vec![
145
- security_df.column("timestamp")?.clone(),
146
- security_df.column("roc-1")?.clone().with_name(ticker_symbol)
147
- ])?;
148
- dfs.push(security_returns_df);
144
+ .build();
145
+
146
+ let fut = tokio::task::spawn(async move {
147
+ match ticker.roc(1).await {
148
+ Ok(security_df) => {
149
+ match DataFrame::new(vec![
150
+ security_df.column("timestamp").map_err(|e| e.to_string())?.clone(),
151
+ security_df.column("roc-1").map_err(|e| e.to_string())?.clone().with_name(&ticker_symbol)
152
+ ]) {
153
+ Ok(security_returns_df) => Ok(security_returns_df),
154
+ Err(e) => {
155
+ eprintln!("Error creating DataFrame for {}: {}", ticker_symbol, e);
156
+ Err(format!("Error creating DataFrame for {}: {}", ticker_symbol, e))
157
+ }
158
+ }
159
+ }
160
+ Err(e) => {
161
+ eprintln!("Error Fetching Price Data for {}: {}", ticker_symbol, e);
162
+ Err(format!("Error Fetching Price Data for {}: {}", ticker_symbol, e))
163
+ }
164
+ }
165
+ });
166
+
167
+ futures.push(fut);
168
+ }
169
+
170
+ let results = join_all(futures).await;
171
+ let mut fetched_symbols: Vec<String> = Vec::new();
172
+ let mut dfs: Vec<DataFrame> = Vec::new();
173
+
174
+ for result in results {
175
+ match result {
176
+ Ok(Ok(df)) => {
177
+ let symbol = df.get_column_names()[1].to_string();
178
+ fetched_symbols.push(symbol);
179
+ dfs.push(df);
180
+ }
181
+ Ok(Err(_)) => continue,
182
+ Err(e) => eprintln!("Error in task: {}", e),
183
+ }
149
184
  }
150
185
 
151
186
  let mut portfolio_returns = dfs[0].clone();
@@ -163,13 +198,13 @@ impl PortfolioPerformanceStats {
163
198
  portfolio_returns = portfolio_returns.fill_null(FillNullStrategy::Forward(None))?;
164
199
  portfolio_returns = portfolio_returns.fill_null(FillNullStrategy::Backward(None))?;
165
200
 
166
- let benchmark_ticker = TickerBuilder::new().ticker(benchmark_symbol)?
201
+ let benchmark_ticker = TickerBuilder::new().ticker(benchmark_symbol)
167
202
  .start_date(start_date)
168
203
  .end_date(end_date)
169
204
  .interval(interval)
170
205
  .confidence_level(confidence_level)
171
206
  .risk_free_rate(risk_free_rate)
172
- .build()?;
207
+ .build();
173
208
  let benchmark_returns = benchmark_ticker.roc(1).await?;
174
209
  let benchmark_returns = if portfolio_returns.height() > benchmark_returns.height() {
175
210
  benchmark_returns.join(
@@ -193,7 +228,7 @@ impl PortfolioPerformanceStats {
193
228
  let _ = portfolio_returns.drop_in_place("timestamp")?;
194
229
 
195
230
  Ok(PortfolioPerformanceStats {
196
- ticker_symbols: ticker_symbols.clone(),
231
+ ticker_symbols: fetched_symbols.clone(),
197
232
  benchmark_symbol: benchmark_symbol.to_string(),
198
233
  start_date: start_date.to_string(),
199
234
  end_date: end_date.to_string(),
@@ -5,7 +5,8 @@ use serde::{Deserialize, Serialize};
5
5
  use tokio::time::Duration;
6
6
  use tokio::time::timeout;
7
7
  use crate::models::ticker::Ticker;
8
- use crate::utils::web_utils::scrape_text;
8
+ use crate::data::ticker::TickerData;
9
+ use crate::utils::web_utils::{scrape_text, REQUEST_CLIENT};
9
10
 
10
11
  #[allow(dead_code)]
11
12
  #[derive(Debug, Clone, Serialize, Deserialize)]
@@ -38,10 +39,11 @@ impl NewsSentiment for Ticker {
38
39
  /// * `Vec<News>` Vector of News struct
39
40
  async fn get_news(&self, compute_sentiment: bool) -> Result<Vec<News>, Box<dyn Error>> {
40
41
  let mut result = vec![];
41
- let symbol = if self.ticker.asset_class == "CRYPTOCURRENCY" { self.ticker.symbol.replace("-USD", "") } else { self.ticker.symbol.clone() };
42
- let token = format!("({} OR {})", &symbol, &self.ticker.name);
42
+ let quote = self.get_quote().await?;
43
+ let symbol = if quote.asset_class == "CRYPTOCURRENCY" { self.ticker.replace("-USD", "") } else { self.ticker.clone() };
44
+ let token = format!("({} OR {})", &symbol, &quote.name);
43
45
  let url = format!("https://news.google.com/rss/search?q=allintext:{token}+when:1d");
44
- let response = reqwest::get(&url).await?;
46
+ let response = REQUEST_CLIENT.get(&url).send().await?;
45
47
  let body = response.text().await?;
46
48
  let document = Document::from_read(body.as_bytes()).unwrap();
47
49
 
@@ -8,7 +8,7 @@ use smartcore::linalg::basic::matrix::DenseMatrix;
8
8
  use smartcore::linear::linear_regression::LinearRegression;
9
9
  use statrs::statistics::Statistics;
10
10
  use statrs::distribution::{ContinuousCDF, Normal};
11
- use crate::data::ticker::Interval;
11
+ use crate::data::config::Interval;
12
12
 
13
13
  #[derive(Debug, Clone)]
14
14
  pub struct PerformanceStats {
@@ -272,14 +272,14 @@ impl VolatilitySurface for Ticker {
272
272
 
273
273
  let mut ivols_df = DataFrame::new(vec![Series::new("strike", &strikes)])?;
274
274
  for (i, ttm) in ttms.iter().enumerate() {
275
- let ttm = *ttm as i64;
275
+ let ttm = format!("{:.2}", *ttm);
276
276
  let col = Series::new(&*format!("{}M", ttm), ivols[i].clone());
277
277
  ivols_df.hstack_mut(&[col])?;
278
278
  }
279
279
 
280
280
 
281
281
  Ok(VolatilitySurfaceData{
282
- symbol: self.ticker.symbol.clone(),
282
+ symbol: self.ticker.clone(),
283
283
  risk_free_rate: self.risk_free_rate,
284
284
  ticker_price,
285
285
  expiration_dates,