screamer 0.1.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.
- screamer-0.1.0/.gitattributes +16 -0
- screamer-0.1.0/.github/workflows/ci.yml +84 -0
- screamer-0.1.0/.github/workflows/publish.yml +43 -0
- screamer-0.1.0/.gitignore +158 -0
- screamer-0.1.0/.gitmodules +0 -0
- screamer-0.1.0/CMakeLists.txt +34 -0
- screamer-0.1.0/DEVGUIDE.md +46 -0
- screamer-0.1.0/LICENSE +21 -0
- screamer-0.1.0/PKG-INFO +10 -0
- screamer-0.1.0/README.md +5 -0
- screamer-0.1.0/_skbuild/macosx-14.0-arm64-3.11/cmake-install/screamer/__init__.py +6 -0
- screamer-0.1.0/_skbuild/macosx-14.0-arm64-3.11/cmake-install/screamer/generators.py +17 -0
- screamer-0.1.0/_skbuild/macosx-14.0-arm64-3.11/cmake-install/screamer/screamer_bindings.cpython-311-darwin.so +0 -0
- screamer-0.1.0/bindings/screamer_bindings.cpp +12 -0
- screamer-0.1.0/examples/lag_example.py +13 -0
- screamer-0.1.0/include/screamer/indicators/lag.h +24 -0
- screamer-0.1.0/poetry.lock +207 -0
- screamer-0.1.0/pyproject.toml +31 -0
- screamer-0.1.0/screamer/__init__.py +6 -0
- screamer-0.1.0/screamer/generators.py +17 -0
- screamer-0.1.0/screamer.egg-info/PKG-INFO +10 -0
- screamer-0.1.0/screamer.egg-info/SOURCES.txt +27 -0
- screamer-0.1.0/screamer.egg-info/dependency_links.txt +1 -0
- screamer-0.1.0/screamer.egg-info/top_level.txt +1 -0
- screamer-0.1.0/setup.cfg +4 -0
- screamer-0.1.0/setup.py +13 -0
- screamer-0.1.0/src/screamer/indicators/lag.cpp +24 -0
- screamer-0.1.0/tests/test_lag.cpp +87 -0
- screamer-0.1.0/tests/test_lag.py +37 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Set the default behavior to automatically normalize line endings.
|
|
2
|
+
* text=auto
|
|
3
|
+
|
|
4
|
+
# Explicitly declare text files you want to always be normalized and converted
|
|
5
|
+
# to native line endings on checkout.
|
|
6
|
+
*.c text
|
|
7
|
+
*.cpp text
|
|
8
|
+
*.h text
|
|
9
|
+
*.hpp text
|
|
10
|
+
*.py text
|
|
11
|
+
*.md text
|
|
12
|
+
|
|
13
|
+
# Declare binary files to be always stored and checked out as-is.
|
|
14
|
+
*.png binary
|
|
15
|
+
*.jpg binary
|
|
16
|
+
*.gif binary
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ main ]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
build:
|
|
11
|
+
|
|
12
|
+
runs-on: ${{ matrix.os }}
|
|
13
|
+
strategy:
|
|
14
|
+
matrix:
|
|
15
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
16
|
+
python-version: ['3.9', '3.10', '3.11']
|
|
17
|
+
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v3
|
|
20
|
+
|
|
21
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
22
|
+
uses: actions/setup-python@v4
|
|
23
|
+
with:
|
|
24
|
+
python-version: ${{ matrix.python-version }}
|
|
25
|
+
|
|
26
|
+
- name: Install Poetry
|
|
27
|
+
run: |
|
|
28
|
+
python -m pip install --upgrade pip
|
|
29
|
+
pip install poetry
|
|
30
|
+
|
|
31
|
+
- name: Install dependencies
|
|
32
|
+
run: poetry install
|
|
33
|
+
|
|
34
|
+
- name: Install CMake
|
|
35
|
+
uses: lukka/get-cmake@latest
|
|
36
|
+
|
|
37
|
+
# Build Step for Windows
|
|
38
|
+
- name: Build with CMake (Windows)
|
|
39
|
+
if: runner.os == 'Windows'
|
|
40
|
+
run: |
|
|
41
|
+
mkdir build
|
|
42
|
+
cd build
|
|
43
|
+
cmake .. -A x64
|
|
44
|
+
cmake --build . --config Debug
|
|
45
|
+
|
|
46
|
+
# Build Step for Linux and macOS
|
|
47
|
+
- name: Build with CMake (Linux and macOS)
|
|
48
|
+
if: runner.os != 'Windows'
|
|
49
|
+
run: |
|
|
50
|
+
mkdir build
|
|
51
|
+
cd build
|
|
52
|
+
cmake ..
|
|
53
|
+
cmake --build .
|
|
54
|
+
|
|
55
|
+
- name: List screamer directory
|
|
56
|
+
if: runner.os != 'Windows'
|
|
57
|
+
run: |
|
|
58
|
+
ls -la screamer
|
|
59
|
+
|
|
60
|
+
- name: List screamer directory
|
|
61
|
+
if: runner.os == 'Windows'
|
|
62
|
+
run: |
|
|
63
|
+
dir screamer
|
|
64
|
+
|
|
65
|
+
# Run C++ Tests on Windows
|
|
66
|
+
- name: Run C++ Tests (Windows)
|
|
67
|
+
if: runner.os == 'Windows'
|
|
68
|
+
run: |
|
|
69
|
+
cd build
|
|
70
|
+
ctest --output-on-failure -C Debug
|
|
71
|
+
|
|
72
|
+
# Run C++ Tests on Linux and macOS
|
|
73
|
+
- name: Run C++ Tests (Linux and macOS)
|
|
74
|
+
if: runner.os != 'Windows'
|
|
75
|
+
run: |
|
|
76
|
+
cd build
|
|
77
|
+
ctest --output-on-failure
|
|
78
|
+
|
|
79
|
+
# Run Python Tests
|
|
80
|
+
- name: Run Python Tests
|
|
81
|
+
env:
|
|
82
|
+
PYTHONPATH: ${{ github.workspace }}
|
|
83
|
+
run: |
|
|
84
|
+
poetry run pytest
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
name: Build and Publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags: 'v*'
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
build_and_publish:
|
|
9
|
+
runs-on: ${{ matrix.os }}
|
|
10
|
+
strategy:
|
|
11
|
+
matrix:
|
|
12
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
13
|
+
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v3
|
|
16
|
+
|
|
17
|
+
- name: Set up Python
|
|
18
|
+
uses: actions/setup-python@v4
|
|
19
|
+
with:
|
|
20
|
+
python-version: '3.x'
|
|
21
|
+
|
|
22
|
+
- name: Install cibuildwheel
|
|
23
|
+
run: |
|
|
24
|
+
python -m pip install --upgrade pip
|
|
25
|
+
pip install cibuildwheel==2.14.1
|
|
26
|
+
|
|
27
|
+
- name: Build wheels
|
|
28
|
+
env:
|
|
29
|
+
CIBW_BUILD_VERBOSITY: 1
|
|
30
|
+
CIBW_SKIP: cp27-*
|
|
31
|
+
CIBW_BEFORE_BUILD: python -m pip install --upgrade pip
|
|
32
|
+
CIBW_TEST_COMMAND: ""
|
|
33
|
+
run: |
|
|
34
|
+
cibuildwheel --output-dir wheelhouse
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
- name: Publish to PyPI via Trusted Publishers
|
|
38
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
39
|
+
with:
|
|
40
|
+
packages_dir: ./wheelhouse
|
|
41
|
+
env:
|
|
42
|
+
# The PyPI Publisher ID provided by PyPI after configuration
|
|
43
|
+
PYPI_PUBLISHER_ID: ${{ secrets.PYPI_PUBLISHER_ID }}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py,cover
|
|
50
|
+
.hypothesis/
|
|
51
|
+
.pytest_cache/
|
|
52
|
+
cover/
|
|
53
|
+
|
|
54
|
+
# Translations
|
|
55
|
+
*.mo
|
|
56
|
+
*.pot
|
|
57
|
+
|
|
58
|
+
# Django stuff:
|
|
59
|
+
*.log
|
|
60
|
+
local_settings.py
|
|
61
|
+
db.sqlite3
|
|
62
|
+
db.sqlite3-journal
|
|
63
|
+
|
|
64
|
+
# Flask stuff:
|
|
65
|
+
instance/
|
|
66
|
+
.webassets-cache
|
|
67
|
+
|
|
68
|
+
# Scrapy stuff:
|
|
69
|
+
.scrapy
|
|
70
|
+
|
|
71
|
+
# Sphinx documentation
|
|
72
|
+
docs/_build/
|
|
73
|
+
|
|
74
|
+
# PyBuilder
|
|
75
|
+
.pybuilder/
|
|
76
|
+
target/
|
|
77
|
+
|
|
78
|
+
# Jupyter Notebook
|
|
79
|
+
.ipynb_checkpoints
|
|
80
|
+
|
|
81
|
+
# IPython
|
|
82
|
+
profile_default/
|
|
83
|
+
ipython_config.py
|
|
84
|
+
|
|
85
|
+
# pyenv
|
|
86
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
87
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
88
|
+
# .python-version
|
|
89
|
+
|
|
90
|
+
# pipenv
|
|
91
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
92
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
93
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
94
|
+
# install all needed dependencies.
|
|
95
|
+
#Pipfile.lock
|
|
96
|
+
|
|
97
|
+
# poetry
|
|
98
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
99
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
100
|
+
# commonly ignored for libraries.
|
|
101
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
102
|
+
#poetry.lock
|
|
103
|
+
|
|
104
|
+
# pdm
|
|
105
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
106
|
+
#pdm.lock
|
|
107
|
+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
|
108
|
+
# in version control.
|
|
109
|
+
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
|
|
110
|
+
.pdm.toml
|
|
111
|
+
.pdm-python
|
|
112
|
+
.pdm-build/
|
|
113
|
+
|
|
114
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
115
|
+
__pypackages__/
|
|
116
|
+
|
|
117
|
+
# Celery stuff
|
|
118
|
+
celerybeat-schedule
|
|
119
|
+
celerybeat.pid
|
|
120
|
+
|
|
121
|
+
# SageMath parsed files
|
|
122
|
+
*.sage.py
|
|
123
|
+
|
|
124
|
+
# Environments
|
|
125
|
+
.env
|
|
126
|
+
.venv
|
|
127
|
+
env/
|
|
128
|
+
venv/
|
|
129
|
+
ENV/
|
|
130
|
+
env.bak/
|
|
131
|
+
venv.bak/
|
|
132
|
+
|
|
133
|
+
# Spyder project settings
|
|
134
|
+
.spyderproject
|
|
135
|
+
.spyproject
|
|
136
|
+
|
|
137
|
+
# Rope project settings
|
|
138
|
+
.ropeproject
|
|
139
|
+
|
|
140
|
+
# mkdocs documentation
|
|
141
|
+
/site
|
|
142
|
+
|
|
143
|
+
# mypy
|
|
144
|
+
.mypy_cache/
|
|
145
|
+
.dmypy.json
|
|
146
|
+
dmypy.json
|
|
147
|
+
|
|
148
|
+
# Pyre type checker
|
|
149
|
+
.pyre/
|
|
150
|
+
|
|
151
|
+
# pytype static type analyzer
|
|
152
|
+
.pytype/
|
|
153
|
+
|
|
154
|
+
# Cython debug symbols
|
|
155
|
+
cython_debug/
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
.DS_Store
|
|
File without changes
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
cmake_minimum_required(VERSION 3.15)
|
|
2
|
+
project(screamer VERSION 0.1.0 LANGUAGES CXX)
|
|
3
|
+
|
|
4
|
+
# Set C++ standard
|
|
5
|
+
set(CMAKE_CXX_STANDARD 17)
|
|
6
|
+
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
|
7
|
+
|
|
8
|
+
# Include FetchContent module
|
|
9
|
+
include(FetchContent)
|
|
10
|
+
|
|
11
|
+
# Fetch pybind11
|
|
12
|
+
FetchContent_Declare(
|
|
13
|
+
pybind11
|
|
14
|
+
GIT_REPOSITORY https://github.com/pybind/pybind11.git
|
|
15
|
+
GIT_TAG v2.13.6 # Specify the desired version
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
# Make pybind11 available
|
|
19
|
+
FetchContent_MakeAvailable(pybind11)
|
|
20
|
+
|
|
21
|
+
# Add source files
|
|
22
|
+
file(GLOB SOURCES "${CMAKE_SOURCE_DIR}/src/screamer/**/*.cpp")
|
|
23
|
+
|
|
24
|
+
# Create the core library
|
|
25
|
+
add_library(screamer_core ${SOURCES})
|
|
26
|
+
set_target_properties(screamer_core PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
|
27
|
+
target_include_directories(screamer_core PUBLIC "${CMAKE_SOURCE_DIR}/include")
|
|
28
|
+
|
|
29
|
+
# Create the Python module
|
|
30
|
+
pybind11_add_module(screamer_bindings MODULE bindings/screamer_bindings.cpp)
|
|
31
|
+
target_link_libraries(screamer_bindings PRIVATE screamer_core)
|
|
32
|
+
|
|
33
|
+
# Install the module into the Python package directory
|
|
34
|
+
install(TARGETS screamer_bindings DESTINATION .)
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
|
|
2
|
+
# Testing
|
|
3
|
+
|
|
4
|
+
## Test C++ code
|
|
5
|
+
|
|
6
|
+
* We use Google Test for the C++ unit tests.
|
|
7
|
+
* We use CMake for compiling the C++ code.
|
|
8
|
+
|
|
9
|
+
When compiling an building binaries we advice to use "out-of-source builds" strategy:
|
|
10
|
+
|
|
11
|
+
First create a `build` directory and run cmake from within that directory. Tell cmake to look for its configuration file
|
|
12
|
+
`CMakeList.txt` in the parent folder by proving the `..` argument to cmake.
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
# From project root
|
|
16
|
+
|
|
17
|
+
rm -rf build
|
|
18
|
+
mkdir build
|
|
19
|
+
cd build
|
|
20
|
+
cmake ..
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Then every time you have updated code, you can build the exedcutables and run ctest:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
# From project root
|
|
27
|
+
cd build
|
|
28
|
+
cmake --build .
|
|
29
|
+
ctest --output-on-failure
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Testing Python interface
|
|
33
|
+
|
|
34
|
+
For testing the Python interface we use `pytest`:
|
|
35
|
+
```
|
|
36
|
+
# From project root
|
|
37
|
+
|
|
38
|
+
poetry run pytest tests/test_lag.py
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# Running Examples
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
poetry run python examples/lag_example.py
|
|
46
|
+
```
|
screamer-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 QuantFinLib
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
screamer-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: screamer
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Screamingly fast streaming indicators with C++ performance and Python simplicity.
|
|
5
|
+
Author: Thijs van den Berg
|
|
6
|
+
Author-email: thijs@sitmo.com
|
|
7
|
+
Requires-Python: >=3.9
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
|
|
10
|
+
Screamer is a high-performance Python library designed for efficient streaming indicator algorithms. Built with a core of optimized C++ code and integrated through Python bindings, Screamer delivers lightning-fast computations for real-time data processing. The library is perfect for real-time algorithmic trading applications that need low-latency indicators.
|
screamer-0.1.0/README.md
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# screamer
|
|
2
|
+
Screamingly fast streaming indicators with C++ performance and Python simplicity.
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
Screamer is a high-performance Python library designed for efficient streaming indicator algorithms. Built with a core of optimized C++ code and integrated through Python bindings, Screamer delivers lightning-fast computations for real-time data processing. The library is perfect for real-time algorithmic trading applications that need low-latency indicators.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# screamer/generators.py
|
|
2
|
+
|
|
3
|
+
from .screamer_bindings import Lag
|
|
4
|
+
|
|
5
|
+
def lag_generator(iterable, delay, initial=0.0):
|
|
6
|
+
"""
|
|
7
|
+
Generator that yields lagged values from the input iterable.
|
|
8
|
+
|
|
9
|
+
:param iterable: An iterable of numerical values.
|
|
10
|
+
:param delay: Number of steps to lag.
|
|
11
|
+
:param initial: Initial value(s) to yield before lagged values are available.
|
|
12
|
+
"""
|
|
13
|
+
lag = Lag(delay, initial)
|
|
14
|
+
buffer = [initial] * delay
|
|
15
|
+
for value in iterable:
|
|
16
|
+
delayed_value = lag(value)
|
|
17
|
+
yield delayed_value
|
|
Binary file
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#include <pybind11/pybind11.h>
|
|
2
|
+
#include <pybind11/functional.h>
|
|
3
|
+
#include "screamer/indicators/lag.h"
|
|
4
|
+
|
|
5
|
+
namespace py = pybind11;
|
|
6
|
+
using namespace screamer::indicators;
|
|
7
|
+
|
|
8
|
+
PYBIND11_MODULE(screamer_bindings, m) {
|
|
9
|
+
py::class_<Lag>(m, "Lag")
|
|
10
|
+
.def(py::init<int, double>(), py::arg("delay"), py::arg("initial") = 0.0)
|
|
11
|
+
.def("__call__", &Lag::operator(), "Apply lag to the input value");
|
|
12
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#ifndef SCREAMER_INDICATORS_LAG_H
|
|
2
|
+
#define SCREAMER_INDICATORS_LAG_H
|
|
3
|
+
|
|
4
|
+
#include <deque>
|
|
5
|
+
#include <stdexcept> // For std::invalid_argument
|
|
6
|
+
|
|
7
|
+
namespace screamer {
|
|
8
|
+
namespace indicators {
|
|
9
|
+
|
|
10
|
+
class Lag {
|
|
11
|
+
public:
|
|
12
|
+
Lag(int delay, double initial = 0.0);
|
|
13
|
+
double operator()(double value);
|
|
14
|
+
|
|
15
|
+
private:
|
|
16
|
+
int delay_;
|
|
17
|
+
double initial_;
|
|
18
|
+
std::deque<double> buffer_;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
} // namespace indicators
|
|
22
|
+
} // namespace screamer
|
|
23
|
+
|
|
24
|
+
#endif // SCREAMER_INDICATORS_LAG_H
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand.
|
|
2
|
+
|
|
3
|
+
[[package]]
|
|
4
|
+
name = "build"
|
|
5
|
+
version = "1.2.2.post1"
|
|
6
|
+
description = "A simple, correct Python build frontend"
|
|
7
|
+
optional = false
|
|
8
|
+
python-versions = ">=3.8"
|
|
9
|
+
files = [
|
|
10
|
+
{file = "build-1.2.2.post1-py3-none-any.whl", hash = "sha256:1d61c0887fa860c01971625baae8bdd338e517b836a2f70dd1f7aa3a6b2fc5b5"},
|
|
11
|
+
{file = "build-1.2.2.post1.tar.gz", hash = "sha256:b36993e92ca9375a219c99e606a122ff365a760a2d4bba0caa09bd5278b608b7"},
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
[package.dependencies]
|
|
15
|
+
colorama = {version = "*", markers = "os_name == \"nt\""}
|
|
16
|
+
importlib-metadata = {version = ">=4.6", markers = "python_full_version < \"3.10.2\""}
|
|
17
|
+
packaging = ">=19.1"
|
|
18
|
+
pyproject_hooks = "*"
|
|
19
|
+
tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
|
|
20
|
+
|
|
21
|
+
[package.extras]
|
|
22
|
+
docs = ["furo (>=2023.08.17)", "sphinx (>=7.0,<8.0)", "sphinx-argparse-cli (>=1.5)", "sphinx-autodoc-typehints (>=1.10)", "sphinx-issues (>=3.0.0)"]
|
|
23
|
+
test = ["build[uv,virtualenv]", "filelock (>=3)", "pytest (>=6.2.4)", "pytest-cov (>=2.12)", "pytest-mock (>=2)", "pytest-rerunfailures (>=9.1)", "pytest-xdist (>=1.34)", "setuptools (>=42.0.0)", "setuptools (>=56.0.0)", "setuptools (>=56.0.0)", "setuptools (>=67.8.0)", "wheel (>=0.36.0)"]
|
|
24
|
+
typing = ["build[uv]", "importlib-metadata (>=5.1)", "mypy (>=1.9.0,<1.10.0)", "tomli", "typing-extensions (>=3.7.4.3)"]
|
|
25
|
+
uv = ["uv (>=0.1.18)"]
|
|
26
|
+
virtualenv = ["virtualenv (>=20.0.35)"]
|
|
27
|
+
|
|
28
|
+
[[package]]
|
|
29
|
+
name = "colorama"
|
|
30
|
+
version = "0.4.6"
|
|
31
|
+
description = "Cross-platform colored terminal text."
|
|
32
|
+
optional = false
|
|
33
|
+
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
|
|
34
|
+
files = [
|
|
35
|
+
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
|
|
36
|
+
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
[[package]]
|
|
40
|
+
name = "exceptiongroup"
|
|
41
|
+
version = "1.2.2"
|
|
42
|
+
description = "Backport of PEP 654 (exception groups)"
|
|
43
|
+
optional = false
|
|
44
|
+
python-versions = ">=3.7"
|
|
45
|
+
files = [
|
|
46
|
+
{file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"},
|
|
47
|
+
{file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"},
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
[package.extras]
|
|
51
|
+
test = ["pytest (>=6)"]
|
|
52
|
+
|
|
53
|
+
[[package]]
|
|
54
|
+
name = "importlib-metadata"
|
|
55
|
+
version = "8.5.0"
|
|
56
|
+
description = "Read metadata from Python packages"
|
|
57
|
+
optional = false
|
|
58
|
+
python-versions = ">=3.8"
|
|
59
|
+
files = [
|
|
60
|
+
{file = "importlib_metadata-8.5.0-py3-none-any.whl", hash = "sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b"},
|
|
61
|
+
{file = "importlib_metadata-8.5.0.tar.gz", hash = "sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7"},
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
[package.dependencies]
|
|
65
|
+
zipp = ">=3.20"
|
|
66
|
+
|
|
67
|
+
[package.extras]
|
|
68
|
+
check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"]
|
|
69
|
+
cover = ["pytest-cov"]
|
|
70
|
+
doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
|
|
71
|
+
enabler = ["pytest-enabler (>=2.2)"]
|
|
72
|
+
perf = ["ipython"]
|
|
73
|
+
test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"]
|
|
74
|
+
type = ["pytest-mypy"]
|
|
75
|
+
|
|
76
|
+
[[package]]
|
|
77
|
+
name = "iniconfig"
|
|
78
|
+
version = "2.0.0"
|
|
79
|
+
description = "brain-dead simple config-ini parsing"
|
|
80
|
+
optional = false
|
|
81
|
+
python-versions = ">=3.7"
|
|
82
|
+
files = [
|
|
83
|
+
{file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
|
|
84
|
+
{file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
|
|
85
|
+
]
|
|
86
|
+
|
|
87
|
+
[[package]]
|
|
88
|
+
name = "packaging"
|
|
89
|
+
version = "24.1"
|
|
90
|
+
description = "Core utilities for Python packages"
|
|
91
|
+
optional = false
|
|
92
|
+
python-versions = ">=3.8"
|
|
93
|
+
files = [
|
|
94
|
+
{file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"},
|
|
95
|
+
{file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"},
|
|
96
|
+
]
|
|
97
|
+
|
|
98
|
+
[[package]]
|
|
99
|
+
name = "pluggy"
|
|
100
|
+
version = "1.5.0"
|
|
101
|
+
description = "plugin and hook calling mechanisms for python"
|
|
102
|
+
optional = false
|
|
103
|
+
python-versions = ">=3.8"
|
|
104
|
+
files = [
|
|
105
|
+
{file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"},
|
|
106
|
+
{file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"},
|
|
107
|
+
]
|
|
108
|
+
|
|
109
|
+
[package.extras]
|
|
110
|
+
dev = ["pre-commit", "tox"]
|
|
111
|
+
testing = ["pytest", "pytest-benchmark"]
|
|
112
|
+
|
|
113
|
+
[[package]]
|
|
114
|
+
name = "pybind11"
|
|
115
|
+
version = "2.13.6"
|
|
116
|
+
description = "Seamless operability between C++11 and Python"
|
|
117
|
+
optional = false
|
|
118
|
+
python-versions = ">=3.7"
|
|
119
|
+
files = [
|
|
120
|
+
{file = "pybind11-2.13.6-py3-none-any.whl", hash = "sha256:237c41e29157b962835d356b370ededd57594a26d5894a795960f0047cb5caf5"},
|
|
121
|
+
{file = "pybind11-2.13.6.tar.gz", hash = "sha256:ba6af10348c12b24e92fa086b39cfba0eff619b61ac77c406167d813b096d39a"},
|
|
122
|
+
]
|
|
123
|
+
|
|
124
|
+
[package.extras]
|
|
125
|
+
global = ["pybind11-global (==2.13.6)"]
|
|
126
|
+
|
|
127
|
+
[[package]]
|
|
128
|
+
name = "pyproject-hooks"
|
|
129
|
+
version = "1.2.0"
|
|
130
|
+
description = "Wrappers to call pyproject.toml-based build backend hooks."
|
|
131
|
+
optional = false
|
|
132
|
+
python-versions = ">=3.7"
|
|
133
|
+
files = [
|
|
134
|
+
{file = "pyproject_hooks-1.2.0-py3-none-any.whl", hash = "sha256:9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913"},
|
|
135
|
+
{file = "pyproject_hooks-1.2.0.tar.gz", hash = "sha256:1e859bd5c40fae9448642dd871adf459e5e2084186e8d2c2a79a824c970da1f8"},
|
|
136
|
+
]
|
|
137
|
+
|
|
138
|
+
[[package]]
|
|
139
|
+
name = "pytest"
|
|
140
|
+
version = "7.4.4"
|
|
141
|
+
description = "pytest: simple powerful testing with Python"
|
|
142
|
+
optional = false
|
|
143
|
+
python-versions = ">=3.7"
|
|
144
|
+
files = [
|
|
145
|
+
{file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"},
|
|
146
|
+
{file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"},
|
|
147
|
+
]
|
|
148
|
+
|
|
149
|
+
[package.dependencies]
|
|
150
|
+
colorama = {version = "*", markers = "sys_platform == \"win32\""}
|
|
151
|
+
exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
|
|
152
|
+
iniconfig = "*"
|
|
153
|
+
packaging = "*"
|
|
154
|
+
pluggy = ">=0.12,<2.0"
|
|
155
|
+
tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""}
|
|
156
|
+
|
|
157
|
+
[package.extras]
|
|
158
|
+
testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
|
|
159
|
+
|
|
160
|
+
[[package]]
|
|
161
|
+
name = "tomli"
|
|
162
|
+
version = "2.0.2"
|
|
163
|
+
description = "A lil' TOML parser"
|
|
164
|
+
optional = false
|
|
165
|
+
python-versions = ">=3.8"
|
|
166
|
+
files = [
|
|
167
|
+
{file = "tomli-2.0.2-py3-none-any.whl", hash = "sha256:2ebe24485c53d303f690b0ec092806a085f07af5a5aa1464f3931eec36caaa38"},
|
|
168
|
+
{file = "tomli-2.0.2.tar.gz", hash = "sha256:d46d457a85337051c36524bc5349dd91b1877838e2979ac5ced3e710ed8a60ed"},
|
|
169
|
+
]
|
|
170
|
+
|
|
171
|
+
[[package]]
|
|
172
|
+
name = "wheel"
|
|
173
|
+
version = "0.44.0"
|
|
174
|
+
description = "A built-package format for Python"
|
|
175
|
+
optional = false
|
|
176
|
+
python-versions = ">=3.8"
|
|
177
|
+
files = [
|
|
178
|
+
{file = "wheel-0.44.0-py3-none-any.whl", hash = "sha256:2376a90c98cc337d18623527a97c31797bd02bad0033d41547043a1cbfbe448f"},
|
|
179
|
+
{file = "wheel-0.44.0.tar.gz", hash = "sha256:a29c3f2817e95ab89aa4660681ad547c0e9547f20e75b0562fe7723c9a2a9d49"},
|
|
180
|
+
]
|
|
181
|
+
|
|
182
|
+
[package.extras]
|
|
183
|
+
test = ["pytest (>=6.0.0)", "setuptools (>=65)"]
|
|
184
|
+
|
|
185
|
+
[[package]]
|
|
186
|
+
name = "zipp"
|
|
187
|
+
version = "3.20.2"
|
|
188
|
+
description = "Backport of pathlib-compatible object wrapper for zip files"
|
|
189
|
+
optional = false
|
|
190
|
+
python-versions = ">=3.8"
|
|
191
|
+
files = [
|
|
192
|
+
{file = "zipp-3.20.2-py3-none-any.whl", hash = "sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350"},
|
|
193
|
+
{file = "zipp-3.20.2.tar.gz", hash = "sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29"},
|
|
194
|
+
]
|
|
195
|
+
|
|
196
|
+
[package.extras]
|
|
197
|
+
check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"]
|
|
198
|
+
cover = ["pytest-cov"]
|
|
199
|
+
doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
|
|
200
|
+
enabler = ["pytest-enabler (>=2.2)"]
|
|
201
|
+
test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"]
|
|
202
|
+
type = ["pytest-mypy"]
|
|
203
|
+
|
|
204
|
+
[metadata]
|
|
205
|
+
lock-version = "2.0"
|
|
206
|
+
python-versions = "^3.9"
|
|
207
|
+
content-hash = "225fa821936948f17149e9904a4a69df322a0fbfb47586763f6eb492577204bf"
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
[tool.poetry]
|
|
2
|
+
name = "screamer"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Screamingly fast streaming indicators with C++ performance and Python simplicity."
|
|
5
|
+
|
|
6
|
+
authors = ["Thijs van den Berg <thijs@sitmo.com>, Mohammadjavad Vakili <Mohammadjavad.Vakili@shell.com>"]
|
|
7
|
+
|
|
8
|
+
maintainers = [
|
|
9
|
+
"Thijs van den Berg <thijs@sitmo.com>",
|
|
10
|
+
"Mohammadjavad Vakili <Mohammadjavad.Vakili@shell.com>"
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
license = "MIT"
|
|
15
|
+
readme = "README.md"
|
|
16
|
+
packages = [{ include = "screamer" }]
|
|
17
|
+
|
|
18
|
+
[tool.poetry.dependencies]
|
|
19
|
+
python = "^3.9"
|
|
20
|
+
pybind11 = "^2.9"
|
|
21
|
+
|
|
22
|
+
[tool.poetry.dev-dependencies]
|
|
23
|
+
pytest = "^7.0"
|
|
24
|
+
|
|
25
|
+
[tool.poetry.group.dev.dependencies]
|
|
26
|
+
wheel = "^0.44.0"
|
|
27
|
+
build = "^1.2.2.post1"
|
|
28
|
+
|
|
29
|
+
[build-system]
|
|
30
|
+
requires = ["setuptools", "wheel", "scikit-build", "cmake", "pybind11"]
|
|
31
|
+
build-backend = "setuptools.build_meta"
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# screamer/generators.py
|
|
2
|
+
|
|
3
|
+
from .screamer_bindings import Lag
|
|
4
|
+
|
|
5
|
+
def lag_generator(iterable, delay, initial=0.0):
|
|
6
|
+
"""
|
|
7
|
+
Generator that yields lagged values from the input iterable.
|
|
8
|
+
|
|
9
|
+
:param iterable: An iterable of numerical values.
|
|
10
|
+
:param delay: Number of steps to lag.
|
|
11
|
+
:param initial: Initial value(s) to yield before lagged values are available.
|
|
12
|
+
"""
|
|
13
|
+
lag = Lag(delay, initial)
|
|
14
|
+
buffer = [initial] * delay
|
|
15
|
+
for value in iterable:
|
|
16
|
+
delayed_value = lag(value)
|
|
17
|
+
yield delayed_value
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: screamer
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Screamingly fast streaming indicators with C++ performance and Python simplicity.
|
|
5
|
+
Author: Thijs van den Berg
|
|
6
|
+
Author-email: thijs@sitmo.com
|
|
7
|
+
Requires-Python: >=3.9
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
|
|
10
|
+
Screamer is a high-performance Python library designed for efficient streaming indicator algorithms. Built with a core of optimized C++ code and integrated through Python bindings, Screamer delivers lightning-fast computations for real-time data processing. The library is perfect for real-time algorithmic trading applications that need low-latency indicators.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
.gitattributes
|
|
2
|
+
.gitignore
|
|
3
|
+
.gitmodules
|
|
4
|
+
CMakeLists.txt
|
|
5
|
+
DEVGUIDE.md
|
|
6
|
+
LICENSE
|
|
7
|
+
README.md
|
|
8
|
+
poetry.lock
|
|
9
|
+
pyproject.toml
|
|
10
|
+
setup.py
|
|
11
|
+
.github/workflows/ci.yml
|
|
12
|
+
.github/workflows/publish.yml
|
|
13
|
+
_skbuild/macosx-14.0-arm64-3.11/cmake-install/screamer/__init__.py
|
|
14
|
+
_skbuild/macosx-14.0-arm64-3.11/cmake-install/screamer/generators.py
|
|
15
|
+
_skbuild/macosx-14.0-arm64-3.11/cmake-install/screamer/screamer_bindings.cpython-311-darwin.so
|
|
16
|
+
bindings/screamer_bindings.cpp
|
|
17
|
+
examples/lag_example.py
|
|
18
|
+
include/screamer/indicators/lag.h
|
|
19
|
+
screamer/__init__.py
|
|
20
|
+
screamer/generators.py
|
|
21
|
+
screamer.egg-info/PKG-INFO
|
|
22
|
+
screamer.egg-info/SOURCES.txt
|
|
23
|
+
screamer.egg-info/dependency_links.txt
|
|
24
|
+
screamer.egg-info/top_level.txt
|
|
25
|
+
src/screamer/indicators/lag.cpp
|
|
26
|
+
tests/test_lag.cpp
|
|
27
|
+
tests/test_lag.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
screamer
|
screamer-0.1.0/setup.cfg
ADDED
screamer-0.1.0/setup.py
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from skbuild import setup
|
|
2
|
+
|
|
3
|
+
setup(
|
|
4
|
+
name="screamer",
|
|
5
|
+
version="0.1.0",
|
|
6
|
+
description="Screamingly fast streaming indicators with C++ performance and Python simplicity.",
|
|
7
|
+
long_description="Screamer is a high-performance Python library designed for efficient streaming indicator algorithms. Built with a core of optimized C++ code and integrated through Python bindings, Screamer delivers lightning-fast computations for real-time data processing. The library is perfect for real-time algorithmic trading applications that need low-latency indicators.",
|
|
8
|
+
author="Thijs van den Berg",
|
|
9
|
+
author_email="thijs@sitmo.com",
|
|
10
|
+
packages=["screamer"],
|
|
11
|
+
cmake_install_dir="screamer",
|
|
12
|
+
python_requires='>=3.9',
|
|
13
|
+
)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#include "screamer/indicators/lag.h"
|
|
2
|
+
|
|
3
|
+
namespace screamer {
|
|
4
|
+
namespace indicators {
|
|
5
|
+
|
|
6
|
+
Lag::Lag(int delay, double initial)
|
|
7
|
+
: delay_(delay), initial_(initial)
|
|
8
|
+
{
|
|
9
|
+
if (delay_ < 1) {
|
|
10
|
+
throw std::invalid_argument("Delay must be an integer >= 1.");
|
|
11
|
+
}
|
|
12
|
+
buffer_.resize(delay_, initial_);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
double Lag::operator()(double value) {
|
|
17
|
+
double delayed = buffer_.front();
|
|
18
|
+
buffer_.pop_front();
|
|
19
|
+
buffer_.push_back(value);
|
|
20
|
+
return delayed;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
} // namespace indicators
|
|
24
|
+
} // namespace screamer
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// tests/test_lag.cpp
|
|
2
|
+
|
|
3
|
+
#include <gtest/gtest.h>
|
|
4
|
+
#include "screamer/indicators/lag.h"
|
|
5
|
+
|
|
6
|
+
using namespace screamer::indicators;
|
|
7
|
+
|
|
8
|
+
// Test Fixture for Lag
|
|
9
|
+
class LagTest : public ::testing::Test {
|
|
10
|
+
protected:
|
|
11
|
+
|
|
12
|
+
LagTest() {
|
|
13
|
+
// Set-up work for each test here.
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
~LagTest() override {
|
|
17
|
+
// Clean-up work that doesn't throw exceptions here.
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
void SetUp() override {
|
|
21
|
+
// Called immediately after the constructor (right before each test).
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
void TearDown() override {
|
|
25
|
+
// Called immediately after each test (right before the destructor).
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// Test the constructor and initial state
|
|
31
|
+
TEST_F(LagTest, ConstructorInitializesBufferCorrectly) {
|
|
32
|
+
int delay = 3;
|
|
33
|
+
double initial = 5.0;
|
|
34
|
+
Lag lag(delay, initial);
|
|
35
|
+
|
|
36
|
+
// Access the internal buffer using a friend class or by modifying the Lag class to provide buffer access for testing
|
|
37
|
+
// For simplicity, we'll test behavior instead of internal state
|
|
38
|
+
|
|
39
|
+
// Initial calls should return the initial value
|
|
40
|
+
EXPECT_DOUBLE_EQ(lag(10.0), 5.0);
|
|
41
|
+
EXPECT_DOUBLE_EQ(lag(20.0), 5.0);
|
|
42
|
+
EXPECT_DOUBLE_EQ(lag(30.0), 5.0);
|
|
43
|
+
// After delay, should return the first value
|
|
44
|
+
EXPECT_DOUBLE_EQ(lag(40.0), 10.0);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Test default initial value
|
|
48
|
+
TEST_F(LagTest, DefaultInitialValue) {
|
|
49
|
+
int delay = 2;
|
|
50
|
+
Lag lag(delay); // initial defaults to 0.0
|
|
51
|
+
|
|
52
|
+
EXPECT_DOUBLE_EQ(lag(10.0), 0.0);
|
|
53
|
+
EXPECT_DOUBLE_EQ(lag(20.0), 0.0);
|
|
54
|
+
EXPECT_DOUBLE_EQ(lag(30.0), 10.0);
|
|
55
|
+
EXPECT_DOUBLE_EQ(lag(40.0), 20.0);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Test multiple sequential calls
|
|
59
|
+
TEST_F(LagTest, MultipleSequentialCalls) {
|
|
60
|
+
int delay = 4;
|
|
61
|
+
double initial = 1.0;
|
|
62
|
+
Lag lag(delay, initial);
|
|
63
|
+
|
|
64
|
+
std::vector<double> inputs = {100.0, 200.0, 300.0, 400.0, 500.0};
|
|
65
|
+
std::vector<double> expected = {1.0, 1.0, 1.0, 1.0, 100.0};
|
|
66
|
+
|
|
67
|
+
for (size_t i = 0; i < inputs.size(); ++i) {
|
|
68
|
+
EXPECT_DOUBLE_EQ(lag(inputs[i]), expected[i]) << "Failed at index " << i;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Test the constructor with valid delay
|
|
73
|
+
TEST_F(LagTest, ConstructorValidDelay) {
|
|
74
|
+
EXPECT_NO_THROW(Lag(2, 0.0));
|
|
75
|
+
EXPECT_NO_THROW(Lag(5, 10.0));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Test the constructor with zero delay
|
|
79
|
+
TEST_F(LagTest, ConstructorZeroDelay) {
|
|
80
|
+
EXPECT_THROW(Lag(0, 0.0), std::invalid_argument);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Test the constructor with negative delay
|
|
84
|
+
TEST_F(LagTest, ConstructorNegativeDelay) {
|
|
85
|
+
EXPECT_THROW(Lag(-1, 0.0), std::invalid_argument);
|
|
86
|
+
EXPECT_THROW(Lag(-5, 10.0), std::invalid_argument);
|
|
87
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# tests/test_python.py
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
from screamer import Lag, lag_generator
|
|
5
|
+
|
|
6
|
+
def test_lag_valid_delay():
|
|
7
|
+
lag = Lag(2, 0.0)
|
|
8
|
+
assert lag(10.0) == 0.0
|
|
9
|
+
assert lag(20.0) == 0.0
|
|
10
|
+
assert lag(30.0) == 10.0
|
|
11
|
+
assert lag(40.0) == 20.0
|
|
12
|
+
|
|
13
|
+
def test_lag_zero_delay():
|
|
14
|
+
with pytest.raises(ValueError) as exc_info:
|
|
15
|
+
Lag(0, 0.0)
|
|
16
|
+
assert "Delay must be an integer >= 1." in str(exc_info.value)
|
|
17
|
+
|
|
18
|
+
def test_lag_negative_delay():
|
|
19
|
+
with pytest.raises(ValueError) as exc_info:
|
|
20
|
+
Lag(-1, 0.0)
|
|
21
|
+
assert "Delay must be an integer >= 1." in str(exc_info.value)
|
|
22
|
+
|
|
23
|
+
def test_lag_generator_valid():
|
|
24
|
+
values = [10, 20, 30, 40]
|
|
25
|
+
delay = 2
|
|
26
|
+
initial = 0.0
|
|
27
|
+
gen = lag_generator(values, delay, initial)
|
|
28
|
+
outputs = list(gen)
|
|
29
|
+
assert outputs == [0.0, 0.0, 10.0, 20.0]
|
|
30
|
+
|
|
31
|
+
def test_lag_generator_invalid_delay():
|
|
32
|
+
values = [10, 20]
|
|
33
|
+
delay = 0
|
|
34
|
+
initial = 0.0
|
|
35
|
+
with pytest.raises(ValueError) as exc_info:
|
|
36
|
+
list(lag_generator(values, delay, initial))
|
|
37
|
+
assert "Delay must be an integer >= 1." in str(exc_info.value)
|