Compare commits
4 Commits
90295d21e6
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c9e39b07f0 | ||
|
|
d17065bb56 | ||
|
|
2a971e81b7 | ||
|
|
196caea4a1 |
30
.github/workflows/rebalance.yml
vendored
Normal file
30
.github/workflows/rebalance.yml
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
name: Weekly Portfolio Rebalance
|
||||
|
||||
on:
|
||||
# 1. Запуск по расписанию (каждый понедельник в 10:30 МСК)
|
||||
schedule:
|
||||
- cron: '30 7 * * 1' # Время в UTC (7:30 UTC = 10:30 МСК)
|
||||
|
||||
# 2. Возможность запустить вручную кнопкой в интерфейсе GitHub
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
rebalance:
|
||||
runs-on: ubuntu-latest
|
||||
environment: tinvest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v3
|
||||
|
||||
- name: Set up Python
|
||||
run: uv python install 3.13
|
||||
|
||||
- name: Run Rebalance Bot
|
||||
env:
|
||||
# Передаем секреты в переменные окружения скрипта
|
||||
TINVEST_TOKEN: ${{ secrets.TINVEST_TOKEN }}
|
||||
run: uv run app/main.py
|
||||
@@ -17,4 +17,4 @@ TARGET_WEIGHTS = {
|
||||
"ROSN": Decimal("0.05"),
|
||||
}
|
||||
|
||||
CORRIDOR = Decimal("0.02") # 3% коридор отклонения от целевой доли
|
||||
CORRIDOR = Decimal("0.02") # 2% коридор отклонения от целевой доли
|
||||
|
||||
21
app/load_config.py
Normal file
21
app/load_config.py
Normal file
@@ -0,0 +1,21 @@
|
||||
import yaml
|
||||
from decimal import Decimal
|
||||
|
||||
|
||||
def load_config(config_path: str) -> dict:
|
||||
with open(config_path, "r") as file:
|
||||
data = yaml.safe_load(file)
|
||||
|
||||
target_weights = {
|
||||
ticker: Decimal(str(weight)) for ticker, weight in data["portfolio"].items
|
||||
}
|
||||
|
||||
config = {
|
||||
"account_id": data["account"]["id"],
|
||||
"is_sandbox": data["account"]["is_sandbox"],
|
||||
"corridor": Decimal(str(data["settings"]["corridor"])),
|
||||
"dry_run": data["settings"]["dry_run"],
|
||||
"target_weights": target_weights,
|
||||
}
|
||||
|
||||
return config
|
||||
@@ -10,13 +10,13 @@ load_dotenv()
|
||||
|
||||
|
||||
def main():
|
||||
with SandboxClient(token=os.getenv("TINVEST_TOKEN")) as client: # type: ignore
|
||||
with Client(token=os.getenv("TINVEST_TOKEN")) as client: # type: ignore
|
||||
bot = RebalanceBot(
|
||||
client=client,
|
||||
account_id="bb29bb79-8cf1-42ba-843f-47ef76c5b7c0",
|
||||
account_id="2235046505",
|
||||
target_weights=TARGET_WEIGHTS,
|
||||
corridor=CORRIDOR,
|
||||
dry_run=True,
|
||||
dry_run=False,
|
||||
)
|
||||
|
||||
plan = bot.calculate_rebalance(bot.fetch_portfolio())
|
||||
@@ -30,3 +30,5 @@ def main():
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
# with Client(token=os.getenv("TINVEST_TOKEN")) as client:
|
||||
# print(client.users.get_accounts())
|
||||
|
||||
@@ -71,6 +71,7 @@ class RebalanceBot:
|
||||
if lots != 0:
|
||||
plan.append(
|
||||
{
|
||||
"figi": pos.figi,
|
||||
"ticker": ticker,
|
||||
"uid": uid,
|
||||
"action": "BUY" if lots > 0 else "SELL",
|
||||
|
||||
Reference in New Issue
Block a user