finalytics 0.3.0__tar.gz → 0.4.0__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 (46) hide show
  1. {finalytics-0.3.0 → finalytics-0.4.0}/PKG-INFO +20 -37
  2. {finalytics-0.3.0 → finalytics-0.4.0}/README.md +20 -95
  3. {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/Cargo.toml +2 -5
  4. {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/analytics/fundamentals.rs +21 -21
  5. {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/analytics/performance.rs +10 -10
  6. {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/analytics/sentiment.rs +6 -4
  7. {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/analytics/statistics.rs +1 -1
  8. {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/analytics/stochastics.rs +2 -2
  9. {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/charts/portfolio.rs +26 -16
  10. {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/charts/ticker.rs +68 -38
  11. finalytics-0.4.0/finalytics/src/data/config.rs +393 -0
  12. finalytics-0.4.0/finalytics/src/data/mod.rs +2 -0
  13. {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/data/ticker.rs +21 -203
  14. {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/lib.rs +13 -12
  15. {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/models/portfolio.rs +5 -5
  16. {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/models/ticker.rs +23 -24
  17. {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/utils/web_utils.rs +15 -1
  18. {finalytics-0.3.0 → finalytics-0.4.0}/pyproject.toml +1 -1
  19. {finalytics-0.3.0 → finalytics-0.4.0}/python/Cargo.toml +1 -1
  20. finalytics-0.4.0/python/README.md +58 -0
  21. {finalytics-0.3.0 → finalytics-0.4.0}/python/conf.py +17 -8
  22. finalytics-0.4.0/python/index.rst +6 -0
  23. {finalytics-0.3.0 → finalytics-0.4.0}/python/src/ffi.rs +18 -15
  24. {finalytics-0.3.0 → finalytics-0.4.0}/python/src/lib.rs +0 -3
  25. {finalytics-0.3.0 → finalytics-0.4.0}/python/src/portfolio.rs +41 -48
  26. {finalytics-0.3.0 → finalytics-0.4.0}/python/src/ticker.rs +104 -270
  27. finalytics-0.4.0/python/test.py +36 -0
  28. finalytics-0.3.0/finalytics/src/data/db.rs +0 -257
  29. finalytics-0.3.0/finalytics/src/data/keys.rs +0 -479
  30. finalytics-0.3.0/finalytics/src/data/mod.rs +0 -3
  31. finalytics-0.3.0/finalytics/src/data/sqlite/symbols.db +0 -0
  32. finalytics-0.3.0/finalytics/src/data/symbols.rs +0 -170
  33. finalytics-0.3.0/python/README.md +0 -77
  34. finalytics-0.3.0/python/index.rst +0 -380
  35. finalytics-0.3.0/python/src/symbols.rs +0 -52
  36. finalytics-0.3.0/python/test.py +0 -40
  37. {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/analytics/mod.rs +0 -0
  38. {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/analytics/optimization.rs +0 -0
  39. {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/analytics/technicals.rs +0 -0
  40. {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/charts/mod.rs +0 -0
  41. {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/models/mod.rs +0 -0
  42. {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/utils/chart_utils.rs +0 -0
  43. {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/utils/date_utils.rs +0 -0
  44. {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/utils/mod.rs +0 -0
  45. {finalytics-0.3.0 → finalytics-0.4.0}/python/Cargo.lock +0 -0
  46. {finalytics-0.3.0 → finalytics-0.4.0}/python/build.sh +0 -0
@@ -1,12 +1,14 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: finalytics
3
- Version: 0.3.0
3
+ Version: 0.4.0
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
 
@@ -15,11 +17,10 @@ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
15
17
  [![pypi](https://img.shields.io/pypi/v/finalytics)](https://pypi.org/project/finalytics/)
16
18
  ![License](https://img.shields.io/crates/l/finalytics)
17
19
  [![Homepage](https://img.shields.io/badge/homepage-finalytics.rs-blue)](https://finalytics.rs/)
18
- [![Documentation Status](https://readthedocs.org/projects/finalytics-py/badge/?version=latest)](https://finalytics-py.readthedocs.io/en/latest/?badge=latest)
20
+ [![Documentation Status](https://readthedocs.org/projects/finalytics/badge/?version=latest)](https://finalytics.readthedocs.io/en/latest/?badge=latest)
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
 
@@ -33,42 +34,23 @@ pip install finalytics
33
34
 
34
35
  ## Documentation
35
36
 
36
- View Library documentation on readthedocs [here](https://finalytics-py.readthedocs.io/en/latest/)
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=False))
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
 
@@ -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
  }
@@ -177,11 +109,10 @@ The Finalytics Telegram Bot allows you to perform security analysis, portfolio o
177
109
  [![pypi](https://img.shields.io/pypi/v/finalytics)](https://pypi.org/project/finalytics/)
178
110
  ![License](https://img.shields.io/crates/l/finalytics)
179
111
  [![Homepage](https://img.shields.io/badge/homepage-finalytics.rs-blue)](https://finalytics.rs/)
180
- [![Documentation Status](https://readthedocs.org/projects/finalytics-py/badge/?version=latest)](https://finalytics-py.readthedocs.io/en/latest/?badge=latest)
112
+ [![Documentation Status](https://readthedocs.org/projects/finalytics/badge/?version=latest)](https://finalytics.readthedocs.io/en/latest/?badge=latest)
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
@@ -192,7 +123,7 @@ pip install finalytics
192
123
 
193
124
  ## Documentation
194
125
 
195
- View Library documentation on readthedocs [here](https://finalytics-py.readthedocs.io/en/latest/)
126
+ View Library documentation on readthedocs [here](https://finalytics.readthedocs.io/en/latest/)
196
127
 
197
128
 
198
129
  ### Security Analysis
@@ -200,22 +131,15 @@ View Library documentation on readthedocs [here](https://finalytics-py.readthedo
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.0"
4
4
  authors = ["Nnamdi Olisaeloka <nnamdiolisaeloka@gmail.com>"]
5
5
  edition = "2021"
6
6
  homepage = "https://finalytics.rs/"
@@ -33,12 +33,9 @@ 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"
42
39
 
43
40
  [features]
44
41
  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,7 @@
1
1
  use polars::prelude::*;
2
2
  use std::error::Error;
3
3
 
4
- use crate::data::ticker::Interval;
4
+ use crate::data::config::Interval;
5
5
  use crate::models::ticker::{Ticker, TickerBuilder};
6
6
  use crate::analytics::technicals::TechnicalIndicators;
7
7
  use crate::analytics::optimization::{ObjectiveFunction, portfolio_optimization};
@@ -38,15 +38,15 @@ impl TickerPerformance for Ticker {
38
38
  let security_prices = security_df.column("close")?.clone();
39
39
  let security_returns = DataFrame::new(vec![
40
40
  security_df.column("timestamp")?.clone(),
41
- security_df.column("roc-1")?.clone().with_name(&*self.ticker.symbol)
41
+ security_df.column("roc-1")?.clone().with_name(&*self.ticker)
42
42
  ])?;
43
- let benchmark_ticker = TickerBuilder::new().ticker(&self.benchmark_symbol.clone())?
43
+ let benchmark_ticker = TickerBuilder::new().ticker(&self.benchmark_symbol.clone())
44
44
  .start_date(&self.start_date.clone())
45
45
  .end_date(&self.end_date.clone())
46
46
  .interval(self.interval.clone())
47
47
  .confidence_level(self.confidence_level)
48
48
  .risk_free_rate(self.risk_free_rate)
49
- .build()?;
49
+ .build();
50
50
  let benchmark_returns = benchmark_ticker.roc(1).await?;
51
51
  let benchmark_returns = benchmark_returns.join(
52
52
  &security_returns,
@@ -58,12 +58,12 @@ impl TickerPerformance for Ticker {
58
58
  let benchmark_returns = benchmark_returns.fill_null(FillNullStrategy::Forward(None))?;
59
59
  let benchmark_returns = benchmark_returns.fill_null(FillNullStrategy::Backward(None))?;
60
60
  let benchmark_returns = benchmark_returns.column("roc-1")?.clone();
61
- let security_returns = security_returns.column(&*self.ticker.symbol)?.clone();
61
+ let security_returns = security_returns.column(&*self.ticker)?.clone();
62
62
  let performance_stats = PerformanceStats::compute_stats(
63
63
  security_returns.clone(), benchmark_returns.clone(),
64
64
  self.risk_free_rate, self.confidence_level, self.interval)?;
65
65
  Ok(TickerPerformanceStats {
66
- ticker_symbol: self.ticker.symbol.clone(),
66
+ ticker_symbol: self.ticker.clone(),
67
67
  benchmark_symbol: self.benchmark_symbol.clone(),
68
68
  start_date: self.start_date.clone(),
69
69
  end_date: self.end_date.clone(),
@@ -133,13 +133,13 @@ impl PortfolioPerformanceStats {
133
133
  ) -> Result<PortfolioPerformanceStats, Box<dyn Error>> {
134
134
  let mut dfs: Vec<DataFrame> = Vec::new();
135
135
  for ticker_symbol in ticker_symbols.iter() {
136
- let ticker = TickerBuilder::new().ticker(ticker_symbol)?
136
+ let ticker = TickerBuilder::new().ticker(ticker_symbol)
137
137
  .start_date(start_date)
138
138
  .end_date(end_date)
139
139
  .interval(interval)
140
140
  .confidence_level(confidence_level)
141
141
  .risk_free_rate(risk_free_rate)
142
- .build()?;
142
+ .build();
143
143
  let security_df = ticker.roc(1).await?;
144
144
  let security_returns_df = DataFrame::new(vec![
145
145
  security_df.column("timestamp")?.clone(),
@@ -163,13 +163,13 @@ impl PortfolioPerformanceStats {
163
163
  portfolio_returns = portfolio_returns.fill_null(FillNullStrategy::Forward(None))?;
164
164
  portfolio_returns = portfolio_returns.fill_null(FillNullStrategy::Backward(None))?;
165
165
 
166
- let benchmark_ticker = TickerBuilder::new().ticker(benchmark_symbol)?
166
+ let benchmark_ticker = TickerBuilder::new().ticker(benchmark_symbol)
167
167
  .start_date(start_date)
168
168
  .end_date(end_date)
169
169
  .interval(interval)
170
170
  .confidence_level(confidence_level)
171
171
  .risk_free_rate(risk_free_rate)
172
- .build()?;
172
+ .build();
173
173
  let benchmark_returns = benchmark_ticker.roc(1).await?;
174
174
  let benchmark_returns = if portfolio_returns.height() > benchmark_returns.height() {
175
175
  benchmark_returns.join(
@@ -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,
@@ -9,19 +9,24 @@ use crate::models::portfolio::Portfolio;
9
9
 
10
10
 
11
11
  pub trait PortfolioCharts {
12
- fn optimization_chart(&self) -> Result<Plot, Box<dyn Error>>;
13
- fn performance_chart(&self) -> Result<Plot, Box<dyn Error>>;
14
- fn asset_returns_chart(&self) -> Result<Plot, Box<dyn Error>>;
15
- fn performance_stats_table(&self) -> Result<Plot, Box<dyn Error>>;
12
+ fn optimization_chart(&self, height: usize, width: usize) -> Result<Plot, Box<dyn Error>>;
13
+ fn performance_chart(&self, height: usize, width: usize) -> Result<Plot, Box<dyn Error>>;
14
+ fn asset_returns_chart(&self, height: usize, width: usize) -> Result<Plot, Box<dyn Error>>;
15
+ fn performance_stats_table(&self, height: usize, width: usize) -> Result<Plot, Box<dyn Error>>;
16
16
  }
17
17
 
18
18
  impl PortfolioCharts for Portfolio {
19
19
  /// Generates Chart of the Portfolio Optimization Results
20
20
  ///
21
+ /// # Arguments
22
+ ///
23
+ /// * `height` - usize - Height of the chart
24
+ /// * `width` - usize - Width of the chart
25
+ ///
21
26
  /// # Returns
22
27
  ///
23
28
  /// * `Plot` Plotly Chart struct
24
- fn optimization_chart(&self) -> Result<Plot, Box<dyn Error>> {
29
+ fn optimization_chart(&self, height: usize, width: usize) -> Result<Plot, Box<dyn Error>> {
25
30
  let days = self.performance_stats.interval.to_days();
26
31
 
27
32
  let ef_returns = self.performance_stats.efficient_frontier.clone().iter()
@@ -61,8 +66,8 @@ impl PortfolioCharts for Portfolio {
61
66
 
62
67
  // Set layout for the plot
63
68
  let layout = Layout::new()
64
- .height(800)
65
- .width(1200)
69
+ .height(height)
70
+ .width(width)
66
71
  .title(Title::from("<span style=\"font-weight:bold; color:darkgreen;\">Portfolio Optimization Chart</span>"))
67
72
  .grid(
68
73
  LayoutGrid::new()
@@ -97,10 +102,15 @@ impl PortfolioCharts for Portfolio {
97
102
 
98
103
  /// Generates Chart of the Portfolio Performance Results
99
104
  ///
105
+ /// # Arguments
106
+ ///
107
+ /// * `height` - usize - Height of the chart
108
+ /// * `width` - usize - Width of the chart
109
+ ///
100
110
  /// # Returns
101
111
  ///
102
112
  /// * `Plot` Plotly Chart struct
103
- fn performance_chart(&self) -> Result<Plot, Box<dyn Error>> {
113
+ fn performance_chart(&self, height: usize, width: usize) -> Result<Plot, Box<dyn Error>> {
104
114
  let dates = generate_dates(&*self.performance_stats.start_date,
105
115
  &*self.performance_stats.end_date, 1);
106
116
 
@@ -146,8 +156,8 @@ impl PortfolioCharts for Portfolio {
146
156
 
147
157
  // Set layout for the plot
148
158
  let layout = Layout::new()
149
- .height(800)
150
- .width(1200)
159
+ .height(height)
160
+ .width(width)
151
161
  .title(Title::from("<span style=\"font-weight:bold; color:darkgreen;\">Portfolio Performance Chart</span>"))
152
162
  .grid(
153
163
  LayoutGrid::new()
@@ -185,7 +195,7 @@ impl PortfolioCharts for Portfolio {
185
195
  /// # Returns
186
196
  ///
187
197
  /// * `Plot` Plotly Chart struct
188
- fn asset_returns_chart(&self) -> Result<Plot, Box<dyn Error>> {
198
+ fn asset_returns_chart(&self, height: usize, width: usize) -> Result<Plot, Box<dyn Error>> {
189
199
  let symbols = self.performance_stats.ticker_symbols.clone();
190
200
  let asset_returns = self.performance_stats.portfolio_returns.clone();
191
201
  let dates = generate_dates(&*self.performance_stats.start_date, &*self.performance_stats.end_date, 1);
@@ -202,8 +212,8 @@ impl PortfolioCharts for Portfolio {
202
212
  }
203
213
 
204
214
  let layout = Layout::new()
205
- .height(800)
206
- .width(1200)
215
+ .height(height)
216
+ .width(width)
207
217
  .title(Title::from("<span style=\"font-weight:bold; color:darkgreen;\">Portfolio Assets Cumulative Returns</span>"))
208
218
  .y_axis(
209
219
  Axis::new()
@@ -220,7 +230,7 @@ impl PortfolioCharts for Portfolio {
220
230
  /// # Returns
221
231
  ///
222
232
  /// * `Plot` Plotly Chart struct
223
- fn performance_stats_table(&self) -> Result<Plot, Box<dyn Error>> {
233
+ fn performance_stats_table(&self, height: usize, width: usize) -> Result<Plot, Box<dyn Error>> {
224
234
  let stats = &self.performance_stats.performance_stats;
225
235
 
226
236
  let fields = vec![
@@ -273,8 +283,8 @@ impl PortfolioCharts for Portfolio {
273
283
  plot.add_trace(trace);
274
284
 
275
285
  let layout = Layout::new()
276
- .height(1000)
277
- .width(1200)
286
+ .height(height)
287
+ .width(width)
278
288
  .title(Title::from("<span style=\"font-weight:bold; color:darkgreen;\"> Portfolio Performance Stats</span>"));
279
289
 
280
290
  plot.set_layout(layout);