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.
- {finalytics-0.3.1 → finalytics-0.4.1}/PKG-INFO +18 -35
- {finalytics-0.3.1 → finalytics-0.4.1}/README.md +19 -94
- {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/Cargo.toml +5 -7
- {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/analytics/fundamentals.rs +21 -21
- {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/analytics/performance.rs +54 -19
- {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/analytics/sentiment.rs +6 -4
- {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/analytics/statistics.rs +1 -1
- {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/analytics/stochastics.rs +2 -2
- {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/charts/portfolio.rs +51 -25
- {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/charts/ticker.rs +68 -38
- finalytics-0.4.1/finalytics/src/data/config.rs +393 -0
- finalytics-0.4.1/finalytics/src/data/mod.rs +2 -0
- {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/data/ticker.rs +118 -264
- finalytics-0.4.1/finalytics/src/lib.rs +79 -0
- {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/models/portfolio.rs +8 -8
- {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/models/ticker.rs +24 -25
- {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/utils/web_utils.rs +16 -3
- {finalytics-0.3.1 → finalytics-0.4.1}/pyproject.toml +1 -1
- {finalytics-0.3.1 → finalytics-0.4.1}/python/Cargo.toml +1 -1
- finalytics-0.4.1/python/README.md +58 -0
- {finalytics-0.3.1 → finalytics-0.4.1}/python/conf.py +2 -2
- finalytics-0.4.1/python/index.rst +198 -0
- {finalytics-0.3.1 → finalytics-0.4.1}/python/src/ffi.rs +18 -15
- {finalytics-0.3.1 → finalytics-0.4.1}/python/src/lib.rs +0 -3
- {finalytics-0.3.1 → finalytics-0.4.1}/python/src/portfolio.rs +41 -48
- {finalytics-0.3.1 → finalytics-0.4.1}/python/src/ticker.rs +104 -270
- finalytics-0.4.1/python/test.py +36 -0
- finalytics-0.3.1/finalytics/src/data/db.rs +0 -257
- finalytics-0.3.1/finalytics/src/data/keys.rs +0 -479
- finalytics-0.3.1/finalytics/src/data/mod.rs +0 -3
- finalytics-0.3.1/finalytics/src/data/sqlite/symbols.db +0 -0
- finalytics-0.3.1/finalytics/src/data/symbols.rs +0 -170
- finalytics-0.3.1/finalytics/src/lib.rs +0 -57
- finalytics-0.3.1/python/README.md +0 -77
- finalytics-0.3.1/python/index.rst +0 -380
- finalytics-0.3.1/python/src/symbols.rs +0 -52
- finalytics-0.3.1/python/test.py +0 -40
- {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/analytics/mod.rs +0 -0
- {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/analytics/optimization.rs +0 -0
- {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/analytics/technicals.rs +0 -0
- {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/charts/mod.rs +0 -0
- {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/models/mod.rs +0 -0
- {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/utils/chart_utils.rs +0 -0
- {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/utils/date_utils.rs +0 -0
- {finalytics-0.3.1 → finalytics-0.4.1}/finalytics/src/utils/mod.rs +0 -0
- {finalytics-0.3.1 → finalytics-0.4.1}/python/Cargo.lock +0 -0
- {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
|
+
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:
|
|
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
|

|
|
20
22
|

|
|
21
23
|

|
|
22
|
-
[](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
|
-
|
|
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
|
|
|
@@ -14,7 +14,7 @@ Add the following to your `Cargo.toml` file:
|
|
|
14
14
|
|
|
15
15
|
```toml
|
|
16
16
|
[dependencies]
|
|
17
|
-
finalytics = {version = "0.
|
|
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()
|
|
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
|
}
|
|
@@ -181,7 +113,6 @@ The Finalytics Telegram Bot allows you to perform security analysis, portfolio o
|
|
|
181
113
|

|
|
182
114
|

|
|
183
115
|

|
|
184
|
-
[](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
|
-
|
|
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.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.
|
|
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
|
-
"
|
|
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,8 @@
|
|
|
1
1
|
use polars::prelude::*;
|
|
2
2
|
use std::error::Error;
|
|
3
|
+
use futures::future::join_all;
|
|
3
4
|
|
|
4
|
-
use crate::data::
|
|
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
|
|
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
|
|
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.
|
|
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
|
|
135
|
-
|
|
136
|
-
|
|
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
|
-
|
|
144
|
-
let
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
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:
|
|
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::
|
|
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,
|