-
Notifications
You must be signed in to change notification settings - Fork 0
149 lines (125 loc) · 5.66 KB
/
daily-trading.yml
File metadata and controls
149 lines (125 loc) · 5.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
name: Daily Trading Pipeline
on:
schedule:
# US market hours — run twice daily Mon-Fri
# 6:45 AM PT = 14:45 UTC (PST, Nov-Mar) / 13:45 UTC (PDT, Mar-Nov)
# 12:45 PM PT = 20:45 UTC (PST) / 19:45 UTC (PDT)
# Using both UTC offsets to cover DST transitions
- cron: '45 13 * * 1-5' # 6:45 AM PDT
- cron: '45 14 * * 1-5' # 6:45 AM PST
- cron: '45 19 * * 1-5' # 12:45 PM PDT
- cron: '45 20 * * 1-5' # 12:45 PM PST
workflow_dispatch: # Allow manual trigger from GitHub UI
concurrency:
group: daily-trading
cancel-in-progress: false
permissions:
contents: write # Needed for commit-back of state files
env:
ALPACA_API_KEY: ${{ secrets.ALPACA_API_KEY }}
ALPACA_SECRET_KEY: ${{ secrets.ALPACA_SECRET_KEY }}
ALPACA_PAPER: ${{ secrets.ALPACA_PAPER || 'true' }}
FINNHUB_API_KEY: ${{ secrets.FINNHUB_API_KEY }}
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }}
SEC_EDGAR_USER_AGENT: ${{ secrets.SEC_EDGAR_USER_AGENT }}
jobs:
trade:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Install uv
uses: astral-sh/setup-uv@v7
- name: Install Python and dependencies
run: uv sync
- name: Ensure data directory exists
run: mkdir -p data
- name: Restore state from trading-data branch
run: |
git fetch origin trading-data 2>/dev/null || true
git checkout origin/trading-data -- data/ 2>/dev/null || echo "No prior trading data"
# Git restores files at 0644; preflight requires 0600 on the state DB.
chmod 600 data/trading_state.db 2>/dev/null || true
- name: 0. Pre-flight Health Check
id: preflight
timeout-minutes: 2
run: uv run python scripts/preflight.py
- name: 1. Position Manager (manage exits)
id: position_manager
if: steps.preflight.outcome == 'success'
timeout-minutes: 10
run: uv run python scripts/position_manager.py --execute --check-sentiment
- name: 2. Screener Auto-Trade (biggest dips)
id: screener
if: steps.preflight.outcome == 'success' && steps.position_manager.outcome == 'success'
timeout-minutes: 10
run: uv run python scripts/screener_trade.py --min-dip -7.0 --max-trades 8 --amount 3000 --execute
continue-on-error: true
- name: 3. Watchlist Scan (3-layer analysis)
id: watchlist
if: steps.preflight.outcome == 'success' && steps.position_manager.outcome == 'success'
timeout-minutes: 10
run: uv run python scripts/scan_with_sentiment.py --execute
continue-on-error: true
- name: 4. Momentum Auto-Trade (trend following)
id: momentum
if: steps.preflight.outcome == 'success' && steps.position_manager.outcome == 'success'
timeout-minutes: 10
run: uv run python scripts/momentum_trade.py --min-momentum 10.0 --max-trades 5 --amount 3000 --execute
continue-on-error: true
- name: 5. Portfolio Summary
if: always()
timeout-minutes: 2
run: uv run python scripts/portfolio.py
continue-on-error: true
- name: 6. Performance Report
if: always()
timeout-minutes: 2
run: uv run python scripts/performance.py
continue-on-error: true
- name: 7. Strategy Agent (Event Check)
if: always()
timeout-minutes: 30
run: uv run python scripts/strategy_agent.py --mode event-check
continue-on-error: true
- name: Commit state to trading-data branch
if: always()
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
# Save data directory
cp -r data/ /tmp/trading-data-snapshot/
# Switch to trading-data branch (create if needed)
git fetch origin trading-data 2>/dev/null || true
git checkout trading-data 2>/dev/null || {
git checkout --orphan trading-data
git rm -rf . 2>/dev/null || true
}
# Clean and restore data
rm -rf data/
cp -r /tmp/trading-data-snapshot/ data/
git add data/
git diff --cached --quiet || git commit -m "chore: update trading state [$(date -u +%Y-%m-%dT%H:%M:%SZ)]"
git push origin trading-data
# Return to original branch for any subsequent steps
git checkout ${{ github.ref_name }} 2>/dev/null || true
- name: Alert on pipeline failures
if: always()
env:
TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }}
GH_REPO: ${{ github.repository }}
GH_RUN_ID: ${{ github.run_id }}
run: |
FAILED=""
[ "${{ steps.preflight.outcome }}" = "failure" ] && FAILED="${FAILED}preflight "
[ "${{ steps.position_manager.outcome }}" = "failure" ] && FAILED="${FAILED}position_manager "
[ "${{ steps.screener.outcome }}" = "failure" ] && FAILED="${FAILED}screener "
[ "${{ steps.watchlist.outcome }}" = "failure" ] && FAILED="${FAILED}watchlist "
[ "${{ steps.momentum.outcome }}" = "failure" ] && FAILED="${FAILED}momentum "
if [ -n "$FAILED" ] && [ -n "$TELEGRAM_BOT_TOKEN" ] && [ -n "$TELEGRAM_CHAT_ID" ]; then
curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
-d chat_id="$TELEGRAM_CHAT_ID" \
-d text="GHA Pipeline Alert: Failed steps: ${FAILED}. Check: https://github.com/${GH_REPO}/actions/runs/${GH_RUN_ID}"
fi