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
66 changes: 48 additions & 18 deletions .github/workflows/daily_trading_bot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ concurrency:

on:
schedule:
# Runs at 00:00 UTC (8:00 AM SGT) Tuesday-Sunday
- cron: '0 0 * * 2-7'
# Runs at 00:00 UTC (8:00 AM SGT) Tuesday-Saturday
- cron: '0 0 * * 2-6'
workflow_dispatch:
inputs:
run_in_lightning_studio:
Expand Down Expand Up @@ -74,6 +74,16 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v4

- name: Enforce schedule day guard (Tue-Sat only)
if: ${{ github.event_name == 'schedule' }}
run: |
dow=$(date -u +%u)
# ISO day-of-week: 1=Mon ... 7=Sun. Allow Tue(2) through Sat(6) only.
if [ "${dow}" -lt 2 ] || [ "${dow}" -gt 6 ]; then
echo "Scheduled run blocked: UTC weekday ${dow} is outside Tue-Sat window." >&2
exit 1
fi

- name: Set up Python
uses: actions/setup-python@v5
with:
Expand Down Expand Up @@ -196,15 +206,35 @@ jobs:

- name: Install Lightning dependencies
id: install_lightning_deps
if: ${{ steps.install_base_dependencies.outcome == 'success' && ((github.event_name == 'workflow_dispatch' && inputs.run_in_lightning_studio) || (github.event_name != 'workflow_dispatch') || (github.event_name == 'workflow_dispatch' && !inputs.disable_ai_trading)) }}
if: ${{ steps.install_base_dependencies.outcome == 'success' && ((github.event_name == 'workflow_dispatch' && inputs.run_in_lightning_studio) || ((github.event_name != 'workflow_dispatch') || !inputs.disable_ai_trading)) }}
continue-on-error: ${{ !(github.event_name == 'workflow_dispatch' && inputs.run_in_lightning_studio) }}
timeout-minutes: 20
run: |
python -m pip install "lightning[app]==2.3.2" lightning-cloud==0.5.70

- name: Validate SMTP configuration for AI reports
if: ${{ steps.install_base_dependencies.outcome == 'success' && !(github.event_name == 'workflow_dispatch' && inputs.run_in_lightning_studio) && ((github.event_name != 'workflow_dispatch') || !inputs.disable_ai_trading) }}
env:
SMTP_SERVER: ${{ secrets.SMTP_SERVER }}
SMTP_PORT: ${{ secrets.SMTP_PORT }}
SENDER_EMAIL: ${{ secrets.SENDER_EMAIL }}
SENDER_PASSWORD: ${{ secrets.SENDER_PASSWORD }}
RECIPIENT_EMAIL: ${{ secrets.RECIPIENT_EMAIL }}
run: |
missing=""
for name in SMTP_SERVER SMTP_PORT SENDER_EMAIL SENDER_PASSWORD RECIPIENT_EMAIL; do
if [ -z "${!name}" ]; then
missing="${missing} ${name}"
fi
done
if [ -n "${missing}" ]; then
echo "Missing required SMTP env vars for AI report:${missing}" >&2
exit 1
fi

- name: Plan AI runtime
id: plan_ai_runtime
if: ${{ !(github.event_name == 'workflow_dispatch' && inputs.run_in_lightning_studio) && (github.event_name == 'workflow_dispatch' && !inputs.disable_ai_trading) }}
if: ${{ !(github.event_name == 'workflow_dispatch' && inputs.run_in_lightning_studio) && ((github.event_name != 'workflow_dispatch') || !inputs.disable_ai_trading) }}
run: |
mkdir -p results
configured_inference_url="${CEREBRIUM_TRAINED_MODEL_URL}"
Expand Down Expand Up @@ -239,7 +269,7 @@ jobs:

- name: Validate Cerebrium primary configuration
id: validate_cerebrium_primary_config
if: ${{ steps.install_base_dependencies.outcome == 'success' && !(github.event_name == 'workflow_dispatch' && inputs.run_in_lightning_studio) && (github.event_name == 'workflow_dispatch' && !inputs.disable_ai_trading) }}
if: ${{ steps.install_base_dependencies.outcome == 'success' && !(github.event_name == 'workflow_dispatch' && inputs.run_in_lightning_studio) && ((github.event_name != 'workflow_dispatch') || !inputs.disable_ai_trading) }}
run: |
runtime_mode="${{ steps.plan_ai_runtime.outputs.runtime_mode }}"
selected_backend="${{ steps.plan_ai_runtime.outputs.selected_backend }}"
Expand Down Expand Up @@ -276,7 +306,7 @@ jobs:

