Live-Test a Daily EMA20 and EMA50 Crossover
Python does the routine work. AI helps only when needed.
Use these copy-ready prompts to build a daily research scanner that logs every run and sends each new crossover signal to Discord with a chart.
1. Start with exact strategy rules
This tutorial uses a simple educational example. It does not buy every day. It checks once per day and produces a signal only when the two averages cross on a completed daily candle.
- Timeframe: Daily candles.
- Long signal: Yesterday's EMA20 was at or below EMA50, and today's completed EMA20 is above EMA50.
- Close signal: Yesterday's EMA20 was at or above EMA50, and today's completed EMA20 is below EMA50.
- Position model: Long or flat. No short selling in this starter version.
- Data rule: Never evaluate an unfinished daily candle.
- Duplicate rule: One alert per symbol, signal type, strategy version, and candle date.
- Execution boundary: The tutorial creates research alerts. It does not place broker orders.
2. Prepare the destination and settings
Create a private Discord webhook for the exact channel that should receive signals, such as #signals. Store the webhook URL in a protected environment variable named EMA_CROSS_DISCORD_WEBHOOK_URL. Do not paste the secret into a prompt, source file, screenshot, or public repository.
Choose these values before starting:
SYMBOL, for exampleSPY,BTC-USD, or another instrument supported by your data provider.TIMEZONE, for exampleAmerica/New_YorkorAsia/Manila.RUN_TIME, scheduled after the market's daily candle is confirmed closed.PROJECT_PATH, for example~/ema-cross-lab.
3. Master build prompt
Give this prompt to Hermes once. Replace the bracketed values first. Hermes should use AI during setup, code review, and troubleshooting only. The recurring scanner must remain deterministic Python.
You are building a deterministic daily EMA crossover research scanner for me.
Configuration:
- Project path: [PROJECT_PATH]
- Symbol: [SYMBOL]
- Timeframe: 1 day
- Timezone: [TIMEZONE]
- Strategy version: ema20_ema50_daily_v1
- Discord destination: the channel connected to the protected environment variable EMA_CROSS_DISCORD_WEBHOOK_URL
Strategy rules:
1. Use completed daily candles only. Never evaluate an unfinished current candle.
2. Calculate EMA20 and EMA50 from the same adjusted-close policy and document that policy.
3. Create a LONG signal when the previous completed candle has EMA20 less than or equal to EMA50 and the newest completed candle has EMA20 greater than EMA50.
4. Create a CLOSE signal when the previous completed candle has EMA20 greater than or equal to EMA50 and the newest completed candle has EMA20 less than EMA50.
5. This starter system is long or flat. Do not create short signals.
6. Do not place broker orders. This is a research and alerting workflow only.
Architecture and token rules:
1. AI tokens may be used while you design, write, test, review, or repair the system.
2. Normal scheduled runs must use deterministic Python only and must not call an LLM, agent, web-search tool, or AI API.
3. Build one Python entry point that fetches data, validates it, calculates the EMAs, checks the crossover, updates state, writes logs, creates the chart, and sends Discord alerts.
4. The Hermes cron must be script-only with no_agent set to true. Do not schedule a recurring agent prompt.
5. A healthy run with no new signal must print nothing and send nothing.
6. A hard failure must exit nonzero with a concise error so the scheduler can report it.
Data and reliability requirements:
1. Use a documented market-data provider supported by the symbol. Isolate the provider behind a small function so it can be replaced later.
2. Require enough valid history to calculate EMA50 with a safety buffer.
3. Reject empty data, duplicate timestamps, non-numeric closes, stale data, and an unfinished newest candle.
4. Use retry with bounded exponential backoff for transient network failures.
5. Save an append-only JSONL run log containing run time, symbol, latest completed candle date, close, EMA20, EMA50, signal decision, strategy version, data freshness, and any rejection reason.
6. Save deduplication state atomically. The key must include symbol, signal type, strategy version, and candle date.
7. Do not mark a signal as delivered until Discord confirms a successful response.
8. Never print or log the Discord webhook URL.
Discord and chart requirements:
1. Send every new LONG or CLOSE signal to the Discord webhook stored in EMA_CROSS_DISCORD_WEBHOOK_URL.
2. Attach a PNG chart to every signal. Do not send a text-only signal.
3. Plot at least the latest 180 completed daily candles, closing price, EMA20, EMA50, and a visible marker on the signal candle.
4. The alert text must include symbol, signal type, completed candle date, close, EMA20, EMA50, strategy version, and the statement: Research alert only, not financial advice.
5. If chart generation or attachment upload fails, treat the delivery as failed and do not mark the signal as sent.
Project requirements:
1. Create a local virtual environment and a pinned requirements file.
2. Keep configuration separate from code. Secrets belong in environment variables.
3. Add focused automated tests using synthetic candles for bullish cross, bearish cross, no cross, duplicate prevention, unfinished-candle rejection, stale data, Discord failure, and successful chart attachment.
4. Add a dry-run mode that creates the chart and alert payload without contacting Discord.
5. Add a test-alert mode that sends a clearly labeled TEST alert and chart without changing strategy deduplication state.
6. Write a README with setup, environment variables, commands, log locations, cron schedule, troubleshooting, and removal instructions.
Before finishing:
1. Run the automated tests and show the real result.
2. Run dry-run mode against current data.
3. Run test-alert mode only after confirming the webhook variable exists.
4. Inspect the generated PNG and verify it is nonempty.
5. Report exact created paths and the final script command.
Do not stop at a plan or pseudocode. Build and verify the working local project.
4. Script-only Hermes cron prompt
Use this after the scanner works. The schedule must run after the instrument's daily candle closes. The script itself handles the signal and Discord chart delivery, while the cron stays token-free.
Create a Hermes cron job for the verified EMA crossover scanner at [PROJECT_PATH].
Requirements:
1. Schedule it at [RUN_TIME] in [TIMEZONE], after the selected market's daily candle is confirmed closed.
2. Use the project's virtual-environment Python and absolute script path.
3. Configure the job as script-only with no_agent=true. It must not call an LLM or start an agent session during normal runs.
4. The Python script must send each new signal and PNG chart directly to the Discord channel webhook in EMA_CROSS_DISCORD_WEBHOOK_URL.
5. Keep cron delivery local or otherwise disabled for ordinary output so Discord does not receive duplicate scheduler messages.
6. Empty stdout means a healthy no-signal run and must remain silent.
7. Nonzero exit means a real operational failure and should trigger the scheduler's normal error alert.
8. Do not put the webhook URL inside the cron definition, command line, logs, or prompt.
9. Run the cron manually once, inspect its actual status, and verify the run log changed.
10. Confirm that the recurring job has no model override, no skills, and no unnecessary toolsets.
Before creating anything, inspect the actual scanner command and Hermes cron capabilities on this installation. After creation, return the job name, job ID, schedule, script path, no_agent value, delivery mode, and the result of the manual verification run.
5. Verification and failure-test prompt
A signal system is not finished just because the happy path works. This prompt asks Hermes to prove that duplicate alerts, missing charts, stale candles, and failed Discord uploads are handled correctly.
Audit the EMA20 and EMA50 daily crossover project at [PROJECT_PATH] as an operational research system.
Do not redesign the strategy. Verify the current implementation with real commands and test fixtures.
Confirm all of the following:
1. Only completed daily candles can generate signals.
2. Bullish and bearish crossover logic uses the previous and newest completed candles exactly as specified.
3. Re-running the same candle cannot send a duplicate alert.
4. A Discord signal is not marked delivered unless both the message and PNG attachment succeed.
5. The chart contains price, EMA20, EMA50, and the signal marker.
6. No webhook secret appears in source, logs, process arguments, or test output.
7. Normal scheduled runs use deterministic Python and no AI tokens.
8. The Hermes cron is script-only with no_agent=true and has no unnecessary model, skills, or toolsets.
9. Healthy no-signal runs are silent.
10. Data, Discord, or chart failures exit nonzero and leave useful bounded diagnostics.
11. The append-only run log and atomic deduplication state remain valid after an interrupted write.
12. The README matches the actual commands and file paths.
Run the focused tests, dry-run mode, and a simulated Discord failure. Inspect the newest log records and generated chart. Return a pass or fail checklist backed by the real command output. Fix any failure you find, rerun the checks, and report the final verified state.
6. Expected Discord alert
LONG · SPY · Daily
Completed candle: 2026-07-22
Close: 000.00
EMA20: 000.00
EMA50: 000.00
Version: ema20_ema50_daily_v1
The message should include a PNG chart with the closing-price series, both EMAs, and a marker on the crossover candle.
Illustrative format only. Research alert only, not financial advice.7. Operating checklist
- Start with one symbol and confirm the daily close time.
- Run synthetic crossover tests before relying on current market data.
- Send one clearly labeled test alert to the correct Discord channel.
- Confirm the chart opens and the signal candle is correct.
- Confirm a second run stays silent and does not duplicate the alert.
- Review the JSONL log and deduplication state.
- Check the cron record and verify
no_agent=true. - Keep the system in research mode until you have enough observations and a separate risk plan.
8. What this starter system does not do
It does not size positions, model commissions or slippage, place orders, manage portfolio exposure, or prove profitability. Those are separate engineering and research stages. The purpose of this tutorial is to teach a clean operating pattern: deterministic strategy logic, scheduled Python, durable evidence, deduplicated alerts, and charts delivered to the right Discord channel.
Daily EMA Scanner FAQ
Does the recurring cron use AI tokens?
No. The prompts require a script-only Hermes cron with no_agent=true. Deterministic Python handles data, calculations, logs, charts, and Discord delivery. AI is reserved for setup, review, or troubleshooting.
Does this system place trades?
No. This starter tutorial creates research alerts only. Broker execution, risk sizing, and portfolio controls are outside its scope.
Why must every signal include a chart?
The chart makes the crossover easier to inspect and creates a visual artifact for review. If chart upload fails, the prompt requires the complete alert delivery to fail rather than silently sending incomplete evidence.
Can I change the symbol?
Yes. Start with one symbol supported by the selected data provider. Confirm its timezone, session, and daily candle close before scheduling the scan.
Turn your strategy rules into a monitored workflow.
Elijah can help map the logic, build the Python scanner, connect Discord, structure the logs, schedule the operations, and document the handoff.
Engineering and educational content only. No strategy or profitability guarantee.