Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions .github/actions/ci/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: Plugin Checks
description: The checks every change to the plugin passes, run from the directory holding its pyproject.toml.

inputs:
directory:
description: The directory holding the plugin's pyproject.toml.
required: false
default: "."
python-version:
description: The Python version the checks run under.
required: false
default: "3.13"

runs:
using: composite
steps:
- name: Install uv
uses: astral-sh/setup-uv@v10.0.1
with:
enable-cache: true
python-version: ${{ inputs.python-version }}

- name: Install Dependencies
shell: bash
working-directory: ${{ inputs.directory }}
run: uv sync

- name: Run Formatter Check
shell: bash
working-directory: ${{ inputs.directory }}
run: uv run ruff format --check

- name: Run Linter
shell: bash
working-directory: ${{ inputs.directory }}
run: uv run ruff check

- name: Run Static Type Checking
shell: bash
working-directory: ${{ inputs.directory }}
run: uv run mypy

- name: Run Tests (with coverage)
shell: bash
working-directory: ${{ inputs.directory }}
run: uv run pytest --cov=src --cov-report=term

- name: Bandit Security Analysis
shell: bash
working-directory: ${{ inputs.directory }}
run: uv run bandit -c pyproject.toml --recursive src --exclude tests
25 changes: 25 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: CI Pipeline

on:
push:
branches:
- main
pull_request:
types: [opened, synchronize, reopened, ready_for_review]

jobs:
ci:
name: Continuous Integration
if: github.event_name != 'pull_request' || github.event.pull_request.draft == false
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.13]
steps:
- name: Checkout Repository
uses: actions/checkout@v7

- name: Run the Plugin Checks
uses: ./.github/actions/ci
with:
python-version: ${{ matrix.python-version }}
54 changes: 53 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "robottraderslab-impulse"
version = "0.1.1"
version = "0.1.2"
description = "Impulse trading strategy plugin for the RobotTradersLab engine"
readme = "README.md"
requires-python = ">=3.13,<3.14"
Expand Down Expand Up @@ -31,3 +31,55 @@ build-backend = "uv_build"

[tool.uv.build-backend]
module-name = "robottraderslab_impulse"

[dependency-groups]
dev = [
"bandit[toml]==1.9.4",
"mypy==1.20.0",
"pandas-stubs==3.0.0.260204",
"pytest==9.0.3",
"pytest-asyncio==1.3.0",
"pytest-cov==7.1.0",
"ruff==0.15.10",
]

[tool.coverage.run]
omit = ["*/tests/*", "*/test_*.py"]

[tool.pytest.ini_options]
testpaths = ["tests"]
asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "function"
filterwarnings = [
"ignore:enable_cleanup_closed ignored because.*:DeprecationWarning:aiohttp.connector",
]

[tool.mypy]
packages = ["robottraderslab_impulse"]
follow_imports = "normal"
python_version = "3.13"
color_output = true
show_error_codes = true
check_untyped_defs = true
disallow_untyped_defs = true
no_implicit_optional = true
warn_return_any = true
warn_unreachable = true
warn_unused_ignores = true
ignore_missing_imports = true
namespace_packages = true
incremental = true
cache_dir = ".mypy_cache"
exclude = '^(build/|dist/|\.venv/|.*tests/)'

[tool.bandit]
skips = ["B101"]

[tool.ruff]
target-version = "py313"

[tool.ruff.lint]
extend-select = ["I", "PT"]

[tool.ruff.lint.isort]
known-first-party = ["robottraderslab"]
2 changes: 0 additions & 2 deletions src/robottraderslab_impulse/examples/impulse-bot-example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ ohlcv_provider = "ccxt_bitget"
ohlcv_provider = "bitget"

[live.trading_account]
exchange = "bitget"
demo_trading = true
secret_name = "impulse-example"

[report]
Expand Down
2 changes: 1 addition & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
from unittest.mock import Mock

import pytest
from robottraderslab_impulse import ImpulseStrategy

from robottraderslab.exchanges import FuturesExchangeProtocol
from robottraderslab.strategies import Balance, TradingMode, TradingSystem
Expand All @@ -13,6 +12,7 @@
MarginMode,
MarginSettings,
)
from robottraderslab_impulse import ImpulseStrategy


@pytest.fixture
Expand Down
2 changes: 1 addition & 1 deletion tests/test_impulse_book_trading_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import numpy as np
import pandas as pd
import pytest
from robottraderslab_impulse import ImpulseStrategy

from robottraderslab import Symbol
from robottraderslab.strategies import (
Expand All @@ -32,6 +31,7 @@
SetMarginModeAction,
UpdatePositionStopLossAction,
)
from robottraderslab_impulse import ImpulseStrategy

BTC = Symbol.create("BTC/USDT:USDT")
ACCOUNT_NAME = "test"
Expand Down
2 changes: 1 addition & 1 deletion tests/test_impulse_chart_indicators.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import numpy as np
from robottraderslab_impulse.chart_indicators import get_lightweight_chart_indicators

from robottraderslab.strategies import Candles
from robottraderslab_impulse.chart_indicators import get_lightweight_chart_indicators