- name: Enforce AI routing invariants
id: enforce_ai_routing_invariants
if: ${{ steps.install_base_dependencies.outcome == 'success' && !(github.event_name == 'workflow_dispatch' && inputs.run_in_lightning_studio) && (github.event_name == 'workflow_dispatch' && !inputs.disable_ai_trading) }}
if: ${{ steps.install_base_dependencies.outcome == 'success' && !(github.event_name == 'workflow_dispatch' && inputs.run_in_lightning_studio) && ((github.event_name != 'workflow_dispatch') || !inputs.disable_ai_trading) }}
run: |
runtime_mode="${{ steps.plan_ai_runtime.outputs.runtime_mode }}"
has_inference_url="${{ steps.validate_cerebrium_primary_config.outputs.has_inference_url }}"
Expand All @@ -294,7 +324,7 @@ jobs:
fi

- name: Emit AI runtime decision
if: ${{ steps.install_base_dependencies.outcome == 'success' && !(github.event_name == 'workflow_dispatch' && inputs.run_in_lightning_studio) && (github.event_name == 'workflow_dispatch' && !inputs.disable_ai_trading) }}
if: ${{ steps.install_base_dependencies.outcome == 'success' && !(github.event_name == 'workflow_dispatch' && inputs.run_in_lightning_studio) && ((github.event_name != 'workflow_dispatch') || !inputs.disable_ai_trading) }}
run: |
echo "AI runtime mode: ${{ steps.plan_ai_runtime.outputs.runtime_mode }}"
echo "AI backend: ${{ steps.plan_ai_runtime.outputs.selected_backend }}"
Expand All @@ -303,7 +333,7 @@ jobs:

- name: Warm Cerebrium inference app
id: warm_cerebrium_inference
if: ${{ steps.install_base_dependencies.outcome == 'success' && !(github.event_name == 'workflow_dispatch' && inputs.run_in_lightning_studio) && (github.event_name == 'workflow_dispatch' && !inputs.disable_ai_trading) && steps.enforce_ai_routing_invariants.outcome == 'success' && steps.plan_ai_runtime.outputs.runtime_mode == 'cerebrium_full' && steps.validate_cerebrium_primary_config.outputs.has_inference_url == 'true' }}
if: ${{ steps.install_base_dependencies.outcome == 'success' && !(github.event_name == 'workflow_dispatch' && inputs.run_in_lightning_studio) && ((github.event_name != 'workflow_dispatch') || !inputs.disable_ai_trading) && steps.enforce_ai_routing_invariants.outcome == 'success' && steps.plan_ai_runtime.outputs.runtime_mode == 'cerebrium_full' && steps.validate_cerebrium_primary_config.outputs.has_inference_url == 'true' }}
continue-on-error: true
timeout-minutes: 45
env:
Expand Down Expand Up @@ -367,7 +397,7 @@ jobs:

- name: Verify Cerebrium predict endpoint
id: verify_cerebrium_predict
if: ${{ steps.install_base_dependencies.outcome == 'success' && !(github.event_name == 'workflow_dispatch' && inputs.run_in_lightning_studio) && (github.event_name == 'workflow_dispatch' && !inputs.disable_ai_trading) && steps.enforce_ai_routing_invariants.outcome == 'success' && steps.plan_ai_runtime.outputs.runtime_mode == 'cerebrium_full' && steps.validate_cerebrium_primary_config.outputs.has_inference_url == 'true' }}
if: ${{ steps.install_base_dependencies.outcome == 'success' && !(github.event_name == 'workflow_dispatch' && inputs.run_in_lightning_studio) && ((github.event_name != 'workflow_dispatch') || !inputs.disable_ai_trading) && steps.enforce_ai_routing_invariants.outcome == 'success' && steps.plan_ai_runtime.outputs.runtime_mode == 'cerebrium_full' && steps.validate_cerebrium_primary_config.outputs.has_inference_url == 'true' }}
continue-on-error: true
timeout-minutes: 3
env:
Expand Down Expand Up @@ -428,7 +458,7 @@ jobs:

