Data Flow Explained
Of course. This is an excellent project to break down. Let's walk through the entire process step-by-step, following the flow of data from a simple stock price list to a fully trained trading model.
The Big Picture: What is this code trying to do?¶
Imagine you want to create an automated stock trader. Instead of programming it with fixed rules like "buy if the price goes up for 3 days," you want it to learn the best rules on its own.
This code uses a technique inspired by biological evolution to build that trader. It creates a population of slightly different "trading brains" (neural networks), tests how well each one performs on historical data, and then combines the traits of the best performers to create a new, slightly better generation. After thousands of these "generations" (epochs), you are left with a highly evolved trading brain.
The Detailed Data Flow: A Step-by-Step Walkthrough¶
Let's assume you run the script from your terminal like this:
python your_script.py --symbol NVDA --period 5y --epochs 10000
Phase 1: Setup and Data Acquisition¶
- User Input: The script starts.
argparsereads your command: you want to analyze NVIDIA (NVDA) using 5 years of data and train for 10,000 epochs. - Data Download: The
Agentclass is initialized. It calls theyfinancelibrary to download 5 years of historical data for NVDA. Let's say it gets 1,259 days of data. - Data Extraction: The code only cares about one column: the
Closeprice. It extracts this into a long list of numbers. This is our raw material.- Raw Data (
self.trend):[25.50, 26.10, 25.95, 26.80, ..., 480.50]
- Raw Data (
Phase 2: Building the "Trading Brain"¶
- The Brain's Structure (
Modelclass): A neural network is created. Think of it as a decision-making machine with many tunable "knobs" (called weights and biases).- Input Layer: It's designed to receive
window_size - 1(e.g., 49) numbers. - Hidden Layers: It has internal layers (
[64, 32, 16]) that process the information in complex, non-linear ways. - Output Layer: It produces 3 scores, one for each possible action:
[Score_Hold, Score_Buy, Score_Sell].
- Input Layer: It's designed to receive
- Initial State: At the beginning, all the "knobs" (weights) in this brain are set to random values. It is essentially "unborn" and knows nothing. Its initial decisions will be meaningless.
Phase 3: The Evolutionary Training Cycle (The Core Logic)¶
This is where the learning happens. The script enters a loop that runs for epochs (10,000) iterations. Each iteration is like one generation of evolution. Let's look at a single generation:
Step 3.1: Create a Population (The "Children")
* The Deep_Evolution_Strategy class takes the current "parent" brain.
* It creates a large population (e.g., 50) of "children." Each child is an almost-perfect copy of the parent, but with its weights and biases "jiggled" or "mutated" slightly by adding small random numbers.
* You now have 50 slightly different trading brains, each with a unique strategy.
Step 3.2: Survival of the Fittest (The "Test")
* Now, we must determine which of these 50 children is the "fittest." This is the job of the get_reward function.
* For each of the 50 children, the code runs a full simulation over the 5 years of NVDA data:
* Day 50: The simulation starts. The code looks at the first 50 days of prices. It doesn't use the prices directly. Instead, it calculates the 49 daily price changes (get_state). This sequence of changes is the input fed into the child's brain.
* Data Transformation: [25.50, 26.10, ...] becomes [+0.60, -0.15, +0.85, ...]. This is the state.
* The Decision: The brain processes these 49 numbers and outputs 3 scores, e.g., [-0.4, 1.8, 0.2]. The code finds the highest score (np.argmax). In this case, the second score is highest, so the action is "Buy" (index 1).
* The Judgment: The code then peeks at the next day's price (Day 51). Did the price actually go up by 1% or more?
* If YES, the child made a good decision. It gets +1 point.
* If NO, it gets 0 points.
* Day 51: The process repeats. The code looks at the price changes from Day 2 to Day 51, feeds it to the brain, gets a new decision ("Hold," "Buy," or "Sell"), and judges it against what happened on Day 52.
* This continues until the end of the 5-year data. The child's final score is the total number of points it earned.
Step 3.3: Evolution (The "Update") * After all 50 children have been tested and scored, we have a list of 50 "fitness scores." * The algorithm gives more importance to the mutations from the high-scoring children. It calculates a weighted average of all the random mutations, where the weights are the fitness scores. * The original "parent" brain's weights are then nudged slightly in this "successful" direction. * The parent has now evolved. It has incorporated the successful random tweaks of its best offspring.
Step 3.4: Repeat * This entire cycle—Create Population, Test, Evolve—repeats for 10,000 generations. With each generation, the parent brain gets incrementally better at making predictions that would have earned points on the historical data.
Phase 4: Analysis and Reporting¶
- Checkpoints: The training doesn't run for 10,000 epochs straight. It pauses at
checkpointintervals (e.g., every 200 epochs). - Logging Performance (
StrategyAnalyzer): At each pause, theStrategyAnalyzertakes the current, evolved parent brain. It runs another full simulation on the 5-year data. - Detailed Stats: This time, it's not just counting points. It's logging every detail:
- How many times did it decide to "Buy"? What percentage of those were correct?
- How many times did it decide to "Sell"? What was its success rate?
- Same for "Hold."
- What was the overall success rate?
- Output: This detailed analysis is printed in a clean table. Furthermore, a list of every single successful prediction (e.g., "On 2022-05-10, it predicted BUY, and the price rose 2.5%") is saved to a CSV file. This allows you to see what the model is learning.
Phase 5: Finalization¶
- Summary: After all 10,000 epochs are complete, a final summary table showing the performance at every checkpoint is printed and saved to a CSV.
- Saving the Brain: Most importantly, the final, fully-trained weights and biases of the "champion" brain are saved to a
.npzfile. This file contains the complete, evolved intelligence of the trading model, ready to be loaded and used on new, unseen data.
You are absolutely right! Thank you for catching that. I see the last remaining "Unsupported" box in the center of the "Fitness Test Simulation" subgraph.
My apologies for the oversight. Let's correct that final piece.
The Final "Unsupported" Box¶
- Location: The diamond-shaped (decision) box inside the "Fitness Test Simulation (get_reward)" subgraph.
- What it Represents: This is the core of the simulation. It represents the loop that iterates through every single day of the 5-year historical data to test how a "child" model performs. The diamond shape signifies the decision at each step: "Are there more days to process?"
- The Correct Text Should Be:
For each day 't' in the 5-year history...
The Final, Fully Corrected Diagram Script¶
For completeness, here is the final version of the Mermaid script with all the text correctly filled in. This should now perfectly match the intended logic.
graph TD
subgraph "Phase 1: Setup"
A[Start: User executes script e.g., python main.py --symbol NVDA] --> B{Parse Command-Line Arguments};
B --> C[Agent Initialization];
C --> D["Download 5 years of NVDA data via yfinance"];
D --> E["Extract 'Close' price into a list of numbers"];
end
subgraph "Phase 2: Model Creation"
F["Initialize Neural Network Model ('The Brain')"];
F --> G["Set all weights/biases to random initial values"];
end
subgraph "Phase 3: The Training Loop"
H{For each batch of Epochs...};
subgraph "Evolutionary Cycle (One Generation)"
I["<b>1. Create Population:</b><br>Make 50 'child' models by slightly<br>mutating the 'parent' model's weights"];
I --> J{"<b>2. Test Fitness: For EACH of the 50 children..."};
subgraph "Fitness Test Simulation (get_reward)"
J --> K{"For each day 't' in the 5-year history..."};
K -- Loop Body --> L[On each day 't', get the last<br>49 price changes as 'state'];
L --> M[Feed 'state' into child's brain<br>to get an action: Hold/Buy/Sell];
M --> N{Check if action was correct<br>based on price on day 't+1'};
N -- Yes --> O[Add +1 to child's fitness score];
N -- No --> P[Add 0 to score];
O --> Q{Continue to next day};
P --> Q;
Q --> K;
end
K -- Loop Finished --> R[End of simulation, child has a final score];
R --> S["<b>3. Evolve:</b><br>Update the 'parent' model's weights<br>based on the scores of all 50 children"];
end
H --> I;
end
subgraph "Phase 4: Analysis"
S --> T{Checkpoint reached?};
T -- Yes --> U[StrategyAnalyzer: Test the current parent model on the 5-year data];
U --> V["Log detailed stats: Buy/Sell/Hold counts and success rates"];
V --> W["Save all *successful* predictions to a checkpoint CSV file"];
W --> H;
T -- No --> H;
end
subgraph "Phase 5: Finalization"
H -- All Epochs Done --> X["Print & Save Final Summary of all Checkpoints"];
X --> Y["Save the final, trained model weights to a .npz file ('The Champion Brain')"];
Y --> Z[End: Process Complete];
end
%% --- Connections between main phases ---
E --> F;
G --> H;
¶
graph TD
subgraph "Phase 1: Setup"
A[Start: User executes script e.g., python main.py --symbol NVDA] --> B{Parse Command-Line Arguments};
B --> C[Agent Initialization];
C --> D["Download 5 years of NVDA data via yfinance"];
D --> E["Extract 'Close' price into a list of numbers"];
end
subgraph "Phase 2: Model Creation"
F["Initialize Neural Network Model ('The Brain')"];
F --> G["Set all weights/biases to random initial values"];
end
subgraph "Phase 3: The Training Loop"
H{For each batch of Epochs...};
subgraph "Evolutionary Cycle (One Generation)"
I["<b>1. Create Population:</b><br>Make 50 'child' models by slightly<br>mutating the 'parent' model's weights"];
I --> J{"<b>2. Test Fitness: For EACH of the 50 children..."};
subgraph "Fitness Test Simulation (get_reward)"
J --> K{"For each day 't' in the 5-year history..."};
K -- Loop Body --> L[On each day 't', get the last<br>49 price changes as 'state'];
L --> M[Feed 'state' into child's brain<br>to get an action: Hold/Buy/Sell];
M --> N{Check if action was correct<br>based on price on day 't+1'};
N -- Yes --> O[Add +1 to child's fitness score];
N -- No --> P[Add 0 to score];
O --> Q{Continue to next day};
P --> Q;
Q --> K;
end
K -- Loop Finished --> R[End of simulation, child has a final score];
R --> S["<b>3. Evolve:</b><br>Update the 'parent' model's weights<br>based on the scores of all 50 children"];
end
H --> I;
end
subgraph "Phase 4: Analysis"
S --> T{Checkpoint reached?};
T -- Yes --> U[StrategyAnalyzer: Test the current parent model on the 5-year data];
U --> V["Log detailed stats: Buy/Sell/Hold counts and success rates"];
V --> W["Save all *successful* predictions to a checkpoint CSV file"];
W --> H;
T -- No --> H;
end
subgraph "Phase 5: Finalization"
H -- All Epochs Done --> X["Print & Save Final Summary of all Checkpoints"];
X --> Y["Save the final, trained model weights to a .npz file ('The Champion Brain')"];
Y --> Z[End: Process Complete];
end
%% --- Connections between main phases ---
E --> F;
G --> H;graph TD
subgraph "Phase 1: Setup"
A[Start: User executes script e.g., python main.py --symbol NVDA] --> B{Parse Command-Line Arguments};
B --> C[Agent Initialization];
C --> D["Download 5 years of NVDA data via yfinance"];
D --> E["Extract 'Close' price into a list of numbers"];
end
subgraph "Phase 2: Model Creation"
F["Initialize Neural Network Model ('The Brain')"];
F --> G["Set all weights/biases to random initial values"];
end
subgraph "Phase 3: The Training Loop"
H{For each batch of Epochs...};
subgraph "Evolutionary Cycle (One Generation)"
I["<b>1. Create Population:</b><br>Make 50 'child' models by slightly<br>mutating the 'parent' model's weights"];
I --> J{2. Test Fitness: For EACH of the 50 children...};
subgraph "Fitness Test Simulation (get_reward)"
J --> K{"For each day 't' in the 5-year history..."};
K -- Loop Body --> L[On each day 't', get the last<br>49 price changes as 'state'];
L --> M[Feed 'state' into child's brain<br>to get an action: Hold/Buy/Sell];
M --> N{Check if action was correct<br>based on price on day 't+1'};
N -- Yes --> O[Add +1 to child's fitness score];
N -- No --> P[Add 0 to score];
O --> Q{Continue to next day};
P --> Q;
Q --> K;
end
K -- Loop Finished --> R[End of simulation, child has a final score];
R --> S["<b>3. Evolve:</b><br>Update the 'parent' model's weights<br>based on the scores of all 50 children"];
end
H --> I;
end
subgraph "Phase 4: Analysis"
S --> T{Checkpoint reached?};
T -- Yes --> U[StrategyAnalyzer: Test the current parent model on the 5-year data];
U --> V["Log detailed stats: Buy/Sell/Hold counts and success rates"];
V --> W["Save all *successful* predictions to a checkpoint CSV file"];
W --> H;
T -- No --> H;
end
subgraph "Phase 5: Finalization"
H -- All Epochs Done --> X["Print & Save Final Summary of all Checkpoints"];
X --> Y["Save the final, trained model weights to a .npz file ('The Champion Brain')"];
Y --> Z[End: Process Complete];
end
%% --- Connections between main phases ---
E --> F;
G --> H;