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.
- {finalytics-0.3.0 → finalytics-0.4.0}/PKG-INFO +20 -37
- {finalytics-0.3.0 → finalytics-0.4.0}/README.md +20 -95
- {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/Cargo.toml +2 -5
- {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/analytics/fundamentals.rs +21 -21
- {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/analytics/performance.rs +10 -10
- {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/analytics/sentiment.rs +6 -4
- {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/analytics/statistics.rs +1 -1
- {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/analytics/stochastics.rs +2 -2
- {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/charts/portfolio.rs +26 -16
- {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/charts/ticker.rs +68 -38
- finalytics-0.4.0/finalytics/src/data/config.rs +393 -0
- finalytics-0.4.0/finalytics/src/data/mod.rs +2 -0
- {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/data/ticker.rs +21 -203
- {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/lib.rs +13 -12
- {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/models/portfolio.rs +5 -5
- {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/models/ticker.rs +23 -24
- {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/utils/web_utils.rs +15 -1
- {finalytics-0.3.0 → finalytics-0.4.0}/pyproject.toml +1 -1
- {finalytics-0.3.0 → finalytics-0.4.0}/python/Cargo.toml +1 -1
- finalytics-0.4.0/python/README.md +58 -0
- {finalytics-0.3.0 → finalytics-0.4.0}/python/conf.py +17 -8
- finalytics-0.4.0/python/index.rst +6 -0
- {finalytics-0.3.0 → finalytics-0.4.0}/python/src/ffi.rs +18 -15
- {finalytics-0.3.0 → finalytics-0.4.0}/python/src/lib.rs +0 -3
- {finalytics-0.3.0 → finalytics-0.4.0}/python/src/portfolio.rs +41 -48
- {finalytics-0.3.0 → finalytics-0.4.0}/python/src/ticker.rs +104 -270
- finalytics-0.4.0/python/test.py +36 -0
- finalytics-0.3.0/finalytics/src/data/db.rs +0 -257
- finalytics-0.3.0/finalytics/src/data/keys.rs +0 -479
- finalytics-0.3.0/finalytics/src/data/mod.rs +0 -3
- finalytics-0.3.0/finalytics/src/data/sqlite/symbols.db +0 -0
- finalytics-0.3.0/finalytics/src/data/symbols.rs +0 -170
- finalytics-0.3.0/python/README.md +0 -77
- finalytics-0.3.0/python/index.rst +0 -380
- finalytics-0.3.0/python/src/symbols.rs +0 -52
- finalytics-0.3.0/python/test.py +0 -40
- {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/analytics/mod.rs +0 -0
- {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/analytics/optimization.rs +0 -0
- {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/analytics/technicals.rs +0 -0
- {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/charts/mod.rs +0 -0
- {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/models/mod.rs +0 -0
- {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/utils/chart_utils.rs +0 -0
- {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/utils/date_utils.rs +0 -0
- {finalytics-0.3.0 → finalytics-0.4.0}/finalytics/src/utils/mod.rs +0 -0
- {finalytics-0.3.0 → finalytics-0.4.0}/python/Cargo.lock +0 -0
- {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
|
+
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:
|
|
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
|
[](https://pypi.org/project/finalytics/)
|
|
16
18
|

|
|
17
19
|
[](https://finalytics.rs/)
|
|
18
|
-
[](https://finalytics.readthedocs.io/en/latest/?badge=latest)
|
|
19
21
|

|
|
20
22
|

|
|
21
23
|

|
|
22
|
-
[](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
|
|
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
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
print(ticker.
|
|
64
|
-
|
|
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.
|
|
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()
|
|
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
|
-
//
|
|
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
|
-
|
|
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
|
[](https://pypi.org/project/finalytics/)
|
|
178
110
|

|
|
179
111
|
[](https://finalytics.rs/)
|
|
180
|
-
[](https://finalytics.readthedocs.io/en/latest/?badge=latest)
|
|
181
113
|

|
|
182
114
|

|
|
183
115
|

|
|
184
|
-
[](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
|
|
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
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
print(ticker.
|
|
211
|
-
|
|
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.
|
|
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.
|
|
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
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
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::
|
|
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
|
|
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
|
|
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.
|
|
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::
|
|
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
|
|
42
|
-
let
|
|
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, "e.name);
|
|
43
45
|
let url = format!("https://news.google.com/rss/search?q=allintext:{token}+when:1d");
|
|
44
|
-
let response =
|
|
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::
|
|
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
|
|
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.
|
|
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(
|
|
65
|
-
.width(
|
|
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(
|
|
150
|
-
.width(
|
|
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(
|
|
206
|
-
.width(
|
|
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(
|
|
277
|
-
.width(
|
|
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);
|