Skip to content

Commit a40ee5c

Browse files
committed
feat: support setting the backend engine with environment variable
1 parent 82f306f commit a40ee5c

File tree

4 files changed

+21
-5
lines changed

4 files changed

+21
-5
lines changed

docs/source/engine.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ CPU and GPU runtime.
1010

1111
- [TensorFlow](https://www.tensorflow.org/guide/tf_numpy)
1212

13+
- [PyTorch](https://pytorch.org/)
14+
1315
The backend engine can be switched in the following ways.
1416

1517
## Local
@@ -48,6 +50,17 @@ from fpm_risk_model.engine import set_backend
4850
set_backend("tensorflow")
4951
```
5052

53+
## Environment variable
54+
55+
Set the environment variable `FPM_BACKEND_ENGINE` before starting the process.
56+
57+
For example, to start the IPython with setting the default backend engine to `torch`, launch the
58+
terminal as below
59+
60+
```
61+
FPM_BACKEND_ENGINE=torch ipython
62+
```
63+
5164
## Reference
5265

5366
For further details, please find the following notebook [example](https://colab.research.google.com/github/factorpricingmodel/factor-pricing-model-risk-model/blob/main/examples/notebook/numpy_backend_engine.ipynb).

src/fpm_risk_model/engine.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from contextlib import contextmanager
2+
from os import environ
23
from typing import Any
34

45
_BACKEND_ENGINE = "numpy"
@@ -86,6 +87,7 @@ def __getattribute__(self, __name: str) -> Any:
8687

8788
anp.array = anp.tensor
8889
anp.ndarray = anp.Tensor
90+
anp.newaxis = None
8991
else:
9092
raise ValueError(f"Cannot recognize backend {_BACKEND_ENGINE}")
9193
except ImportError:
@@ -145,5 +147,6 @@ def __getattribute__(self, __name: str) -> Any:
145147
)
146148

147149

150+
set_backend(environ.get("FPM_BACKEND_ENGINE", "numpy"))
148151
numpy = NumpyEngine()
149152
linalg = LinAlgEngine()

src/fpm_risk_model/risk_model.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,9 @@ def _to_numpy(values: Union[ndarray, DataFrame]) -> ndarray:
112112
if values is None:
113113
return values
114114
elif isinstance(values, (DataFrame, Series)):
115-
return values.values
115+
return np.array(values.values)
116116
elif isinstance(values, ndarray):
117-
return values
117+
return np.array(values)
118118
else:
119119
raise TypeError(
120120
"Expect either pandas DataFrame or numpy array, "

src/fpm_risk_model/statistical/pca.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ def fit(
9191

9292
# Normalize the instrument return by full history mean
9393
if self._config.demean:
94-
X_mean = np.array(np.mean(X, axis=0))[np.newaxis, :]
94+
X_mean = np.array(X.mean(axis=0))[np.newaxis, :]
9595
X_fit = np.subtract(X_fit, X_mean)
9696

9797
# Remove the instruments without any returns always
@@ -109,11 +109,11 @@ def fit(
109109
N = X.shape[1]
110110
# Dimension (n, N) where n is the number of instruments
111111
# Eigenvectors
112-
U_m = self._model.components_
112+
U_m = np.array(self._model.components_)
113113
# Exposure matrix (n, N)
114114
B = np.multiply(
115115
U_m,
116-
np.array(self._model.singular_values_ * np.sqrt(T))[:, np.newaxis],
116+
np.array(self._model.singular_values_ * (T**0.5))[:, np.newaxis],
117117
)
118118
# Factor matrix (T, n)
119119
wls = WLS()

0 commit comments

Comments
 (0)