diff --git a/.coverage b/.coverage index 3493a68..8585ff2 100644 Binary files a/.coverage and b/.coverage differ diff --git a/.github/Contributor_Guide/Contributing.md b/.github/Contributor_Guide/Contributing.md new file mode 100644 index 0000000..73aebc7 --- /dev/null +++ b/.github/Contributor_Guide/Contributing.md @@ -0,0 +1,37 @@ +# Contribute to + +Thank you for taking the time to contribute to ! We really appreciate it. + +Before contributing, please make sure to read the [Code of Conduct](../../CODE_OF_CONDUCT.md). We expect you to follow it in all your interactions with the project. + +## New to ? + +If you are new to , please take a look at the [documentation](./Project_Tour.md). It is a great place to start. + +## New Contributor Guide + +To get an overview of the codebase, check out the '[README.md](../../README.md)' file in the root directory. + +that will help you understand the structure of the project. + +## How to Contribute + +### Reporting Bugs + +If you find a bug in the source code, you can help us by [submitting an issue](../ISSUE_TEMPLATE/bug_report.yaml). + +### Suggesting Enhancements + +If you want to suggest an enhancement to , please [submit an issue](../ISSUE_TEMPLATE/feature_request.yaml). + +### Pull Requests + +If you want to contribute to , submit a pull request. + +- url: `https://github.com/OPCODE-Open-Spring-Fest//compare/branch...YOURGITHUBUSERNAME::BRANCH?quick_pull=1&template=pr.md` + +### Requirements + + +### Setup + diff --git a/.github/Contributor_Guide/Project_Tour.md b/.github/Contributor_Guide/Project_Tour.md new file mode 100644 index 0000000..a37e500 --- /dev/null +++ b/.github/Contributor_Guide/Project_Tour.md @@ -0,0 +1,12 @@ +# Project Tour + +* notes: +* > Discuss about your project file structure +* > what each folder is responsible +* > then go through each file in folders and explain there purpose +* > if possible create a doc system ( there are autogen docs available for most of the languages ) +* > decide coding style , linting style and formatting style and other themes like variable naming etc. +* > provide an example for existing function and tests system if possible +* + +# MAKE SURE PROJECT MANAGERS UPDATE THIS MD \ No newline at end of file diff --git a/.github/Contributor_Guide/commiting.md b/.github/Contributor_Guide/commiting.md new file mode 100644 index 0000000..6fd6efd --- /dev/null +++ b/.github/Contributor_Guide/commiting.md @@ -0,0 +1,73 @@ +# Commiting Guidelines + +## Commit Structure + +- **Make Commits Atomic**: Each commit should represent a single logical change. Avoid mixing multiple changes in a single commit. If a change affects multiple files, ensure it constitutes one "logical" change. + +### Writing Commit Messages + +- **Clear Subject Line**: Start the commit message with a clear and concise description of the change. It should be no more than 50 characters, start with a capital letter, and be in imperative mood. + + - > ```bash + > feat: Add function to calculate average + > ``` + +- **Separate Subject from Body**: If further explanation is needed, include it in the body of the commit message, following a blank line after the subject line. + +- **Explain the Change**: The body of the commit message should explain why the change was needed and how it was implemented. Keep it wrapped to 72 characters and written in present tense. + + - > ```bash + > fix: Resolve issue with login form not submitting on Safari + > + > This commit fixes a bug where the login form was not submitting on Safari browsers. The issue was caused by an outdated event listener binding, which has been updated to the correct syntax. + > ``` + +- **Avoid "How" Details**: Use the commit message to explain what changes were made and why, not how they were made. Well-written code should be self-explanatory. + +- **Reference Issues or Pull Requests**: If the commit is related to an issue or a pull request, include the reference in the commit message. This can be done in the body of the message or at the end. + + - > ```bash + > feat: Add user authentication feature + > + > Closes #123 + > ``` + +- **Avoid Unnecessary Punctuation**: Do not end the subject line with a period. + +### Commit Message Structure Rules + +- **Type Enum**: Ensure your commit type matches one of the predefined values: `build`, `chore`, `ci`, `docs`, `feat`, `fix`, `perf`, `refactor`, `revert`, `style`, `test`. + + - `build`: This type is used for changes related to build processes or tools. It includes modifications to build scripts, configuration files, and build-related dependencies. + + - `chore`: Chore changes typically involve tasks related to maintenance or housekeeping. This could include updating dependencies, cleaning up code, or configuring development tools. + + - `ci`: Changes related to Continuous Integration (CI) configuration files and scripts fall under this type. It includes modifications to CI pipelines, configurations for automated testing, and integration with CI services. + + - `docs`: Documentation changes belong to this type. It covers updates to documentation files, such as READMEs, API documentation, or inline code comments. + + - `feat`: This type is for new feature implementations or enhancements to existing features. It signifies significant additions or improvements to the codebase's functionality. + + - `fix`: Use this type for bug fixes or patches. It indicates changes made to address issues or bugs in the codebase. + + - `perf`: Performance-related changes are categorized under this type. It includes optimizations aimed at improving the codebase's performance, such as reducing execution time or memory usage. + + - `refactor`: Refactoring changes fall under this type. It involves restructuring or cleaning up the code without changing its external behavior. Refactoring aims to improve code quality, maintainability, or readability. + + - `revert`: Reverting changes made in a previous commit is indicated by this type. It's used when undoing the effects of a specific commit, often to address unexpected issues or regressions introduced by the previous change. + + - `style`: Style-related changes belong to this type. It covers modifications to code style, formatting, or whitespace, without affecting the code's functionality. + + - `test`: Test-related changes are categorized under this type. It includes additions or modifications to test cases, test suites, or testing infrastructure to ensure code correctness and reliability. + +- **Type Case**: Use lowercase for commit types. + +- **Subject Not Empty**: The subject line should not be empty. + +- **Subject Case**: Use sentence case for the subject line. + +- **Subject Length**: Keep the subject line under 100 characters. + +- **Body Leading Blank**: Ensure there's a leading blank line in the commit body. + +- **Body Max Line Length**: Keep each line in the commit body under 100 characters. diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml new file mode 100644 index 0000000..e30e4e3 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -0,0 +1,75 @@ +name: Bug Report +description: File a bug report +title: "[Bug]: " +labels: ["Issue:bug"] +assignees: + - +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this bug report! + - type: textarea + id: what-happened + attributes: + label: Description + description: Also tell us, what did you expect to happen? + placeholder: Tell us what you see! + value: "Describe the issue happened" + validations: + required: true + - type: textarea + id: error-message + attributes: + label: Error message + description: If applicable, please provide the error message you received. + placeholder: Copy and paste the error message here + validations: + required: false + - type: dropdown + id: severity + attributes: + label: Severity + description: How severe is the bug? + options: + - Low + - Medium + - High + - Critical + - type: textarea + id: steps + attributes: + label: Steps to reproduce + description: Please provide detailed steps for reproducing the issue. + placeholder: Tell us how to reproduce the issue + value: "1. 2. 3." + validations: + required: true + - type: textarea + id: environment + attributes: + label: Environment + description: Please provide details about your environment. + placeholder: Tell us about your environment + value: "OS: \nBrowser: \nVersion: \nLanguage:..." + - type: textarea + id: screenshots + attributes: + label: Screenshots + description: If applicable, add screenshots to help explain your problem. + placeholder: Drag and drop your screenshots here + + - type: textarea + id: logs + attributes: + label: Relevant log output + description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. + render: shell + - type: checkboxes + id: terms + attributes: + label: Code of Conduct + description: By submitting this issue, you agree to follow our [Code of Conduct](../Code_of_Conduct.md) + options: + - label: I agree to follow this project's Code of Conduct + required: true diff --git a/.github/ISSUE_TEMPLATE/feature_request.yaml b/.github/ISSUE_TEMPLATE/feature_request.yaml new file mode 100644 index 0000000..484f52f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yaml @@ -0,0 +1,30 @@ +name: Feature Request +description: Request a feature or suggest us what is in your mind! +title: "[Feature]: " +labels: "Issue:feature" +assignees: + - +body: + - type: markdown + attributes: + value: | + Please explain what is in your mind, we would like to hear it from you! + + + - type: textarea + id: explaining + attributes: + label: So, what is it about? + description: Please describe what you're requesting for. So, we Quant Team can understand your request better and work on it faster! + placeholder: It's about... + validations: + required: true + + - type: checkboxes + id: terms + attributes: + label: Code of Conduct + description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/OPCODE-Open-Spring-Fest/template/blob/main/.github/Contributor_Guide/CODE_OF_CONDUCT.md) + options: + - label: I agree to follow this project's Code of Conduct + required: true diff --git a/.github/ISSUE_TEMPLATE/good-first-issue-2.md b/.github/ISSUE_TEMPLATE/good-first-issue-2.md index 6c41023..263750e 100644 --- a/.github/ISSUE_TEMPLATE/good-first-issue-2.md +++ b/.github/ISSUE_TEMPLATE/good-first-issue-2.md @@ -14,6 +14,3 @@ Teach `VectorizedBacktest` to rebalance weekly or monthly via a `rebalance_freq` ### Definition of Done - Tests pass; daily default unchanged. - - - diff --git a/.github/ISSUE_TEMPLATE/good-first-issue-3.md b/.github/ISSUE_TEMPLATE/good-first-issue-3.md index 4c7a840..6060a1a 100644 --- a/.github/ISSUE_TEMPLATE/good-first-issue-3.md +++ b/.github/ISSUE_TEMPLATE/good-first-issue-3.md @@ -16,4 +16,3 @@ Modify CLI backtest command to also save a Plotly HTML chart for PnL. - CLI still supports Matplotlib PNG; Plotly HTML added. - diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 8e3c290..288778b 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,17 +1,24 @@ -### Summary -Describe the change and why it’s needed. -### Changes -- +## Description + +> Give a brief description of the pull request. ### Testing + - [ ] `pytest` passes locally - [ ] Linting passes (`ruff`, `black`) -### Screenshots (optional) +## Semver Changes + +- [ ] Patch (bug fix, no new features) +- [ ] Minor (new features, no breaking changes) +- [ ] Major (breaking changes) + +## Issues -### Related Issues -Fixes # +> List any issues that this pull request closes. +## Checklist +- [ ] I have read the [Contributing Guidelines](../Contributor_Guide/Contruting.md). diff --git a/.github/workflows/checklabels.yaml b/.github/workflows/checklabels.yaml new file mode 100644 index 0000000..1b752ff --- /dev/null +++ b/.github/workflows/checklabels.yaml @@ -0,0 +1,21 @@ +name: Label Checker + +on: + pull_request: + types: [opened, edited, synchronize, reopened, labeled, unlabeled] + +jobs: + check-labels: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: 16 + - name: Install dependencies + run: npm install @actions/github @actions/core + - name: Run Label Checker + run: node .github/workflows/label-checker.js + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/commitlint.yaml b/.github/workflows/commitlint.yaml new file mode 100644 index 0000000..7c61d10 --- /dev/null +++ b/.github/workflows/commitlint.yaml @@ -0,0 +1,36 @@ +name: CI + +on: [push, pull_request] + +jobs: + commitlint: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Install required dependencies + run: | + sudo apt update + sudo apt install -y sudo + sudo apt install -y git curl + curl -sL https://deb.nodesource.com/setup_20.x | sudo -E bash - + sudo DEBIAN_FRONTEND=noninteractive apt install -y nodejs + - name: Print versions + run: | + git --version + node --version + npm --version + npx commitlint --version + - name: Install commitlint + run: | + npm install conventional-changelog-conventionalcommits + npm install commitlint@latest + + - name: Validate current commit (last commit) with commitlint + if: github.event_name == 'push' + run: npx commitlint --from HEAD~1 --to HEAD --verbose + + - name: Validate PR commits with commitlint + if: github.event_name == 'pull_request' + run: npx commitlint --from ${{ github.event.pull_request.head.sha }}~${{ github.event.pull_request.commits }} --to ${{ github.event.pull_request.head.sha }} --verbose diff --git a/.github/workflows/label-checker.js b/.github/workflows/label-checker.js new file mode 100644 index 0000000..aae7358 --- /dev/null +++ b/.github/workflows/label-checker.js @@ -0,0 +1,42 @@ +import { getOctokit, context } from '@actions/github'; +import { setFailed } from '@actions/core'; + +async function run() { + try { + const token = process.env.GITHUB_TOKEN; + const octokit = new getOctokit(token); + + const pullRequest = context.payload.pull_request; + const owner = pullRequest.base.repo.owner.login; + const repo = pullRequest.base.repo.name; + const pullNumber = pullRequest.number; + + const { data: labels } = await octokit.rest.issues.listLabelsOnIssue({ + owner, + repo, + issue_number: pullNumber, + }); + + const labelNames = labels.map((label) => label.name); + + const requiredLabels = [ + ['Type:Easy', 'Type:Medium', 'Type:Hard'], + ['Semver:major', 'Semver:minor', 'Semver:patch'], + ['PR:Accept'], + ]; + + const hasRequiredLabels = requiredLabels.every((labelGroup) => + labelGroup.some((label) => labelNames.includes(label)) + ); + + if (!hasRequiredLabels) { + setFailed( + 'This pull request must have at least one label from each of the following groups: Type (Easy, Medium, Hard), Semver (Major, Minor, Patch), and PR:Accept.' + ); + } + } catch (error) { + setFailed(error.message); + } +} + +run(); \ No newline at end of file diff --git a/.github/workflows/prmerged.yaml b/.github/workflows/prmerged.yaml new file mode 100644 index 0000000..2c91fce --- /dev/null +++ b/.github/workflows/prmerged.yaml @@ -0,0 +1,32 @@ +name: On Pull Request Merge + +on: + pull_request_target: + types: [closed] + +jobs: + + on-merge: + runs-on: ubuntu-latest + if: ${{ github.event.pull_request.merged == true }} + steps: + - name: Get Pull Request Data + id: get-pr-data + env: + PULL_REQUEST_OWNER: ${{ github.event.pull_request.user.login }} + PULL_REQUEST_LABELS: ${{ join(github.event.pull_request.labels.*.name, ', ') }} + REPOSITORY_NAME: ${{ github.event.repository.name }} + REPOSITORY_URL: ${{ github.event.repository.html_url }} + run: | + echo "::set-output name=owner::$PULL_REQUEST_OWNER" + echo "::set-output name=labels::$PULL_REQUEST_LABELS" + echo "::set-output name=repo_name::$REPOSITORY_NAME" + echo "::set-output name=repo_url::$REPOSITORY_URL" + + - name: Send Data to API + env: + API_URL: https://opcode.gymkhana.iiitbh.ac.in/api/prmerged + API_AUTH_TOKEN: ${{ secrets.API_AUTH_TOKEN }} + run: | + payload=$(echo '{"owner":"${{ steps.get-pr-data.outputs.owner }}","labels":"${{ steps.get-pr-data.outputs.labels }}","repository_name":"${{ steps.get-pr-data.outputs.repo_name }}","repository_url":"${{ steps.get-pr-data.outputs.repo_url }}"}') + curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $API_AUTH_TOKEN" -d "$payload" "$API_URL" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ba83c77 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +node_modules +.vscode +.coverage +__pycache__/ +*.py[cod] +*$py.class \ No newline at end of file diff --git a/.husky/commit-msg b/.husky/commit-msg new file mode 100644 index 0000000..78f4d1d --- /dev/null +++ b/.husky/commit-msg @@ -0,0 +1 @@ +npm run commitlint ${1} diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index f2c2655..6199abc 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -18,6 +18,3 @@ We are committed to fostering a welcoming and inclusive community. - Maintainers may take appropriate action, including warnings or bans. Adapted from the Contributor Covenant. - - - diff --git a/README.md b/README.md index 44e41a4..cdb1b2d 100644 --- a/README.md +++ b/README.md @@ -10,15 +10,15 @@ A modular, open-source quantitative research and backtesting framework built for ## Why this project -QuantResearchStarter provides a clean, well-documented starting point for quantitative research and backtesting. Its priorities are: +QuantResearchStarter aims to provide a clean, well-documented starting point for quantitative research and backtesting. It focuses on: * **Readability**: idiomatic Python, type hints, and small modules you can read and change quickly. * **Testability**: deterministic vectorized backtests with unit tests and CI. -* **Extensibility**: plugin-friendly factor & data adapters so you can try new ideas fast. +* **Extensibility**: plug-in friendly factor & data adapters so you can try new ideas fast. --- -## Features +## Key features * **Data management** — download market data or generate synthetic price series for experiments. * **Factor library** — example implementations of momentum, value, size, and volatility factors. @@ -77,7 +77,7 @@ streamlit run src/quant_research_starter/dashboard/streamlit_app.py --- -## Minimal example +## Example: small strategy (concept) ```python from quant_research_starter.backtest import Backtester @@ -93,7 +93,7 @@ results = bt.run() print(results.performance.summary()) ``` -> See the `examples/` directory for fully working notebooks and scripts. +> The code above is illustrative—see `examples/` for fully working notebooks and scripts. --- @@ -127,44 +127,60 @@ QuantResearchStarter/ ## Tests & CI -Run unit tests locally with: +We include unit tests and a CI workflow (GitHub Actions). Run tests locally with: ```bash pytest -q ``` -CI runs linting (ruff), formatting checks (black), and unit tests across supported Python versions. The workflow is defined in `.github/workflows/ci.yml`. +The CI pipeline runs linting, unit tests, and builds docs on push/PR. --- ## Contributing -Contributions are welcome. Please follow these steps: +Contributions are very welcome. Please follow these steps: 1. Fork the repository -2. Create a descriptive branch (feature or fix) +2. Create a feature branch 3. Add tests for new behavior 4. Open a pull request with a clear description and rationale -Before submitting, ensure your tests pass and formatting/linting checks succeed. +Please review `CONTRIBUTING.md` and the `CODE_OF_CONDUCT.md` before submitting. --- -## AI policy (short & practical) +## AI policy — short & practical -**Yes — you may use AI tools** (ChatGPT, Copilot, etc.) to help write or review code and documentation. Please follow these guidelines: +**Yes — you are allowed to use AI tools** (ChatGPT, Copilot, Codeium, etc.) to help develop, prototype, or document code in this repository. -* **Disclose** substantial AI assistance in the PR or commit message (e.g., "Generated with ChatGPT; reviewed and adapted by @your-username"). -* **Review thoroughly** all AI-generated code for correctness, security, numerical stability, and licensing concerns. -* **Add tests** for AI-generated logic when applicable. -* **Respect licenses**: do not paste or rely on large verbatim copyrighted snippets without appropriate permission or attribution. +A few friendly guidelines: -This policy encourages fast iteration while maintaining quality and transparency. +* **Be transparent** when a contribution is substantially generated by an AI assistant — add a short note in the PR or commit message (e.g., "Generated with ChatGPT; reviewed and adapted by "). +* **Review and test** all AI-generated code. Treat it as a helpful draft, not final production-quality code. +* **Follow licensing** and attribution rules for any external snippets the AI suggests. Don’t paste large verbatim copyrighted material. +* **Security & correctness**: double-check numerical logic, data handling, and anything that affects trading decisions. + +This policy is intentionally permissive: we want the community to move fast while keeping quality and safety in mind. --- ## License -This project is available under the MIT License — see the `LICENSE` file for details. +This project is licensed under the MIT License — see the `LICENSE` file for details. + +--- + +## Acknowledgements + +Built with inspiration from open-source quant libraries and the research community. If you use this project in papers or public work, a short citation or mention is appreciated. --- + +If you'd like, I can also: + +* produce a shorter README for a GitHub landing page (one-screen summary), +* create a `CONTRIBUTING.md` snippet for how to document AI-assisted PRs, or +* generate example Jupyter notebooks that exercise the backtester. + +Tell me which of those you'd like and I'll add them next. diff --git a/commitlint.config.js b/commitlint.config.js new file mode 100644 index 0000000..0fca76f --- /dev/null +++ b/commitlint.config.js @@ -0,0 +1 @@ +export default {extends: ['@commitlint/config-conventional']}; diff --git a/data_sample/sample_prices.csv b/data_sample/sample_prices.csv deleted file mode 100644 index 28848b2..0000000 --- a/data_sample/sample_prices.csv +++ /dev/null @@ -1,366 +0,0 @@ -date,SYMBOL_00,SYMBOL_01,SYMBOL_02,SYMBOL_03,SYMBOL_04 -2020-01-01,101.04342882773649,100.56862543263516,101.53934783731859,103.31063855398534,100.62495115927857 -2020-01-02,100.6207903119225,102.57847528698282,103.24733722645678,102.86674777694316,101.90901588263725 -2020-01-03,99.73851117603287,101.3031444092264,102.70476049922597,98.86677722255703,97.61564376945392 -2020-01-04,98.66674547535155,99.11184669671138,101.78904033435498,96.71157365852639,94.2747108279334 -2020-01-05,101.60829619965239,100.89599958398054,103.91567839690133,94.9915660189228,93.65735415889269 -2020-01-06,101.88451359287025,99.46534341830954,103.96723795268205,93.83110332020665,92.85438585767866 -2020-01-07,100.70936355184,101.32922908629321,104.29124597984129,92.12641663080797,94.04179907034458 -2020-01-08,98.30070928959195,99.97125958635326,100.06246739488172,88.96766022866274,93.02286721192601 -2020-01-09,99.80169616673379,101.320194877739,101.12948751904571,88.9432889988398,90.88900614265867 -2020-01-10,98.4147628618792,99.70413884851244,101.31100015752843,89.24914744421952,87.7944872230779 -2020-01-11,99.10186352676672,99.67863073577044,100.73192129167742,90.33103956269687,89.73545310616558 -2020-01-12,100.99724731161818,99.85392015834783,101.22551665653809,91.22852819517566,91.80541460994169 -2020-01-13,100.07983989647029,98.9898733361795,99.0615385700473,88.76932332530693,92.34455422628014 -2020-01-14,102.84452689717205,100.83760949317426,102.27589763471406,90.28968748283475,92.34096716491828 -2020-01-15,103.63930075943189,103.63425951146719,103.75492242104298,93.55741586206369,89.08898098097322 -2020-01-16,105.39474930445269,105.0288640532631,104.68344184737579,94.22335438186042,86.34858561938337 -2020-01-17,104.98440120297361,105.31583043452176,106.68114829738325,93.55873458831515,85.12656394273039 -2020-01-18,103.98335964765275,106.02745510178426,107.05031317718641,92.67693212065608,85.80662975061477 -2020-01-19,104.23724044896827,107.7134183125539,106.91548022127935,92.34633554494728,85.30636871575335 -2020-01-20,101.23830237874272,106.03818624939339,105.3622783458126,91.7194043954283,84.35979076208284 -2020-01-21,98.4231254991102,103.37491690967214,102.63051194283759,89.47215088981821,83.05556801640444 -2020-01-22,99.26769644791051,106.81770930398106,104.66715437375682,90.63885249529275,83.71422198671189 -2020-01-23,95.507888445166,103.98336481000337,102.00731667558061,93.87052021707112,83.34543927750003 -2020-01-24,96.13164569991768,104.44431770978217,100.94935842758781,95.94295071950162,84.93157073772825 -2020-01-25,97.70057636464155,104.31823709066772,103.45362452796701,93.93277332325557,85.84691820052592 -2020-01-26,102.02960436019237,106.11519445812453,105.34604166793069,95.0906844021145,85.98967319365751 -2020-01-27,98.91634607839458,103.99045747203684,101.73157641479378,94.9754710140004,83.83193409086245 -2020-01-28,102.03208276941147,105.1571296994273,103.12765286337368,97.14603952330822,82.84150103118935 -2020-01-29,102.54726328587131,107.52960803021246,102.17595471616285,97.75296629281756,83.53560344128935 -2020-01-30,104.2020136623901,106.88285730445793,100.878968505046,98.72890235809103,84.18596113936239 -2020-01-31,104.77615214457177,107.86214447867619,100.62835993423307,99.35785635255947,84.89355920412216 -2020-02-01,103.3315996411719,109.73406892592246,101.4295434662693,97.31767585756818,85.6873336235697 -2020-02-02,101.36895613716112,109.54789063250206,102.12798531494167,95.69078235700813,86.8277708976018 -2020-02-03,102.2565044925412,111.54466238631674,105.81729851659452,96.04828229818688,86.27125876471624 -2020-02-04,100.4884591353818,108.93471331908013,103.97266568683432,96.0131037595259,86.24955237996494 -2020-02-05,102.20115162365965,110.2934925890537,107.23724419625718,96.31064293522151,91.18440310168825 -2020-02-06,103.53113133395895,109.9872884814707,106.22943832040544,97.24162165393385,91.04489186302574 -2020-02-07,105.06132324324851,111.90791607885839,107.57363310306715,96.28167239241071,88.75998315802806 -2020-02-08,104.17562442777992,112.65632318913347,107.83121469651516,94.0749916947767,88.65985857621368 -2020-02-09,105.03052624016695,111.92152059780022,108.1568221357716,94.27778943319336,86.91595610598087 -2020-02-10,105.83461380011971,113.4577228345186,110.66891056694688,96.71978916792415,85.6086747026225 -2020-02-11,103.90244312270518,112.8829135070045,110.3821958960654,97.39064662349112,91.62897476241108 -2020-02-12,105.14073333974294,115.69580671796555,113.46301798951914,99.42003066366048,92.12745067641903 -2020-02-13,106.7892761391827,115.72987537328055,113.8964999318468,98.80366336706061,92.36790204330704 -2020-02-14,111.78628753264455,116.47544832379388,117.44758347781598,96.89051151221985,91.99851332198313 -2020-02-15,114.27677681248336,118.44044459745152,117.73157249746606,96.13375882217254,93.41750905848478 -2020-02-16,112.66463550353907,117.67929840353912,116.84428687950839,94.6614854090199,96.58815803743347 -2020-02-17,114.14937367542375,115.40303593791434,116.86928190352883,93.45532662329433,97.83224747895584 -2020-02-18,112.39713256780404,114.01508598052348,116.3580013072454,94.65287244956589,95.67330919382353 -2020-02-19,111.70139119123932,112.7883373569549,114.5943092097602,97.4660870859542,96.72880554362185 -2020-02-20,108.940390669737,112.35572812324956,116.44957208832662,99.25739235336755,94.32444935995295 -2020-02-21,107.93980738330767,113.70657375789665,115.55095031509907,100.07362732740373,95.8319946557911 -2020-02-22,105.99272238226041,112.2147273948449,109.23117798378384,97.11531858026513,94.02072328578184 -2020-02-23,103.40059871940561,112.95014310637168,106.42824850404506,95.82704901298183,93.62308219648483 -2020-02-24,106.43287095505475,112.99268512223301,109.37580420540894,96.57819024714594,92.6587352933688 -2020-02-25,107.46974789785328,114.12483368806983,109.44692532953478,96.99711803522717,92.31527416229855 -2020-02-26,107.76747653019014,115.46619367438147,112.39642498279538,95.28346075148409,96.01703448536479 -2020-02-27,103.61392666928364,112.14191367807128,110.1774927046277,94.79571456056618,94.03202262418556 -2020-02-28,103.23444617114288,111.10481288593081,108.78244792538125,96.0548133511123,94.72035096650409 -2020-02-29,101.85541993844778,111.53314608308172,108.82728479554247,97.46203464679056,96.07055049934333 -2020-03-01,100.2175941302178,109.42518636537748,108.35373754235964,98.14962070237442,95.84845788152693 -2020-03-02,100.50286843153596,111.67916856909098,108.6007173106436,99.5231937717672,96.06216263359755 -2020-03-03,100.11556796554235,113.17044640164926,110.22760928031512,101.40007701348337,99.03049261212539 -2020-03-04,100.20768202627255,114.38605275299795,110.34762327480148,102.22877735732179,99.13421050970585 -2020-03-05,100.45218080589142,115.59460655671181,109.79927931800117,106.409851273349,98.27832414754826 -2020-03-06,98.06304782044461,115.62345847138853,109.90238249241754,107.41073873640796,99.437183230846 -2020-03-07,98.08806023943437,114.20363044711594,109.50241647104323,105.88060061203268,100.81581956592056 -2020-03-08,97.8486126839217,112.70274280245347,108.37734650148816,106.41202059541119,99.665487256608 -2020-03-09,96.28847370966275,111.87736952082436,107.71981703957945,105.05554693992825,98.2901438407454 -2020-03-10,96.78349287987876,110.00599202698751,105.26761220474819,103.23185265630958,97.25567698197149 -2020-03-11,97.4336993546488,112.88068048600456,107.90089566169094,103.7160857544284,97.91762205306081 -2020-03-12,95.52881235771679,111.3463212577275,106.05805684542622,103.74447627424341,95.99180867274916 -2020-03-13,96.56882839805486,114.67221825926251,107.72231809986019,105.31059892329975,98.09641647619289 -2020-03-14,95.84220463095569,114.4762059961862,107.3654524907821,105.3888526746569,96.63914771852387 -2020-03-15,95.93710796346011,115.41068244743549,109.83295225281688,107.76663937243707,101.28253245266734 -2020-03-16,94.51273368552945,115.6903756484283,109.56893500244954,112.06401698677229,100.52670592062537 -2020-03-17,92.97270114555745,113.42167812599943,104.95574149985296,109.91396750640403,97.98698295712802 -2020-03-18,93.29883799048257,114.29432665794982,108.03701337056644,112.4912681000954,97.86829584923026 -2020-03-19,91.66906569718421,113.74060425164285,105.22305296808688,115.74603168726736,100.17075140872038 -2020-03-20,90.85472194933512,110.29086593359432,105.41250831030555,115.0094622419175,101.99618426366317 -2020-03-21,88.00292225224918,106.96276135897294,102.78179869403792,113.92160474508033,100.12387857801532 -2020-03-22,89.14317656692594,106.34005351456821,102.9267478575353,114.35516453540453,101.2834083766433 -2020-03-23,90.45646102635372,105.76651371062724,101.30081481386561,117.06961988761444,102.39332315097629 -2020-03-24,89.14757973797117,107.07623943384064,101.39926188663337,119.70970018148081,103.04437090227026 -2020-03-25,92.866369186299,112.92569092480625,105.12628105175533,123.94913576965372,106.43969841676075 -2020-03-26,95.45480053514322,113.61295896033738,107.56919604142725,127.36552873627593,104.26123855724583 -2020-03-27,93.24357272363727,108.50212056512245,104.20842904588368,127.56504666342235,106.2067265734938 -2020-03-28,93.42837184332883,111.21529365449791,103.52844244141144,123.85732094891651,105.70907130068541 -2020-03-29,94.19273860294713,111.83999110175584,101.36444364525681,123.59769976177219,103.09740386459416 -2020-03-30,95.50140145340988,113.5532187925439,101.37666159797138,122.91242513712564,101.31117308922187 -2020-03-31,95.42943328552408,115.08297889259866,100.63987868290299,124.22135693018157,100.65085747260605 -2020-04-01,93.96387916838465,113.71097758531488,98.18609625540789,122.18187092767,97.61503730280822 -2020-04-02,97.70312687736016,116.97640150073092,100.09369835940964,124.07510388785798,98.62393810531506 -2020-04-03,97.32018983294579,117.72336212636525,101.21479620522705,123.10532721144905,97.59353274800812 -2020-04-04,96.8334880168981,113.48276548201723,97.54193300952208,125.14408941364938,100.19255297630762 -2020-04-05,96.39960397692153,114.10186634684342,98.00798286449746,132.55270897308742,103.61443273008722 -2020-04-06,96.20117957648931,112.42095862716319,95.3130193554209,132.38949243299982,101.739510726091 -2020-04-07,93.51282913169666,109.22377495463915,91.78939297578651,135.11540001667285,102.94440966861028 -2020-04-08,93.54467467728189,111.597569772127,92.74598924627333,133.53524238516343,105.9548700602472 -2020-04-09,94.59969083646423,110.8651491876264,92.72646716280937,131.47027977887012,103.00632108273078 -2020-04-10,96.3993137748166,115.40457985491028,93.35839687886211,134.02424775818793,102.9204679451051 -2020-04-11,95.50834193187421,113.72270003067307,91.4233690426151,133.46367285280263,100.84993985190751 -2020-04-12,96.07271404491378,114.15210792340547,91.53337405810419,131.42598348203217,99.6081143114906 -2020-04-13,97.57220085629498,116.25673976400302,91.68167384985468,132.31977683257125,101.52568281617589 -2020-04-14,94.36323440423841,114.5240675325158,89.11658133886365,132.5514254665112,99.4244719305536 -2020-04-15,91.00412408714624,109.04898627432284,86.14080782439811,131.32731149610447,96.4755539132202 -2020-04-16,92.21191770028,107.51314840381254,86.06594542147657,128.36503840869486,94.88610930245518 -2020-04-17,92.34543817346096,106.33926329209767,85.32753773251291,130.56968152135505,94.09714565463965 -2020-04-18,93.9350587726926,105.94275508372412,86.41750734092976,134.60620030722913,90.7155165607341 -2020-04-19,92.48489752383288,105.70891764127141,85.58936452971336,135.152761464667,89.58254173920326 -2020-04-20,92.6913050282193,105.67676196838724,86.98607937622094,136.17255577829434,90.48471047199305 -2020-04-21,91.9741020521131,104.40614442799881,85.81684194902614,136.6835755481118,89.6003848806391 -2020-04-22,92.55312503785696,107.99840629322479,88.25605756116963,137.0893860412214,92.29060190341868 -2020-04-23,91.84402822534508,104.313904140197,85.60852539996013,131.09180609389676,90.22952509918542 -2020-04-24,91.92378264209793,106.91228818669309,86.90934282074129,131.28378168948876,92.04167848543871 -2020-04-25,87.90462409309104,104.03810600405372,85.28289556007756,126.22243124626343,92.4625650836715 -2020-04-26,88.54368471382082,103.9875968155225,86.25129835416507,131.96828402141796,93.86941426707992 -2020-04-27,89.02752410475439,103.7402272394674,85.43488514064724,133.98981099552458,92.67744758283202 -2020-04-28,89.19946525095999,103.20976981290954,85.88337479105445,134.92990391204108,94.64721766736147 -2020-04-29,88.33420075001227,102.14797402507236,84.1103620113346,133.17862769736456,94.70975501672707 -2020-04-30,89.71572822971498,101.95733858485607,85.56677479825187,137.16058216511783,96.36302400606426 -2020-05-01,93.12814986128191,103.58154585360609,86.10982626859898,133.6624998839245,99.11612198615236 -2020-05-02,94.39351182707338,104.52147352577539,87.25514428403682,131.49188322099377,103.63745075149535 -2020-05-03,94.6846615519434,104.9477789766221,88.3651483811011,133.07235019478156,104.57881622745316 -2020-05-04,93.23508703234674,104.56727609231228,89.86954069273324,136.47659453527373,108.24086040906965 -2020-05-05,92.32843936085219,102.41482681196865,88.63007263103685,135.93183609919018,109.90993354815639 -2020-05-06,89.2493496822887,102.29796729358162,87.21791982947504,134.04578811668026,107.04333574576566 -2020-05-07,86.34007526686538,101.20300409492803,85.77445931911065,129.84813648601718,103.19977059177981 -2020-05-08,85.80341151196372,103.21132900100001,85.99390975928611,126.49455458674186,102.38183944973022 -2020-05-09,85.37830075148307,98.91460437873775,84.31158716604833,124.95782078666262,102.8111889313289 -2020-05-10,88.57820609282089,103.13657987141764,86.82689833550617,124.12959214052644,108.70187818531404 -2020-05-11,88.72740452351906,103.31553006808667,86.95014004000264,124.72641923282382,108.62521091382058 -2020-05-12,87.75377692008264,101.75185864314736,86.0066156563893,122.93187915127406,106.52319867008744 -2020-05-13,87.98444701304622,101.60485628733453,87.76017228337824,117.18106093822828,107.88727592772034 -2020-05-14,90.22116268677071,100.44028952669586,87.90175187618934,116.64427856369271,105.20164291950591 -2020-05-15,88.86276207068188,97.82436483146601,88.44751496425529,118.24686175870029,107.65706275283912 -2020-05-16,90.1897895736331,97.30436643144658,88.2227340033729,119.49745428997076,105.59925745105463 -2020-05-17,91.52098870169057,98.01045620129526,88.62082944229395,121.55073892366633,107.17138674233806 -2020-05-18,90.90602928088951,99.20737104536482,87.60312332283434,122.92757815439495,108.58449270107226 -2020-05-19,90.38868928333869,99.3097076016171,86.03700031422058,124.77935209170292,108.36903831840108 -2020-05-20,89.48891820443629,100.14111095948724,85.22017278716298,121.35403511431493,104.56546939839448 -2020-05-21,90.61828672756323,99.23012636905655,87.31797451865263,117.07774801245803,107.39211268649828 -2020-05-22,91.04603691175177,99.4563684058345,86.97877014143799,118.05895250521947,107.59025970131162 -2020-05-23,93.10058623497916,101.22517902527012,88.62238557323775,118.18008074351711,108.17875192408744 -2020-05-24,93.72026734049726,99.26041534092683,86.63069147656192,119.3703607974405,108.42342711427997 -2020-05-25,93.42226797578454,99.1010622690143,86.88011372153711,118.18417009996305,106.67127476928391 -2020-05-26,93.83490547416146,98.05801617785752,87.15152943236842,114.40450641338833,107.99002276202236 -2020-05-27,94.76874619560964,99.13472012240203,89.04577671508486,118.65857069903423,111.35971198737293 -2020-05-28,91.32698199168449,94.83810279358596,85.42982640007158,116.98896481550788,110.82115097377405 -2020-05-29,90.04704499962345,94.19455327147269,83.88597933019271,115.12768575348137,107.2041024992458 -2020-05-30,88.42937920013702,91.22515163170566,81.13836505587358,116.28389178183855,104.737268751028 -2020-05-31,93.12919447586587,95.29437737275067,84.62592299081993,116.50371883713662,107.63139894965622 -2020-06-01,92.10358481895213,94.75985191233937,86.89412902842398,116.49599739787182,110.0655211481726 -2020-06-02,90.85433459645157,93.84663893925436,88.09506314298497,115.03811576758874,113.39721389251294 -2020-06-03,92.18580905258968,94.08894624311773,89.47412982664356,117.67326944200673,115.66448051122673 -2020-06-04,89.33685180868886,91.10993263545564,86.90990861977129,116.22182661064508,115.69812910399449 -2020-06-05,89.69902537541246,89.66331867621123,86.94514478825857,117.4477441004014,117.07173516271416 -2020-06-06,91.68277543451006,92.1513683996953,89.27826678377451,118.47381028916382,114.64594193435514 -2020-06-07,92.51638905317995,93.0441402256447,90.3133014673642,116.12944608522477,112.28028215728226 -2020-06-08,94.51132622740265,94.42921789903292,92.4992659859538,117.12656672669519,113.2686099216258 -2020-06-09,96.33215173853816,95.04040484866836,93.62540135262392,116.71664448941766,112.75404370994482 -2020-06-10,95.78465322243223,94.99776722364977,92.83605567840907,119.32070241478728,111.31789009218693 -2020-06-11,95.47455668133325,94.21975879616046,94.17788295802265,119.86393756168023,113.62476022866252 -2020-06-12,92.68562820442952,92.68618931273367,93.53506815166355,119.32241979323355,115.21214008854541 -2020-06-13,91.77306646304223,93.94621859460479,96.50865343859701,119.09297700020247,114.67682387606604 -2020-06-14,94.48658535732972,98.04370923137904,98.79147702758047,119.6477994645264,115.34224349615417 -2020-06-15,91.99317664391404,94.98119441949748,95.18831726669634,116.56596121657101,113.62395261755832 -2020-06-16,92.47009661595258,97.46321310429938,95.20980893060029,119.24229483035916,114.13298358316297 -2020-06-17,92.42485336142808,98.40402008823035,94.20872450410153,120.1374869784126,114.70121644683799 -2020-06-18,93.38136098363431,99.55845141571798,98.10662994530637,119.70343707555715,114.26241310058391 -2020-06-19,92.26425689674245,97.97042412506568,96.19703019075044,121.73259988066967,117.17963487320198 -2020-06-20,91.25719886827487,96.09215423637228,95.6268338869178,119.97533967375166,117.82601719059325 -2020-06-21,91.67319140508067,94.35277139422686,97.05082002819314,124.11167269014116,117.42445249399005 -2020-06-22,91.008190882042,94.29259631624501,97.18951258306606,125.60984052276292,122.05024089547194 -2020-06-23,90.73162189808211,93.05055819771798,94.82753774244054,123.30301791161278,121.07091992221972 -2020-06-24,94.03345227088363,94.76621419180971,97.2754961278081,124.56589852251507,125.00096491455703 -2020-06-25,98.83279498989133,97.46721943732653,99.8734188757296,128.7295702262037,128.82037294328333 -2020-06-26,102.53251816786249,100.86893614480452,102.41360056702797,131.7960362505051,133.39997646417228 -2020-06-27,104.2663073768409,102.82974247633452,105.40164196710006,135.84123752634005,138.58377951316933 -2020-06-28,105.67121292373791,103.59089630712721,106.5432588231789,139.531615111508,137.7912363768761 -2020-06-29,106.50321206062317,103.6168443092581,106.97419334212348,143.17060095519872,139.26412809114336 -2020-06-30,106.65537657344844,101.74495670939648,107.31523767948543,144.73857924291673,145.01394188968843 -2020-07-01,106.05217988913655,101.6969611679507,107.42774004317414,149.01671610883298,145.65914636353952 -2020-07-02,106.69702312238125,103.0491120336826,108.58073519094556,148.39430448943273,146.5507082468097 -2020-07-03,109.04143903894372,103.16002546753154,109.83450096218925,147.14841807609182,150.0834136862872 -2020-07-04,105.77414828436109,100.20959234807852,107.76087294311627,150.13366321741717,149.46811271108416 -2020-07-05,104.65251965641231,102.19400469322338,106.17311705422125,143.88065666997932,149.35135350851198 -2020-07-06,103.65402062533846,100.05735009092692,105.8553912708087,144.00790730582497,147.4041167327322 -2020-07-07,101.05167236354708,99.58147938362781,105.48406882468724,143.2059534965816,151.82651840982686 -2020-07-08,98.93952003949323,95.99027279664483,102.09418908021755,141.55543249309704,150.8733827776281 -2020-07-09,98.51163398995962,96.21663060992333,100.38163840121143,145.14118181663966,151.24323926169026 -2020-07-10,100.76222369264696,98.26068651884763,102.83348198712613,148.0107259540656,154.21326813301565 -2020-07-11,102.10784896734799,101.07971771378234,104.9102469999083,151.20917762149077,155.67975553085992 -2020-07-12,105.09984981043883,102.2126064702097,109.15353472598636,152.69617348048973,153.21539127819273 -2020-07-13,105.42167499160007,101.47393181995032,110.19618967645567,150.99331794704077,151.7473628622944 -2020-07-14,101.49041288704368,98.20578920004041,103.60204175324105,144.11720400372076,150.54731261196073 -2020-07-15,103.13618256733497,99.95238179475362,103.78228867622879,144.69939254627445,151.26561265469616 -2020-07-16,100.79836324842752,100.5483806894037,104.28736599598874,143.95101140667933,151.06832674209193 -2020-07-17,101.26885558470222,97.98063447707676,103.08959919823857,141.5869163066717,147.34522392685662 -2020-07-18,100.75015565384311,100.18008479855042,104.71848264188779,140.71615655450486,149.25656847537743 -2020-07-19,103.62023772773182,103.53656523537882,107.50687091883651,140.62598343778262,152.52837841516867 -2020-07-20,104.48750926382691,105.50394631044367,109.64231340030557,144.30342136921183,152.64813153526057 -2020-07-21,107.29277891383413,107.82217085539855,114.84367156943594,144.23390210758475,159.03170263178436 -2020-07-22,107.7711135011526,107.19396628905025,114.09303991341912,143.28876652491627,160.00310596523585 -2020-07-23,108.95193090278153,107.17603037333612,114.60087821379594,149.4128690837624,166.8523907722432 -2020-07-24,109.9571734970453,107.96467438101276,115.59982756725714,151.6829454108057,164.73818094718334 -2020-07-25,109.44614389668868,105.07895351069129,114.7446359471878,152.86886782014918,162.9904691468566 -2020-07-26,112.94620435439641,105.6290853724818,114.35326471194243,154.23331095388568,167.0591111947445 -2020-07-27,116.80654420989065,107.50166299364736,118.44008636939756,155.88377715629977,168.4261757401393 -2020-07-28,118.92929381446054,109.90920064302165,118.02696817264227,161.01644905520936,174.57179110933637 -2020-07-29,117.50080314057907,109.64568363999977,118.12405318717887,161.60966985295,172.78500599950814 -2020-07-30,115.98122707954785,108.65222397286252,118.89581405423301,163.0287321799663,171.74242395156293 -2020-07-31,117.82926988504234,105.48234557718148,120.06403269715949,157.69205580909278,169.4296016713244 -2020-08-01,115.24958550622242,101.95289826435456,119.180594727888,155.1405866575073,168.9620657172368 -2020-08-02,115.19905872836141,102.6526723513153,119.65386129007263,151.66499261604247,171.51336165320456 -2020-08-03,114.11905184530025,99.733437106335,117.16302857454866,154.91347076961773,174.06254588172513 -2020-08-04,113.38035398182495,98.81963340267792,115.95635450187139,160.5458402679122,176.25896374418377 -2020-08-05,114.41221015845258,100.93862916676018,117.81285435046271,160.77214286317374,176.5642520352319 -2020-08-06,114.30557504342045,100.85515433205201,118.88163056687276,161.15218767013303,179.2433000640327 -2020-08-07,114.17820066515803,100.9257707934031,115.8081344784627,163.48124578210113,180.5526697958201 -2020-08-08,116.51431090533309,98.23229863214917,118.69675118679201,163.51074171366923,184.66064280006353 -2020-08-09,114.14928842816734,97.73136998251648,115.86660371715179,160.65963605345735,189.67804808864898 -2020-08-10,113.77103767599796,97.84308540510213,117.1129002283467,162.40819472789096,190.88750750444302 -2020-08-11,114.65836347773563,101.77091918017933,119.3751517090764,164.46551134704788,196.44557401964133 -2020-08-12,117.25084984081991,105.14346860556516,123.14675436291742,162.79669942085488,203.71594677287624 -2020-08-13,114.62127452010265,103.98486640068232,120.28185747336599,161.52261947299672,203.56731080512884 -2020-08-14,115.41527302658447,105.1528569752224,123.74677334247441,163.92721353501142,204.32856712588156 -2020-08-15,117.69838947964371,108.43292652266823,124.40718193041627,167.00345591093725,209.00561113619443 -2020-08-16,117.05678345131292,110.1884813015368,124.75480288152949,167.75976891684022,208.91450843350316 -2020-08-17,117.15178455452151,108.56509813122035,121.74193146525798,172.08040331046192,206.10466173877583 -2020-08-18,114.88749165600305,103.79593956181851,117.59805921400243,165.7788575144907,208.86048790921947 -2020-08-19,117.26524363922496,104.3165526668622,122.32903887935997,170.28998112971118,210.26581361761555 -2020-08-20,111.46200495726902,104.15347062419009,117.58484326847443,163.17869174775404,210.60494911640504 -2020-08-21,116.95653260320735,109.84389421879403,123.51815767593189,168.23328309938458,218.59588383759706 -2020-08-22,118.79024491346246,111.52981010019136,125.30391205799936,169.0706180102877,216.87141479231107 -2020-08-23,118.18281050976003,108.47359523915121,123.50660493789223,165.0107377962641,210.46143104162934 -2020-08-24,118.66711008471623,110.98013659105015,126.40656841531978,161.25116703249213,206.7612941485543 -2020-08-25,120.9592167484016,110.96294737820381,127.07541565302228,163.49115377185782,204.27451879237998 -2020-08-26,121.27461928823458,109.0908476732208,125.3757471497289,163.9883794146265,197.95040433934392 -2020-08-27,122.40362528542592,109.81010880304763,127.13911950157603,165.37175778298743,203.95214165524703 -2020-08-28,122.77138594392218,109.40678364077381,127.34787704370807,167.16261015455086,204.71575243794803 -2020-08-29,122.93244168116013,108.44935324965124,125.90043481118049,162.43077967305518,209.80223660743326 -2020-08-30,119.9356835107412,105.56420081377156,122.12122706436031,163.60156750025845,207.40327454024464 -2020-08-31,122.98862884559276,106.46741527517169,124.31467461880563,162.16651983232788,216.3707073929443 -2020-09-01,120.12889970663937,105.24366108084521,123.60201730224179,162.68671128376303,215.01513193420502 -2020-09-02,119.87705967421032,105.19265334892569,123.27437853526048,165.6114835738612,224.5730088520732 -2020-09-03,118.60038804612675,102.38795025492063,121.27886452631138,172.6315922332319,222.17918892056946 -2020-09-04,122.54768799737019,107.26336661494378,124.48444585120365,176.8796874464401,232.45053213109023 -2020-09-05,121.67973684511999,106.45798742029054,122.83456341487371,172.96550907625686,228.05321882079755 -2020-09-06,118.76200066320001,104.76091153831678,119.62438858334099,172.38073491956933,219.9755985916791 -2020-09-07,119.60730205333586,106.56746997558896,117.75905216805175,173.86578119239852,225.6408411676868 -2020-09-08,116.77346631347163,107.3839103091848,117.66226002988462,171.27185969062722,224.426851877459 -2020-09-09,118.13580910602444,108.41578596504118,119.5564301635637,169.18165292254992,225.47848050829785 -2020-09-10,114.85466925127304,106.17444684445985,115.80369338390264,165.22838534256715,227.82719988715291 -2020-09-11,117.41893912706107,108.7954321964254,116.43665720496443,165.40503935870413,234.25209838203415 -2020-09-12,117.81045378550097,112.692246074373,118.94775629898176,167.3368568310687,235.00672710485014 -2020-09-13,118.18400949099797,112.73720300863839,120.25760059985483,170.7370429727248,233.05991904771653 -2020-09-14,115.09649099162533,107.75912528811955,117.61169941462097,165.29849145462464,220.23800882129945 -2020-09-15,116.04852039025421,112.25854040666863,120.0633491431383,169.45216547271048,223.3793709914132 -2020-09-16,115.87702460600677,113.65612267645385,120.1912234952182,170.64065435839916,225.40170380299318 -2020-09-17,114.38663569439922,114.28384881376124,119.59342785158765,168.02859599561793,226.72999767425156 -2020-09-18,112.38837341879176,112.97313127587773,118.19309969054663,170.69184333408154,228.66709239685625 -2020-09-19,112.38831282177114,114.33296067892711,120.95600647368695,173.32178558101813,230.35866566383496 -2020-09-20,109.49580431488278,110.57466310289004,117.59582954723429,169.5413589195379,226.6480163391747 -2020-09-21,109.67461088826317,111.5771006179345,118.04423913826739,171.48284744744296,227.8940891417235 -2020-09-22,105.39627551478854,107.07319511771784,114.00312254843993,165.21986390562137,226.2058226294319 -2020-09-23,108.67568402165271,111.30740453349223,117.04045600361914,171.94783198189458,231.04540209868097 -2020-09-24,107.99736055479494,109.88564336558264,115.70137185615137,170.11662112333582,230.66328465934197 -2020-09-25,108.39819075803052,110.21514780870167,116.71670868881417,174.34235918544834,236.3657971170344 -2020-09-26,105.23318320610207,103.98150770548638,114.05262141562808,167.5681652289455,231.0255546228341 -2020-09-27,102.8231042238035,99.67542876799584,111.87315269148972,168.2965308437853,226.99109648158085 -2020-09-28,97.54613290436176,95.35256075763952,108.11812475832792,160.98813228375312,222.90931052955244 -2020-09-29,97.5650376486228,96.18848649211638,108.72049906589103,158.4048350538754,227.48770980263947 -2020-09-30,97.30448116195305,96.00550438868756,107.2305015601996,156.7945285876098,222.98709252812122 -2020-10-01,97.01656472597887,98.18808882656676,106.22377800576363,152.30511229105724,228.0106910809347 -2020-10-02,96.65891554805572,97.0314584373962,107.01962766139381,150.48713855313775,235.02899011431714 -2020-10-03,98.01779727618258,97.344797297839,110.82129481684578,149.83400037477125,239.35745529524044 -2020-10-04,98.65352648213603,99.63140492323882,114.47758731145967,151.17427718911543,238.08485838741507 -2020-10-05,99.61041120350889,99.37903387130876,117.85263932111711,152.32692583756872,237.83645477960425 -2020-10-06,100.02813824214188,97.79411266035522,115.830155290239,155.29335742587904,235.36921610927516 -2020-10-07,97.98374015900616,97.17950316272596,116.38090178712694,157.04369075584438,239.84573545203935 -2020-10-08,96.5496590458056,94.24510955584418,116.5445919599047,155.3104238995113,237.26210684107053 -2020-10-09,99.16266901267576,96.81294438810617,119.88035339714287,163.3290047691125,239.08743619505 -2020-10-10,101.05239336239553,98.21781043830117,121.99545542135513,169.1551180271324,244.44249973330173 -2020-10-11,102.19084227081194,100.53198944097028,123.20516332406896,167.50620373991666,240.42653945648436 -2020-10-12,98.22306298659731,100.78800905974181,119.63556254137211,165.52052397698685,237.162676371279 -2020-10-13,98.87606339341868,102.4673225637182,122.16267333343652,164.6994064163077,237.33233257630295 -2020-10-14,99.48430959120206,102.58118057921766,125.12351917693383,166.9490647179332,242.07550935578973 -2020-10-15,100.85297813741781,105.32502081815326,127.5459506113765,164.19775671723025,244.55478134496715 -2020-10-16,99.58957834340222,103.64381360807633,127.06466463171458,167.4438247931588,245.0066990297934 -2020-10-17,100.2545044551018,106.68506094625505,129.38876977385087,176.8674560314565,251.89616281882823 -2020-10-18,96.77414200950615,105.2785562250906,127.52083555903278,179.87064950522634,254.4905341321989 -2020-10-19,96.55454978959264,103.30797189235898,126.11340182879974,176.35292228448068,250.03195002806763 -2020-10-20,97.73942611401934,106.69628815490324,129.14271071650882,173.9854095553875,253.18829501386082 -2020-10-21,100.12745851658589,107.62992864112275,130.7240202042581,175.10348342790286,251.1227930852472 -2020-10-22,101.47573636491892,108.49694214335155,132.63881331384428,173.0496037620392,249.4884763661077 -2020-10-23,102.99255859594918,109.0931627204008,136.7799242864398,172.94565116945105,251.8748202416496 -2020-10-24,104.96505417944888,108.38460181673122,134.40249832054894,167.9535542015389,256.19404693840744 -2020-10-25,103.8590197498624,111.58406206419586,134.50968278777788,169.03193847121395,264.43498437763606 -2020-10-26,108.07796818703753,118.08233417560817,142.14441201119058,175.6610539098122,273.6903738993115 -2020-10-27,109.81448171194647,118.52297059142482,141.83571693675262,176.11967810007704,273.5852023771154 -2020-10-28,108.87396841586235,119.03360298812866,143.3968919558575,176.64461735556657,281.50990111820204 -2020-10-29,106.44239969322872,116.88592941993036,139.72159937697344,169.0580757089923,276.82459926453464 -2020-10-30,106.23643885111524,119.29600333514895,141.98919471788486,166.613165749615,286.5113901839453 -2020-10-31,108.8839238248789,122.4114858977255,144.600720811591,165.12570784352377,286.1001738097279 -2020-11-01,111.3093114349305,127.65888199775944,151.43095262813284,166.0021152205128,283.82340578553806 -2020-11-02,111.6786052979815,124.77648167846249,150.9161814341232,165.1484357184626,280.57566997309567 -2020-11-03,108.17255855927306,122.9942901454719,147.08043782084107,160.11824775642313,262.09140226102147 -2020-11-04,108.1671176822754,126.14721385975241,151.8580293060942,159.97687665342858,260.75693062779146 -2020-11-05,109.23532097768354,125.26545630481753,152.68438807016022,162.52786907557325,267.86143127899703 -2020-11-06,109.0711313022474,124.81398308148744,150.66815087037935,159.7002659503533,265.3993879213326 -2020-11-07,109.92704672445319,127.17281805879068,150.80140809600385,164.81854434513437,266.7164199217536 -2020-11-08,109.93503338052444,125.86746497199674,145.45930640402696,166.70170798355485,269.9028065116813 -2020-11-09,109.37144552776795,125.5811552765347,146.04015636199335,161.8014104766744,265.630499661182 -2020-11-10,111.16352966941099,124.81660580856999,147.26489690108866,158.11986255827296,267.246921006446 -2020-11-11,111.13987076291949,121.9632184463559,148.14622314208953,155.66808106410102,262.05644148105426 -2020-11-12,111.6412656421836,124.39283380907378,147.72607381559246,156.3425444334848,265.04444208857 -2020-11-13,113.24467082107772,126.00131258462139,148.72860284644437,154.6443401906643,265.8692496702949 -2020-11-14,110.87301138092451,118.94169105536187,144.9083139372242,155.36658057325522,251.99347732290747 -2020-11-15,108.6894091165152,118.39624272614331,147.3873488186323,155.3613311818475,248.55100856205718 -2020-11-16,108.34617552719281,120.50176772233938,147.0837312941472,153.33911997985842,246.08018842189784 -2020-11-17,106.33455743463827,119.18981232378843,148.45805903588422,153.9593076244795,244.77222491239417 -2020-11-18,105.76713198695158,116.12602066164592,148.31525480415556,153.1901362487899,243.04068723829047 -2020-11-19,112.57453554817991,121.89488343502197,153.87674035638076,154.9334432573914,252.5083180342468 -2020-11-20,112.88585024876406,119.67031500492011,154.78676444960965,152.87064662996207,260.3873286718171 -2020-11-21,115.38073730548565,120.79984639219975,159.42817312295628,154.313778537616,266.6953503615264 -2020-11-22,116.55700485938378,120.24476133803263,158.51221963834544,157.3782632829298,266.2889808790774 -2020-11-23,115.67432180264068,118.00990387939487,157.7303742426949,162.9566300537024,262.3542147119855 -2020-11-24,115.78819040497726,120.513686672245,159.0601080053812,165.04627486814007,258.8450544850883 -2020-11-25,116.83794309952134,120.99940617717726,162.01038739696983,169.4693021870772,273.5815825590175 -2020-11-26,118.25082573172234,122.62990234684266,164.1786420318062,169.2465831120133,276.3876000319859 -2020-11-27,117.61132161141128,122.50452082799457,166.61295270481304,166.29422910909236,281.527049767128 -2020-11-28,120.76828172637875,124.64348836983932,165.10508947317533,165.2009028838505,288.9685613803968 -2020-11-29,120.77343113801169,122.91268982086116,163.13292922205343,167.36272402932983,292.0753461610906 -2020-11-30,120.25668460669299,121.9444716354199,161.5376445371678,164.07398218962743,299.0545890008486 -2020-12-01,119.5415887712841,123.60036949006587,165.2965431361932,167.87121827985126,299.18849350715544 -2020-12-02,120.56661080685261,124.34366593671946,164.39896623709856,169.16839497482036,293.5884138048955 -2020-12-03,123.49078514618141,125.6739570009064,167.2489363366178,171.2567050211182,294.6029097350509 -2020-12-04,125.00155685783139,125.9426215325756,170.18981040962964,167.67833985590755,295.05188277622113 -2020-12-05,129.91144296158316,127.65096445321113,172.44701444066138,170.76647921323982,299.2345435395043 -2020-12-06,130.88741641389814,129.25973560164405,175.35614055971817,175.20684159444738,304.3657006710669 -2020-12-07,130.32130801698915,130.15624935896196,179.93800759349043,175.48094609974828,300.006361814289 -2020-12-08,133.27199416437566,132.04179742548564,177.65898963129376,178.90204353201295,299.1460375971875 -2020-12-09,133.09731905270192,132.59389599161923,178.36730033616823,181.5310674094613,298.01560849286403 -2020-12-10,134.52972855098514,133.14859935890982,181.23824813810742,184.4256921773186,294.93484349782204 -2020-12-11,137.51893249586652,134.2478360405532,185.4777056027113,187.03063778002755,307.50131345687794 -2020-12-12,136.9730756222879,133.25296566834677,184.62204969843594,185.67644797310828,311.2177110541257 -2020-12-13,132.61373927646267,128.32648592043935,176.88616985541557,186.51922123062096,318.06710518577506 -2020-12-14,132.40301801204518,127.92014310697732,176.7586445411746,190.56257805283522,314.0664666766768 -2020-12-15,133.10043532405052,130.2192344876897,179.6605034879332,192.27767789625142,321.82615816048326 -2020-12-16,125.97095407736998,126.64391550787522,172.1957084639322,182.79030725695742,317.7602210297908 -2020-12-17,129.49476286652592,128.92035527095948,177.6453145479024,190.20212643921263,330.75436503948737 -2020-12-18,133.80684876080977,133.33797625051756,182.81982708959504,186.8497008651324,331.3293364687496 -2020-12-19,131.61710769736962,135.9925933140736,182.72757332317647,187.44244722923324,335.1682895973631 -2020-12-20,131.79769289911226,139.46417313203588,183.3301088757674,188.92556201807795,332.2978263892973 -2020-12-21,128.38407160767682,135.76683045130648,179.34490266876955,185.73530601030265,324.59869559011946 -2020-12-22,124.83728663090608,133.02863754919142,172.36121578548207,186.46891671137573,322.73607656929795 -2020-12-23,121.26056799950334,129.82064737060233,166.98496724579124,185.72118079881164,327.9068444013451 -2020-12-24,116.77350646464852,126.71761892011313,162.50346631203075,186.12087302831924,326.65770292677763 -2020-12-25,115.07569045655308,124.8957361054519,158.93773310727482,188.79862263659282,326.2912300924644 -2020-12-26,119.50884713540992,128.2001421967924,161.77664866097058,185.45798596233683,317.0516042644404 -2020-12-27,115.78223449058567,125.9367067588932,159.64718932628188,178.58286544415378,318.0024069451796 -2020-12-28,114.72152731829215,125.43810407688198,162.18674654235386,181.74684664328882,317.8538757089632 -2020-12-29,112.734108423566,120.10651684408398,156.7259404259801,178.98535947364022,308.2712976704662 -2020-12-30,112.49453261479931,120.10257028740577,156.17898531271933,176.75127445654758,308.3861338311089 diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..614aca8 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1498 @@ +{ + "name": "QuantResearch_Opcode", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "devDependencies": { + "@commitlint/cli": "^19.1.0", + "@commitlint/config-conventional": "^19.1.0", + "husky": "^9.0.11" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/code-frame/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@commitlint/cli": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-19.1.0.tgz", + "integrity": "sha512-SYGm8HGbVzrlSYeB6oo6pG1Ec6bOMJcDsXgNGa4vgZQsPj6nJkcbTWlIRmtmIk0tHi0d5sCljGuQ+g/0NCPv7w==", + "dev": true, + "dependencies": { + "@commitlint/format": "^19.0.3", + "@commitlint/lint": "^19.1.0", + "@commitlint/load": "^19.1.0", + "@commitlint/read": "^19.0.3", + "@commitlint/types": "^19.0.3", + "execa": "^8.0.1", + "yargs": "^17.0.0" + }, + "bin": { + "commitlint": "cli.js" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/config-conventional": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-19.1.0.tgz", + "integrity": "sha512-KIKD2xrp6Uuk+dcZVj3++MlzIr/Su6zLE8crEDQCZNvWHNQSeeGbzOlNtsR32TUy6H3JbP7nWgduAHCaiGQ6EA==", + "dev": true, + "dependencies": { + "@commitlint/types": "^19.0.3", + "conventional-changelog-conventionalcommits": "^7.0.2" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/config-validator": { + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-19.0.3.tgz", + "integrity": "sha512-2D3r4PKjoo59zBc2auodrSCaUnCSALCx54yveOFwwP/i2kfEAQrygwOleFWswLqK0UL/F9r07MFi5ev2ohyM4Q==", + "dev": true, + "dependencies": { + "@commitlint/types": "^19.0.3", + "ajv": "^8.11.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/ensure": { + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-19.0.3.tgz", + "integrity": "sha512-SZEpa/VvBLoT+EFZVb91YWbmaZ/9rPH3ESrINOl0HD2kMYsjvl0tF7nMHh0EpTcv4+gTtZBAe1y/SS6/OhfZzQ==", + "dev": true, + "dependencies": { + "@commitlint/types": "^19.0.3", + "lodash.camelcase": "^4.3.0", + "lodash.kebabcase": "^4.1.1", + "lodash.snakecase": "^4.1.1", + "lodash.startcase": "^4.4.0", + "lodash.upperfirst": "^4.3.1" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/execute-rule": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-19.0.0.tgz", + "integrity": "sha512-mtsdpY1qyWgAO/iOK0L6gSGeR7GFcdW7tIjcNFxcWkfLDF5qVbPHKuGATFqRMsxcO8OUKNj0+3WOHB7EHm4Jdw==", + "dev": true, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/format": { + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-19.0.3.tgz", + "integrity": "sha512-QjjyGyoiVWzx1f5xOteKHNLFyhyweVifMgopozSgx1fGNrGV8+wp7k6n1t6StHdJ6maQJ+UUtO2TcEiBFRyR6Q==", + "dev": true, + "dependencies": { + "@commitlint/types": "^19.0.3", + "chalk": "^5.3.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/is-ignored": { + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-19.0.3.tgz", + "integrity": "sha512-MqDrxJaRSVSzCbPsV6iOKG/Lt52Y+PVwFVexqImmYYFhe51iVJjK2hRhOG2jUAGiUHk4jpdFr0cZPzcBkSzXDQ==", + "dev": true, + "dependencies": { + "@commitlint/types": "^19.0.3", + "semver": "^7.6.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/lint": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-19.1.0.tgz", + "integrity": "sha512-ESjaBmL/9cxm+eePyEr6SFlBUIYlYpI80n+Ltm7IA3MAcrmiP05UMhJdAD66sO8jvo8O4xdGn/1Mt2G5VzfZKw==", + "dev": true, + "dependencies": { + "@commitlint/is-ignored": "^19.0.3", + "@commitlint/parse": "^19.0.3", + "@commitlint/rules": "^19.0.3", + "@commitlint/types": "^19.0.3" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/load": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-19.1.0.tgz", + "integrity": "sha512-rWqnvNDpeshX8JfUC/qjpDkQB78qF+4uHcJmIRJMwvlj6zWce08SP/TPKN3GlNKgXhAawwcAPxXL9qOTTdiOBA==", + "dev": true, + "dependencies": { + "@commitlint/config-validator": "^19.0.3", + "@commitlint/execute-rule": "^19.0.0", + "@commitlint/resolve-extends": "^19.1.0", + "@commitlint/types": "^19.0.3", + "chalk": "^5.3.0", + "cosmiconfig": "^8.3.6", + "cosmiconfig-typescript-loader": "^5.0.0", + "lodash.isplainobject": "^4.0.6", + "lodash.merge": "^4.6.2", + "lodash.uniq": "^4.5.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/message": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-19.0.0.tgz", + "integrity": "sha512-c9czf6lU+9oF9gVVa2lmKaOARJvt4soRsVmbR7Njwp9FpbBgste5i7l/2l5o8MmbwGh4yE1snfnsy2qyA2r/Fw==", + "dev": true, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/parse": { + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-19.0.3.tgz", + "integrity": "sha512-Il+tNyOb8VDxN3P6XoBBwWJtKKGzHlitEuXA5BP6ir/3loWlsSqDr5aecl6hZcC/spjq4pHqNh0qPlfeWu38QA==", + "dev": true, + "dependencies": { + "@commitlint/types": "^19.0.3", + "conventional-changelog-angular": "^7.0.0", + "conventional-commits-parser": "^5.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/read": { + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-19.0.3.tgz", + "integrity": "sha512-b5AflTyAXkUx5qKw4TkjjcOccXZHql3JqMi522knTQktq2AubKXFz60Sws+K4FsefwPws6fGz9mqiI/NvsvxFA==", + "dev": true, + "dependencies": { + "@commitlint/top-level": "^19.0.0", + "@commitlint/types": "^19.0.3", + "git-raw-commits": "^4.0.0", + "minimist": "^1.2.8" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/resolve-extends": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-19.1.0.tgz", + "integrity": "sha512-z2riI+8G3CET5CPgXJPlzftH+RiWYLMYv4C9tSLdLXdr6pBNimSKukYP9MS27ejmscqCTVA4almdLh0ODD2KYg==", + "dev": true, + "dependencies": { + "@commitlint/config-validator": "^19.0.3", + "@commitlint/types": "^19.0.3", + "global-directory": "^4.0.1", + "import-meta-resolve": "^4.0.0", + "lodash.mergewith": "^4.6.2", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/rules": { + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-19.0.3.tgz", + "integrity": "sha512-TspKb9VB6svklxNCKKwxhELn7qhtY1rFF8ls58DcFd0F97XoG07xugPjjbVnLqmMkRjZDbDIwBKt9bddOfLaPw==", + "dev": true, + "dependencies": { + "@commitlint/ensure": "^19.0.3", + "@commitlint/message": "^19.0.0", + "@commitlint/to-lines": "^19.0.0", + "@commitlint/types": "^19.0.3", + "execa": "^8.0.1" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/to-lines": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-19.0.0.tgz", + "integrity": "sha512-vkxWo+VQU5wFhiP9Ub9Sre0FYe019JxFikrALVoD5UGa8/t3yOJEpEhxC5xKiENKKhUkTpEItMTRAjHw2SCpZw==", + "dev": true, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/top-level": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-19.0.0.tgz", + "integrity": "sha512-KKjShd6u1aMGNkCkaX4aG1jOGdn7f8ZI8TR1VEuNqUOjWTOdcDSsmglinglJ18JTjuBX5I1PtjrhQCRcixRVFQ==", + "dev": true, + "dependencies": { + "find-up": "^7.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/types": { + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-19.0.3.tgz", + "integrity": "sha512-tpyc+7i6bPG9mvaBbtKUeghfyZSDgWquIDfMgqYtTbmZ9Y9VzEm2je9EYcQ0aoz5o7NvGS+rcDec93yO08MHYA==", + "dev": true, + "dependencies": { + "@types/conventional-commits-parser": "^5.0.0", + "chalk": "^5.3.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@types/conventional-commits-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", + "integrity": "sha512-loB369iXNmAZglwWATL+WRe+CRMmmBPtpolYzIebFaX4YA3x+BEfLqhUAV9WanycKI3TG1IMr5bMJDajDKLlUQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "20.11.26", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.26.tgz", + "integrity": "sha512-YwOMmyhNnAWijOBQweOJnQPl068Oqd4K3OFbTc6AHJwzweUwwWG3GIFY74OKks2PJUDkQPeddOQES9mLn1CTEQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-ify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", + "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", + "dev": true + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/compare-func": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", + "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", + "dev": true, + "dependencies": { + "array-ify": "^1.0.0", + "dot-prop": "^5.1.0" + } + }, + "node_modules/conventional-changelog-angular": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz", + "integrity": "sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==", + "dev": true, + "dependencies": { + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/conventional-changelog-conventionalcommits": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-7.0.2.tgz", + "integrity": "sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==", + "dev": true, + "dependencies": { + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/conventional-commits-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", + "integrity": "sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==", + "dev": true, + "dependencies": { + "is-text-path": "^2.0.0", + "JSONStream": "^1.3.5", + "meow": "^12.0.1", + "split2": "^4.0.0" + }, + "bin": { + "conventional-commits-parser": "cli.mjs" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cosmiconfig-typescript-loader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-5.0.0.tgz", + "integrity": "sha512-+8cK7jRAReYkMwMiG+bxhcNKiHJDM6bR9FD/nGBXOWdMLuYawjF5cGrtLilJ+LGd3ZjCXnJjR5DkfWPoIVlqJA==", + "dev": true, + "dependencies": { + "jiti": "^1.19.1" + }, + "engines": { + "node": ">=v16" + }, + "peerDependencies": { + "@types/node": "*", + "cosmiconfig": ">=8.2", + "typescript": ">=4" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/dargs": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-8.1.0.tgz", + "integrity": "sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/find-up": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-7.0.0.tgz", + "integrity": "sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==", + "dev": true, + "dependencies": { + "locate-path": "^7.2.0", + "path-exists": "^5.0.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/git-raw-commits": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-4.0.0.tgz", + "integrity": "sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==", + "dev": true, + "dependencies": { + "dargs": "^8.0.0", + "meow": "^12.0.1", + "split2": "^4.0.0" + }, + "bin": { + "git-raw-commits": "cli.mjs" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/global-directory": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz", + "integrity": "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==", + "dev": true, + "dependencies": { + "ini": "4.1.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/husky": { + "version": "9.0.11", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.11.tgz", + "integrity": "sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==", + "dev": true, + "bin": { + "husky": "bin.mjs" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/import-meta-resolve": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.0.0.tgz", + "integrity": "sha512-okYUR7ZQPH+efeuMJGlq4f8ubUgO50kByRPyt/Cy1Io4PSRsPjxME+YlVaCOx+NIToW7hCsZNFJyTPFFKepRSA==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/ini": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", + "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-text-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-2.0.0.tgz", + "integrity": "sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==", + "dev": true, + "dependencies": { + "text-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/jiti": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", + "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", + "dev": true, + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "dev": true, + "engines": [ + "node >= 0.2.0" + ] + }, + "node_modules/JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "dependencies": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "bin.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "dev": true, + "dependencies": { + "p-locate": "^6.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "dev": true + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true + }, + "node_modules/lodash.kebabcase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", + "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.mergewith": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", + "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", + "dev": true + }, + "node_modules/lodash.snakecase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", + "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==", + "dev": true + }, + "node_modules/lodash.startcase": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", + "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==", + "dev": true + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", + "dev": true + }, + "node_modules/lodash.upperfirst": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz", + "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==", + "dev": true + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/meow": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", + "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", + "dev": true, + "engines": { + "node": ">=16.10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "dev": true, + "dependencies": { + "p-limit": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "dev": true, + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/text-extensions": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-2.4.0.tgz", + "integrity": "sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, + "node_modules/typescript": { + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz", + "integrity": "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==", + "dev": true, + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..929c798 --- /dev/null +++ b/package.json @@ -0,0 +1,12 @@ +{ + "devDependencies": { + "@commitlint/cli": "^19.1.0", + "@commitlint/config-conventional": "^19.1.0", + "husky": "^9.0.11" + }, + "scripts": { + "prepare": "husky", + "commitlint": "commitlint --edit" + }, + "type": "module" +} diff --git a/src/quant_research_starter/__pycache__/cli.cpython-312.pyc b/src/quant_research_starter/__pycache__/cli.cpython-312.pyc deleted file mode 100644 index 436e305..0000000 Binary files a/src/quant_research_starter/__pycache__/cli.cpython-312.pyc and /dev/null differ diff --git a/src/quant_research_starter/factors/__init__.py b/src/quant_research_starter/factors/__init__.py index a66c4d3..feea7ea 100644 --- a/src/quant_research_starter/factors/__init__.py +++ b/src/quant_research_starter/factors/__init__.py @@ -1,6 +1,7 @@ """Factors module public API.""" from .base import Factor +from .bollinger import BollingerBandsFactor from .momentum import CrossSectionalMomentum, MomentumFactor from .size import SizeFactor from .value import ValueFactor @@ -8,10 +9,11 @@ __all__ = [ "Factor", - "MomentumFactor", + "BollingerBandsFactor", "CrossSectionalMomentum", - "ValueFactor", + "MomentumFactor", "SizeFactor", - "VolatilityFactor", + "ValueFactor", "IdiosyncraticVolatility", + "VolatilityFactor", ] diff --git a/src/quant_research_starter/factors/bollinger.py b/src/quant_research_starter/factors/bollinger.py new file mode 100644 index 0000000..ad0ca5a --- /dev/null +++ b/src/quant_research_starter/factors/bollinger.py @@ -0,0 +1,32 @@ +import pandas as pd + +from .base import Factor + + +class BollingerBandsFactor(Factor): + """ + Compute Bollinger Bands z-score: + z = (price - rolling_mean) / rolling_std + """ + + def __init__( + self, name: str = "bollinger_bands", lookback: int = 20, num_std: float = 2.0 + ): + super().__init__(name=name, lookback=lookback) + self.num_std = num_std + + def compute(self, prices: pd.DataFrame) -> pd.DataFrame: + # Validate data + self._validate_data(prices) + + # Rolling statistics + rolling_mean = prices.rolling(self.lookback).mean() + rolling_std = prices.rolling(self.lookback).std() + + # Bollinger z-score + zscore = (prices - rolling_mean) / rolling_std + + # Save results + self._values = zscore + + return zscore diff --git a/tests/test_factors.py b/tests/test_factors.py index 2091d3e..8e54093 100644 --- a/tests/test_factors.py +++ b/tests/test_factors.py @@ -5,6 +5,7 @@ import pytest from quant_research_starter.factors import ( + BollingerBandsFactor, MomentumFactor, SizeFactor, ValueFactor, @@ -195,3 +196,32 @@ def test_volatility_calculation(self): assert ( spearman_corr < -0.5 ), f"volatility factor should be negatively correlated with realized volatility (spearman={spearman_corr})" + + +class TestBollingerBandsFactor: + """Test Bollinger Bands factor calculations.""" + + def test_bollinger_basic(self, sample_prices): + """Test basic Bollinger Bands z-score calculation.""" + factor = BollingerBandsFactor(lookback=20, num_std=2.0) + result = factor.compute(sample_prices) + + # Must be a DataFrame with same shape as prices + assert isinstance(result, pd.DataFrame) + assert not result.empty + assert set(result.columns) == set(sample_prices.columns) + + # Values should be finite where enough data exists + valid_values = result.iloc[factor.lookback :].values.flatten() + assert np.all(np.isfinite(valid_values)), "NaNs found after lookback period" + + # Mean of z-scores should be roughly centered near 0 + mean_z = np.nanmean(valid_values) + assert abs(mean_z) < 0.5, f"Z-scores not centered: mean={mean_z}" + + def test_bollinger_lookback_validation(self, sample_prices): + """Ensure _validate_data raises for insufficient data.""" + short_data = sample_prices.iloc[:5] + factor = BollingerBandsFactor(lookback=10) + with pytest.raises(ValueError): + factor.compute(short_data)