- name: Run AI Trading Bot on Cerebrium
id: run_ai_bot_cerebrium
if: ${{ steps.install_base_dependencies.outcome == 'success' && !(github.event_name == 'workflow_dispatch' && inputs.run_in_lightning_studio) && (github.event_name == 'workflow_dispatch' && !inputs.disable_ai_trading) && steps.enforce_ai_routing_invariants.outcome == 'success' && steps.plan_ai_runtime.outputs.runtime_mode == 'cerebrium_full' && steps.validate_cerebrium_primary_config.outputs.has_inference_url == 'true' && steps.verify_cerebrium_predict.outcome == 'success' }}
if: ${{ steps.install_base_dependencies.outcome == 'success' && !(github.event_name == 'workflow_dispatch' && inputs.run_in_lightning_studio) && ((github.event_name != 'workflow_dispatch') || !inputs.disable_ai_trading) && steps.enforce_ai_routing_invariants.outcome == 'success' && steps.plan_ai_runtime.outputs.runtime_mode == 'cerebrium_full' && steps.validate_cerebrium_primary_config.outputs.has_inference_url == 'true' && steps.verify_cerebrium_predict.outcome == 'success' }}
continue-on-error: true
timeout-minutes: 90
env:
Expand Down Expand Up @@ -459,7 +489,7 @@ jobs:

- name: Run AI Trading Bot on Cerebrium (Retry)
id: run_ai_bot_cerebrium_retry
if: ${{ always() && steps.install_base_dependencies.outcome == 'success' && !(github.event_name == 'workflow_dispatch' && inputs.run_in_lightning_studio) && (github.event_name == 'workflow_dispatch' && !inputs.disable_ai_trading) && steps.enforce_ai_routing_invariants.outcome == 'success' && steps.plan_ai_runtime.outputs.runtime_mode == 'cerebrium_full' && steps.validate_cerebrium_primary_config.outputs.has_inference_url == 'true' && steps.verify_cerebrium_predict.outcome == 'success' && steps.run_ai_bot_cerebrium.outcome == 'failure' }}
if: ${{ always() && steps.install_base_dependencies.outcome == 'success' && !(github.event_name == 'workflow_dispatch' && inputs.run_in_lightning_studio) && ((github.event_name != 'workflow_dispatch') || !inputs.disable_ai_trading) && steps.enforce_ai_routing_invariants.outcome == 'success' && steps.plan_ai_runtime.outputs.runtime_mode == 'cerebrium_full' && steps.validate_cerebrium_primary_config.outputs.has_inference_url == 'true' && steps.verify_cerebrium_predict.outcome == 'success' && steps.run_ai_bot_cerebrium.outcome == 'failure' }}
continue-on-error: true
timeout-minutes: 90
env:
Expand Down Expand Up @@ -490,7 +520,7 @@ jobs:

- name: Launch Lightning inference studio
id: launch_lightning_inference
if: ${{ !(github.event_name == 'workflow_dispatch' && inputs.run_in_lightning_studio) && (github.event_name == 'workflow_dispatch' && !inputs.disable_ai_trading) && steps.plan_ai_runtime.outputs.runtime_mode == 'lightning_full' && steps.install_lightning_deps.outcome == 'success' }}
if: ${{ !(github.event_name == 'workflow_dispatch' && inputs.run_in_lightning_studio) && ((github.event_name != 'workflow_dispatch') || !inputs.disable_ai_trading) && steps.plan_ai_runtime.outputs.runtime_mode == 'lightning_full' && steps.install_lightning_deps.outcome == 'success' }}
continue-on-error: true
timeout-minutes: 60
env:
Expand Down Expand Up @@ -519,7 +549,7 @@ jobs:

- name: Run AI Trading Bot in Lightning Studio
id: run_ai_bot_in_lightning_studio
if: ${{ !(github.event_name == 'workflow_dispatch' && inputs.run_in_lightning_studio) && (github.event_name == 'workflow_dispatch' && !inputs.disable_ai_trading) && steps.plan_ai_runtime.outputs.runtime_mode == 'lightning_full' && steps.install_lightning_deps.outcome == 'success' && steps.launch_lightning_inference.outcome == 'success' }}
if: ${{ !(github.event_name == 'workflow_dispatch' && inputs.run_in_lightning_studio) && ((github.event_name != 'workflow_dispatch') || !inputs.disable_ai_trading) && steps.plan_ai_runtime.outputs.runtime_mode == 'lightning_full' && steps.install_lightning_deps.outcome == 'success' && steps.launch_lightning_inference.outcome == 'success' }}
continue-on-error: true
timeout-minutes: 90
env:
Expand Down Expand Up @@ -553,7 +583,7 @@ jobs:

- name: Run AI Trading Bot (Distilled Local Fallback)
id: run_ai_bot_distilled_local
if: ${{ steps.install_base_dependencies.outcome == 'success' && !(github.event_name == 'workflow_dispatch' && inputs.run_in_lightning_studio) && (github.event_name == 'workflow_dispatch' && !inputs.disable_ai_trading) && (steps.plan_ai_runtime.outputs.runtime_mode == 'distilled_local' || (steps.plan_ai_runtime.outputs.runtime_mode == 'cerebrium_full' && steps.validate_cerebrium_primary_config.outputs.has_inference_url == 'true' && (steps.warm_cerebrium_inference.outcome == 'failure' || steps.verify_cerebrium_predict.outcome == 'failure' || (steps.run_ai_bot_cerebrium.outcome == 'failure' && steps.run_ai_bot_cerebrium_retry.outcome != 'success'))) || (steps.plan_ai_runtime.outputs.runtime_mode == 'lightning_full' && (steps.launch_lightning_inference.outcome == 'failure' || steps.run_ai_bot_in_lightning_studio.outcome == 'failure'))) }}
if: ${{ steps.install_base_dependencies.outcome == 'success' && !(github.event_name == 'workflow_dispatch' && inputs.run_in_lightning_studio) && ((github.event_name != 'workflow_dispatch') || !inputs.disable_ai_trading) && (steps.plan_ai_runtime.outputs.runtime_mode == 'distilled_local' || (steps.plan_ai_runtime.outputs.runtime_mode == 'cerebrium_full' && steps.validate_cerebrium_primary_config.outputs.has_inference_url == 'true' && (steps.warm_cerebrium_inference.outcome == 'failure' || steps.verify_cerebrium_predict.outcome == 'failure' || (steps.run_ai_bot_cerebrium.outcome == 'failure' && steps.run_ai_bot_cerebrium_retry.outcome != 'success'))) || (steps.plan_ai_runtime.outputs.runtime_mode == 'lightning_full' && (steps.launch_lightning_inference.outcome == 'failure' || steps.run_ai_bot_in_lightning_studio.outcome == 'failure'))) }}
continue-on-error: true
timeout-minutes: 60
env:
Expand All @@ -575,7 +605,7 @@ jobs:

- name: Run AI Trading Bot (Emergency Distilled Retry)
id: run_ai_bot_distilled_emergency_retry
if: ${{ always() && steps.install_base_dependencies.outcome == 'success' && !(github.event_name == 'workflow_dispatch' && inputs.run_in_lightning_studio) && (github.event_name == 'workflow_dispatch' && !inputs.disable_ai_trading) && steps.run_ai_bot_distilled_local.outcome == 'failure' }}
if: ${{ always() && steps.install_base_dependencies.outcome == 'success' && !(github.event_name == 'workflow_dispatch' && inputs.run_in_lightning_studio) && ((github.event_name != 'workflow_dispatch') || !inputs.disable_ai_trading) && steps.run_ai_bot_distilled_local.outcome == 'failure' }}
continue-on-error: true
timeout-minutes: 60
env:
Expand All @@ -599,7 +629,7 @@ jobs:

