2026-08-01 11:27:28 -04:00
|
|
|
# AI/ — neural network subsystem
|
|
|
|
|
|
|
|
|
|
The engine behind the four AI signal modules (`CSignalPAI`, `CSignalCONV`,
|
|
|
|
|
`CSignalLSTM`, `CSignalHYBRID`). It is a from-scratch MQL5 network — no external
|
|
|
|
|
ML runtime — with four interchangeable compute tiers behind one interface.
|
|
|
|
|
|
|
|
|
|
## File layout
|
|
|
|
|
|
|
|
|
|
`AI\Network.mqh` is the entry point and the only file anything outside `AI\`
|
|
|
|
|
includes. It holds **declarations only**: the nine core classes, the compile-time
|
|
|
|
|
constants, and the nested include chain that orders them. Each nested `#include`
|
|
|
|
|
sits exactly where its base class becomes visible, so that order is a dependency
|
|
|
|
|
graph, not a preference — do not reorder it.
|
|
|
|
|
|
|
|
|
|
| file | holds |
|
|
|
|
|
|---|---|
|
|
|
|
|
| `Network.mqh` | class declarations, tuning constants, include chain |
|
|
|
|
|
| `Network.cl` | OpenCL kernels (see below) |
|
|
|
|
|
| `NeuronPrimitives.mqh` | `CConnection` / `CArrayCon` — weight storage |
|
|
|
|
|
| `NeuronCPU.mqh` | `CNeuron` — pure-MQL5 dense neuron |
|
|
|
|
|
| `NeuronDirectML.mqh` | `CDirectMLMy` — DirectML + CPU-DLL bridge (`#import`ed DLLs) |
|
|
|
|
|
| `ArrayLayer.mqh` | `CArrayLayer` — the layer collection |
|
|
|
|
|
| `LayerDescription.mqh` | `CLayerDescription` — the topology descriptor |
|
|
|
|
|
| `BufferDouble.mqh` | `CBufferDouble` — host/device buffer |
|
|
|
|
|
| `NeuronOCLConvPool.mqh` | `CNeuronConvOCL`, `CNeuronPoolOCL` |
|
|
|
|
|
| `NeuronBatchNorm.mqh` | `CNeuronBatchNormOCL` — host-side batch norm, all tiers |
|
|
|
|
|
|
|
|
|
|
Method **bodies** live in `AI\Impl\`, included at the bottom of `Network.mqh`
|
|
|
|
|
after every declaration. This is a pure relocation — a body cannot run during
|
|
|
|
|
compilation, and every declaration it could reference is already visible above it.
|
|
|
|
|
|
|
|
|
|
| `AI\Impl\` | holds |
|
|
|
|
|
|---|---|
|
|
|
|
|
| `NeuronBase.mqh` | `CNeuronBase` — init, forward, gradients, activation, persistence |
|
|
|
|
|
| `NeuronConvPool.mqh` | `CNeuronConv`, `CNeuronPool` |
|
|
|
|
|
| `NeuronLSTM.mqh` | `CNeuronLSTM` — gate layers, BPTT |
|
|
|
|
|
| `Layer.mqh` | `CLayer` — element construction from a descriptor or a `.nnw` stream |
|
|
|
|
|
| `NetBuild.mqh` | `CNet` lifecycle: topology construction, OpenCL/DirectML init |
|
|
|
|
|
| `NetForward.mqh` | `feedForward`, `backProp`, `getResults`, logit adjustment |
|
|
|
|
|
| `NetPersistence.mqh` | `CNet::Save` / `CNet::Load` — the `.nnw` format |
|
|
|
|
|
| `NetWeights.mqh` | EMA blend, in-memory snapshot/restore, per-layer learning report |
|
|
|
|
|
| `NeuronOCLBase.mqh` | `CNeuronBaseOCL` |
|
|
|
|
|
| `NeuronOCLLSTM.mqh` | `CNeuronLSTMOCL` — sequence LSTM, fused kernels, BPTT caches |
|
|
|
|
|
|
|
|
|
|
## Compute tiers
|
|
|
|
|
|
|
|
|
|
Selected once at construction and logged; each layer runs entirely on one tier.
|
|
|
|
|
|
|
|
|
|
1. **OpenCL** — `Network.cl`, compiled from the `#resource` at startup.
|
|
|
|
|
2. **DirectML** — `WarriorDML.dll` (D3D12 compute).
|
|
|
|
|
3. **CPU DLL** — `WarriorCPU.dll`, a threaded fallback. Thread count is fixed at
|
|
|
|
|
`CPU_THREADS_PER_NETWORK` per net rather than a share of the machine; see the
|
|
|
|
|
comment on that constant for why a machine-wide budget was wrong.
|
|
|
|
|
4. **Pure MQL5** — no DLL, no GPU. Single backtests run here so a Market build
|
|
|
|
|
(which strips every `#import`) is still able to infer.
|
|
|
|
|
|
|
|
|
|
A Market build (`WARRIOR_MARKET_BUILD`) compiles tiers 2 and 3 out entirely.
|
|
|
|
|
|
|
|
|
|
## Classes
|
|
|
|
|
|
|
|
|
|
- **`CNet`** — owns the layer stack, the forward/backward passes and `.nnw`
|
|
|
|
|
persistence. Note that a `.nnw` pins the **architecture**, not just the
|
|
|
|
|
weights: `Save` writes each layer's activation and `Load` restores it, so a
|
|
|
|
|
head activation changed in source only ever reaches a brand-new topology.
|
|
|
|
|
`EnforceOutputActivation()` re-asserts it after every load.
|
|
|
|
|
- **`CLayer` / `CArrayLayer`** — neuron containers; `CreateElementScaled()` is
|
|
|
|
|
the single construction point for every neuron type, from a descriptor or from
|
|
|
|
|
a file stream.
|
|
|
|
|
- **`CNeuronBase` → `CNeuron` / `CNeuronPool` / `CNeuronConv` / `CNeuronLSTM`** —
|
|
|
|
|
the pure-MQL5 family.
|
|
|
|
|
- **`CNeuronBaseOCL` → `CNeuronLSTMOCL` / `CNeuronConvOCL` / `CNeuronPoolOCL` /
|
|
|
|
|
`CNeuronBatchNormOCL`** — the accelerated family. Despite the `OCL` suffix
|
|
|
|
|
these also drive the DirectML and CPU-DLL tiers.
|
|
|
|
|
|
|
|
|
|
`ENUM_ACTIVATION` is `NONE, TANH, SIGMOID, PRELU`; `ENUM_OPTIMIZATION` is
|
|
|
|
|
`SGD, ADAM`. `NativeActivationCode()` translates to the int code the backends
|
|
|
|
|
share — and deliberately makes `NONE` fall through every backend switch.
|
|
|
|
|
|
|
|
|
|
## Network.cl
|
|
|
|
|
|
|
|
|
|
22 kernels in four groups: dense (`FeedForward`, `CaclOutputGradient`,
|
|
|
|
|
`CaclHiddenGradient`, `UpdateWeightsMomentum/Adam`), conv/pool (`FeedForwardConv`,
|
|
|
|
|
`FeedForwardProof`, `CalcHiddenGradientConv`, `CalcInputGradientProof`,
|
|
|
|
|
`UpdateWeightsConv*`), single-step LSTM (`LSTM_Gates`, `LSTM_State`,
|
|
|
|
|
`LSTM_*Gradient`) and sequence LSTM (`LSTM_SeqStep*`, `LSTM_UpdateWeights*`).
|
|
|
|
|
|
|
|
|
|
Two invariants worth knowing before touching them:
|
|
|
|
|
|
|
|
|
|
- `MIN_ACTIVATION_DERIVATIVE` (1.0e-3f) floors every LSTM gate derivative in both
|
|
|
|
|
gradient kernels. It is already there — do not "add" it.
|
|
|
|
|
- Kernel math is mirrored in `DirectML\WarriorCPU.cpp` and `WarriorDML.cpp`.
|
|
|
|
|
A change to one is a change to all three, or the tiers silently diverge.
|
|
|
|
|
|
|
|
|
|
## Usage
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
CNet *net = new CNet(topology); // CArrayObj of CLayerDescription
|
|
|
|
|
net.feedForward(inputs); // CArrayDouble
|
|
|
|
|
net.backProp(targets, weight);
|
|
|
|
|
net.getResults(out);
|
|
|
|
|
net.Save(path, ...); net.Load(path, ...);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The 3-output classification case is special-cased in `backProp`/`backPropOCL`:
|
|
|
|
|
it computes a joint softmax + cross-entropy gradient across all three neurons
|
|
|
|
|
rather than three independent per-neuron deltas.
|
|
|
|
|
|
|
|
|
|
## Known gaps
|
|
|
|
|
|
|
|
|
|
- No unit tests. Changes are validated by compile + a live era's `dW/W` line
|
|
|
|
|
(`CNet::LayerLearningReport`), which is the only reliable check that a layer is
|
|
|
|
|
actually receiving gradient in the assembled net.
|
|
|
|
|
- No dedicated SoftMax layer; the head is `Dense(SIGMOID)` with the gradient
|
|
|
|
|
short-circuited. See `REFACTOR_NOTES.md` §G for why, and for what would have to
|
|
|
|
|
move together to change it.
|