CLOSES = np.array([100.0 + i * 2.0 for i in range(250)])
CANDLES = Candles(
Expand Down
2 changes: 1 addition & 1 deletion tests/test_impulse_generate_trading_signals.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import numpy as np
import pandas as pd
import pytest
from robottraderslab_impulse.impulse_indicator import compute_signals

from robottraderslab import Symbol
from robottraderslab.exceptions import MissingOhlcvDataError
from robottraderslab.indicators import MAType
from robottraderslab.strategies import OHLCVs, TradingMode
from robottraderslab_impulse.impulse_indicator import compute_signals

BTC = Symbol.create("BTC/USDT:USDT")
TIMEFRAME = "1d"
Expand Down
2 changes: 1 addition & 1 deletion tests/test_impulse_indicator.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import numpy as np
from robottraderslab_impulse.impulse_indicator import ImpulseSignals, compute_signals

from robottraderslab.indicators import MAType
from robottraderslab_impulse.impulse_indicator import ImpulseSignals, compute_signals

TREND_LENGTH = 10

Expand Down
7 changes: 3 additions & 4 deletions tests/test_impulse_position_orders.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
from robottraderslab_impulse.position_orders import wanted_entry_side, wants_exit
from robottraderslab_impulse.profile_config import ProfileConfig
from robottraderslab_impulse.profile_snapshot import ProfileSnapshot

from robottraderslab.strategies import (
PositionSide,
TrackedPosition,
)
from robottraderslab.strategies.futures import TotalBalanceRatio
from robottraderslab_impulse.position_orders import wanted_entry_side, wants_exit
from robottraderslab_impulse.profile_config import ProfileConfig
from robottraderslab_impulse.profile_snapshot import ProfileSnapshot


def _profile(**overrides) -> ProfileConfig:
Expand Down
8 changes: 4 additions & 4 deletions tests/test_impulse_position_tracking.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import pytest

from robottraderslab import Symbol
from robottraderslab.strategies import profile_tag
from robottraderslab.strategies.futures import TotalBalanceRatio
from robottraderslab_impulse.position_tracking import (
tags_by_profile_id,
tracked_symbols,
)
from robottraderslab_impulse.profile_config import ProfileConfig

from robottraderslab import Symbol
from robottraderslab.strategies import profile_tag
from robottraderslab.strategies.futures import TotalBalanceRatio


@pytest.fixture
def btc() -> Symbol:
Expand Down
2 changes: 1 addition & 1 deletion tests/test_impulse_profile_config.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import pytest
from robottraderslab_impulse.profile_config import ProfileConfig

from robottraderslab.exceptions import StrategyCriticalError
from robottraderslab.indicators import MAType
from robottraderslab.strategies.futures import (
MarginMode,
TotalBalanceRatio,
)
from robottraderslab_impulse.profile_config import ProfileConfig


class TestDirectionFlags:
Expand Down
2 changes: 1 addition & 1 deletion tests/test_impulse_profile_isolation.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

import pandas as pd
import pytest
from robottraderslab_impulse import ImpulseStrategy

from robottraderslab import Symbol
from robottraderslab.strategies import (
Expand All @@ -20,6 +19,7 @@
MarginMode,
MarginSettings,
)
from robottraderslab_impulse import ImpulseStrategy

BTC = Symbol.create("BTC/USDT:USDT")
ETH = Symbol.create("ETH/USDT:USDT")
Expand Down
2 changes: 1 addition & 1 deletion tests/test_impulse_setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
from collections.abc import Callable

import pytest
from robottraderslab_impulse import ImpulseStrategy

from robottraderslab import Symbol
from robottraderslab.exceptions import StrategyCriticalError
from robottraderslab.strategies import StrategyRequirements
from robottraderslab.strategies.futures import MarginMode, MarginSettings
from robottraderslab_impulse import ImpulseStrategy


def _profile(tag: str, stop_loss_pct: float) -> dict:
Expand Down
4 changes: 2 additions & 2 deletions tests/test_impulse_stacked_profiles_backtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
from typing import Any

import pytest
from robottraderslab_impulse import ImpulseStrategy
from robottraderslab_impulse.profile_config import ProfileConfig

from robottraderslab import Symbol
from robottraderslab.backtester.backtester import Backtester
Expand All @@ -18,6 +16,8 @@
from robottraderslab.ohlcv_provider import CSVOHLCVProvider
from robottraderslab.strategies import OHLCVs, PositionSide, TradingMode, TradingSystem
from robottraderslab.strategies.futures import FuturesAccount
from robottraderslab_impulse import ImpulseStrategy
from robottraderslab_impulse.profile_config import ProfileConfig

BTC = Symbol.create("BTC/USDT:USDT")
TIMEFRAME = "1d"
Expand Down
4 changes: 2 additions & 2 deletions tests/test_impulse_stop_loss_backtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
from typing import Any

import pytest
from robottraderslab_impulse import ImpulseStrategy
from robottraderslab_impulse.profile_config import ProfileConfig

from robottraderslab import Symbol
from robottraderslab.backtester.backtester import Backtester
Expand All @@ -18,6 +16,8 @@
from robottraderslab.ohlcv_provider import CSVOHLCVProvider
from robottraderslab.strategies import OHLCVs, TradingMode, TradingSystem
from robottraderslab.strategies.futures import FuturesAccount
from robottraderslab_impulse import ImpulseStrategy
from robottraderslab_impulse.profile_config import ProfileConfig

BTC = Symbol.create("BTC/USDT:USDT")
TIMEFRAME = "1d"
Expand Down
Loading