Meridian.AI for Forex #485
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Meridian.AI for Forex | |
| on: | |
| schedule: | |
| - cron: '30 */6 * * *' | |
| workflow_dispatch: | |
| # Only one forex training run at a time — queued runs wait, never cancel in-progress | |
| concurrency: | |
| group: forex-training | |
| cancel-in-progress: false | |
| permissions: | |
| contents: write | |
| issues: write | |
| env: | |
| PYTHON_VERSION: '3.11' | |
| CACHE_VERSION: v3 | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true | |
| jobs: | |
| setup: | |
| name: Setup & Fetch Forex Data | |
| runs-on: ubuntu-latest | |
| outputs: | |
| has_data: ${{ steps.check_data.outputs.has_data }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 1 | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Cache Dependencies | |
| id: cache-deps | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.cache/pip | |
| key: ${{ runner.os }}-pip-${{ env.CACHE_VERSION }}-${{ hashFiles('requirements.txt') }} | |
| restore-keys: | | |
| ${{ runner.os }}-pip-${{ env.CACHE_VERSION }}- | |
| - name: Install Dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install torch --index-url https://download.pytorch.org/whl/cpu | |
| pip install -r requirements.txt | |
| pip install comet-ml | |
| - name: Free Disk Space | |
| run: | | |
| sudo rm -rf /usr/share/dotnet /opt/ghc /usr/local/share/boost | |
| df -h | |
| - name: Fetch Forex Data | |
| env: | |
| HF_TOKEN: ${{ secrets.HF_TOKEN }} | |
| run: | | |
| echo "Fetching forex data..." | |
| python scripts/fetch_and_store_data.py \ | |
| --db-file training.db \ | |
| --asset-type forex \ | |
| --limit 30 | |
| - name: Check if Data was Fetched | |
| id: check_data | |
| run: | | |
| if [ -f training.db ]; then | |
| COUNT=$(sqlite3 training.db "SELECT COUNT(*) FROM market_data;") | |
| echo "Total rows: $COUNT" | |
| if [ "$COUNT" -gt "0" ]; then | |
| echo "has_data=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "has_data=false" >> $GITHUB_OUTPUT | |
| fi | |
| else | |
| echo "has_data=false" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Upload Database | |
| if: steps.check_data.outputs.has_data == 'true' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: forex-training-db-${{ github.run_number }} | |
| path: training.db | |
| retention-days: 1 | |
| train: | |
| name: Train Forex Model | |
| needs: setup | |
| if: needs.setup.outputs.has_data == 'true' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 60 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Download Database | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: forex-training-db-${{ github.run_number }} | |
| - name: Cache Dependencies | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.cache/pip | |
| key: ${{ runner.os }}-pip-${{ env.CACHE_VERSION }}-${{ hashFiles('requirements.txt') }} | |
| - name: Install Dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install torch --index-url https://download.pytorch.org/whl/cpu | |
| pip install -r requirements.txt | |
| pip install comet-ml huggingface_hub | |
| - name: Download Existing Model | |
| env: | |
| HF_TOKEN: ${{ secrets.HF_TOKEN }} | |
| run: | | |
| mkdir -p models | |
| python -c " | |
| import os | |
| from huggingface_hub import hf_hub_download | |
| try: | |
| hf_hub_download(repo_id='meridianal/ARA.AI', filename='models/Meridian.AI_Forex.pt', local_dir='.', token=os.environ.get('HF_TOKEN')) | |
| print('Downloaded existing forex model (loader will skip if old version).') | |
| except Exception as e: | |
| print(f'No existing model found, will train fresh: {e}') | |
| " | |
| - name: Train Model | |
| env: | |
| COMET_API_KEY: ${{ secrets.COMET_API_KEY }} | |
| run: | | |
| echo "Training Forex Model (45min budget)" | |
| python scripts/train_forex_model.py \ | |
| --db-file training.db \ | |
| --output models/Meridian.AI_Forex.pt \ | |
| --use-all-data \ | |
| --epochs 999 \ | |
| --max-time 45 \ | |
| --comet-api-key "$COMET_API_KEY" | |
| - name: Upload Model | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: forex-model-${{ github.run_number }} | |
| path: models/Meridian.AI_Forex.pt | |
| retention-days: 7 | |
| deploy: | |
| name: Push to Hugging Face | |
| needs: [train, setup] | |
| if: needs.setup.outputs.has_data == 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Install Dependencies | |
| run: | | |
| pip install huggingface_hub python-dotenv | |
| - name: Download Model | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: forex-model-${{ github.run_number }} | |
| path: models/ | |
| - name: Upload to HF Hub | |
| env: | |
| HF_TOKEN: ${{ secrets.HF_TOKEN }} | |
| run: | | |
| echo "Uploading Forex Model to Hugging Face..." | |
| python scripts/push_elite_models.py \ | |
| --model-path models/Meridian.AI_Forex.pt \ | |
| --model-type forex | |
| cleanup: | |
| name: Cleanup & Report | |
| needs: [setup, train, deploy] | |
| if: always() | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Delete Artifacts | |
| uses: geekyeggo/delete-artifact@v5 | |
| with: | |
| name: forex-training-db-${{ github.run_number }} | |
| continue-on-error: true | |
| - name: Close Previous Failure Issues on Success | |
| if: needs.train.result == 'success' | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| // Find open automated forex-training issues and close them | |
| const issues = await github.rest.issues.listForRepo({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| labels: 'forex-training,automated', | |
| state: 'open', | |
| per_page: 10, | |
| }); | |
| for (const issue of issues.data) { | |
| await github.rest.issues.update({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: issue.number, | |
| state: 'closed', | |
| state_reason: 'completed', | |
| }); | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: issue.number, | |
| body: `Resolved by successful training run [#${context.runNumber}](${context.payload.repository.html_url}/actions/runs/${context.runId}).`, | |
| }); | |
| } | |
| - name: Create Failure Issue | |
| if: needs.train.result == 'failure' | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| // Check if an open issue already exists to avoid duplicates | |
| const existing = await github.rest.issues.listForRepo({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| labels: 'forex-training,automated', | |
| state: 'open', | |
| per_page: 5, | |
| }); | |
| if (existing.data.length > 0) { | |
| // Comment on existing issue instead of creating a new one | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: existing.data[0].number, | |
| body: `Still failing — run [#${context.runNumber}](${context.payload.repository.html_url}/actions/runs/${context.runId})\n- Setup: ${{ needs.setup.result }}\n- Training: ${{ needs.train.result }}\n- Deploy: ${{ needs.deploy.result }}`, | |
| }); | |
| return; | |
| } | |
| const title = `Forex Training Failed — Run ${context.runNumber}`; | |
| const body = `## Forex Model Training Failure | |
| **Workflow:** [Run #${context.runNumber}](${context.payload.repository.html_url}/actions/runs/${context.runId}) | |
| **Triggered by:** ${context.eventName} | |
| **Commit:** ${context.sha.substring(0, 7)} | |
| ### Job Results | |
| | Job | Result | | |
| |-----|--------| | |
| | Setup | ${{ needs.setup.result }} | | |
| | Training | ${{ needs.train.result }} | | |
| | Deploy | ${{ needs.deploy.result }} | | |
| > This issue will auto-close when the next training run succeeds. | |
| [View Logs](${context.payload.repository.html_url}/actions/runs/${context.runId}) | |
| `; | |
| await github.rest.issues.create({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| title: title, | |
| body: body, | |
| labels: ['bug', 'forex-training', 'automated'] | |
| }); |