- name: Send AI Failure Report
id: send_ai_failure_report
if: ${{ always() && !(github.event_name == 'workflow_dispatch' && inputs.run_in_lightning_studio) && (github.event_name == 'workflow_dispatch' && !inputs.disable_ai_trading) && (((steps.plan_ai_runtime.outputs.runtime_mode == 'cerebrium_full' && steps.validate_cerebrium_primary_config.outputs.has_inference_url == 'true') && (steps.warm_cerebrium_inference.outcome == 'failure' || steps.verify_cerebrium_predict.outcome == 'failure' || (steps.run_ai_bot_cerebrium.outcome == 'failure' && steps.run_ai_bot_cerebrium_retry.outcome != 'success'))) || ((steps.plan_ai_runtime.outputs.runtime_mode == 'lightning_full') && (steps.launch_lightning_inference.outcome == 'failure' || steps.run_ai_bot_in_lightning_studio.outcome == 'failure') && steps.run_ai_bot_distilled_local.outcome == 'failure' && steps.run_ai_bot_distilled_emergency_retry.outcome != 'success') || ((steps.plan_ai_runtime.outputs.runtime_mode == 'distilled_local') && steps.run_ai_bot_distilled_local.outcome == 'failure' && steps.run_ai_bot_distilled_emergency_retry.outcome != 'success')) }}
if: ${{ always() && !(github.event_name == 'workflow_dispatch' && inputs.run_in_lightning_studio) && ((github.event_name != 'workflow_dispatch') || !inputs.disable_ai_trading) && (((steps.plan_ai_runtime.outputs.runtime_mode == 'cerebrium_full' && steps.validate_cerebrium_primary_config.outputs.has_inference_url == 'true') && (steps.warm_cerebrium_inference.outcome == 'failure' || steps.verify_cerebrium_predict.outcome == 'failure' || (steps.run_ai_bot_cerebrium.outcome == 'failure' && steps.run_ai_bot_cerebrium_retry.outcome != 'success'))) || ((steps.plan_ai_runtime.outputs.runtime_mode == 'lightning_full') && (steps.launch_lightning_inference.outcome == 'failure' || steps.run_ai_bot_in_lightning_studio.outcome == 'failure') && steps.run_ai_bot_distilled_local.outcome == 'failure' && steps.run_ai_bot_distilled_emergency_retry.outcome != 'success') || ((steps.plan_ai_runtime.outputs.runtime_mode == 'distilled_local') && steps.run_ai_bot_distilled_local.outcome == 'failure' && steps.run_ai_bot_distilled_emergency_retry.outcome != 'success')) }}
continue-on-error: true
env:
SMTP_SERVER: ${{ secrets.SMTP_SERVER }}
Expand Down Expand Up @@ -712,7 +742,7 @@ jobs:
RECIPIENT_EMAIL: ${{ secrets.RECIPIENT_EMAIL }}
RUN_URL: ${{ format('{0}/{1}/actions/runs/{2}', github.server_url, github.repository, github.run_id) }}
CORE_EXPECTED: ${{ (github.event_name != 'workflow_dispatch') || (github.event_name == 'workflow_dispatch' && !inputs.disable_core_trading) }}
AI_EXPECTED: "false"
AI_EXPECTED: ${{ (github.event_name != 'workflow_dispatch') || (github.event_name == 'workflow_dispatch' && !inputs.disable_ai_trading) }}
BASE_DEPS_OUTCOME: ${{ steps.install_base_dependencies.outcome }}
CORE_OUTCOME: ${{ steps.run_core_bot.outcome }}
CORE_RETRY_OUTCOME: ${{ steps.run_core_bot_retry.outcome }}
Expand Down Expand Up @@ -772,7 +802,7 @@ jobs:
CORE_OUTCOME: ${{ steps.run_core_bot.outcome }}
CORE_RETRY_OUTCOME: ${{ steps.run_core_bot_retry.outcome }}
CORE_EXPECTED: ${{ (github.event_name != 'workflow_dispatch') || (github.event_name == 'workflow_dispatch' && !inputs.disable_core_trading) }}
AI_EXPECTED: "false"
AI_EXPECTED: ${{ (github.event_name != 'workflow_dispatch') || (github.event_name == 'workflow_dispatch' && !inputs.disable_ai_trading) }}
INSTALL_LIGHTNING_OUTCOME: ${{ steps.install_lightning_deps.outcome }}
AI_RUNTIME_MODE: ${{ steps.plan_ai_runtime.outputs.runtime_mode }}
LAUNCH_LIGHTNING_OUTCOME: ${{ steps.launch_lightning_inference.outcome }}
Expand Down
Loading
Loading