What you will build.
Use a fictional BTC/USD position with a 100-unit collateral allocation. Your task is not to open a trade: build a review record that refuses to use an expired observation or an unresolved position outcome. The venue supplies its own matching, margin, funding-rate and liquidation systems.
Your working record
Create a private worksheet with columns for the source reference, observed state, responsible system, observation time, expected result and unresolved issue. Use the same fictional case throughout the steps; do not paste live personal or financial records into this exercise.
Run the example before changing it.
Inspect the baseline record below. Download and read the complete JavaScript file before running it. It uses only Node’s built-in test and assertion modules; there is no package installation, account connection or secret to configure.
{
"observationAge": 2,
"freshnessLimit": 5,
"marginReviewed": true,
"outcomeKnown": true
}Save it as perpetuals-trading.mjs. Open a terminal in that folder and run:
node --version
node --test perpetuals-trading.mjsExpected result: four passing tests and zero failures. These tests verify the teaching classifier only. They do not verify a production integration, security boundary or financial outcome.
File or test runner will not start?
Check that Node.js 22 or later is installed, the filename ends in .mjs rather than .mjs.txt, and your terminal is in the download folder. If a managed browser blocks scripts, open “Read the full exercise” and save that text locally under the same filename. Do not disable organizational security controls.
Read the full exercise
// Hybrid-Chain offline teaching model: perpetuals-trading
// Fictional fields/states; NOT an API client, authorization system or production implementation.
// No network calls, credentials, payments or file writes. Review before running.
// Requires Node.js 22+. Run: node --test perpetuals-trading.mjs
import test from 'node:test';
import assert from 'node:assert/strict';
export function inspect(record) {
if (record.observationAge > record.freshnessLimit) return 'STALE_PRICE';
if (!record.marginReviewed) return 'RISK_REVIEW_REQUIRED';
if (!record.outcomeKnown) return 'OUTCOME_UNRESOLVED';
return 'REVIEWABLE_SIMULATION';
}
const baseline = {
"observationAge": 2,
"freshnessLimit": 5,
"marginReviewed": true,
"outcomeKnown": true
};
const cases = [
{
"name": "baseline is reviewable, not executable",
"patch": {},
"expected": "REVIEWABLE_SIMULATION"
},
{
"name": "stale source",
"patch": {
"observationAge": 6
},
"expected": "STALE_PRICE"
},
{
"name": "missing risk review",
"patch": {
"marginReviewed": false
},
"expected": "RISK_REVIEW_REQUIRED"
},
{
"name": "unknown outcome",
"patch": {
"outcomeKnown": false
},
"expected": "OUTCOME_UNRESOLVED"
}
];
for (const example of cases) {
test(example.name, () => {
assert.equal(inspect({...baseline, ...example.patch}), example.expected);
});
}
Know what the tests demonstrate
- baseline is reviewable, not executable
REVIEWABLE_SIMULATION- stale source
STALE_PRICE- missing risk review
RISK_REVIEW_REQUIRED- unknown outcome
OUTCOME_UNRESOLVED
Now change one fixture at a time. If you change a case’s input without changing its expected result, the test should fail. Read the actual-versus-expected difference and use the walkthrough to decide whether your rule or your expectation needs correcting. Keep an unchanged copy for comparison.
Work through the case, step by step.
- 01
Write the instrument worksheet
Do this
- Create a row labelled DEMO-PERP-01; use fictional figures and mark the entire worksheet SIMULATION.
- Record the instrument, price-source reference, observation time and freshness limit as different fields.
- Add separate owners for matching, margin, funding and liquidation. Mark each unavailable integration as a dependency.
Expected resultYou can explain every field without suggesting that a price feed or barrier-product record operates a perpetuals venue.
If your result is different
If an owner or instrument rule is unknown, leave the value unresolved; do not fill it with a platform product name.
- 02
Reject stale input before reviewing the position
Do this
- Start with the local model's observationAge=2 and freshnessLimit=5, both expressed in the same fictional time unit.
- Run the exercise, then change observationAge to 6. The result must change to STALE_PRICE.
- In your integration plan, identify the actual source timestamp and clock policy that would replace those fixture values.
Expected resultA readable price is not automatically an acceptable price; the freshness boundary is explicit and testable.
If your result is different
If changing the observation age does not change the result, check the comparison and units before adding any later stage.
- 03
Separate risk review from outcome evidence
Do this
- Set marginReviewed=false and confirm the model returns RISK_REVIEW_REQUIRED.
- Restore the baseline and set outcomeKnown=false; the review must remain incomplete.
- Add links or private references to the risk decision and final position evidence in separate worksheet columns.
Expected resultThe record distinguishes an accepted observation, a risk decision and a known outcome instead of one green status.
If your result is different
If the application only has a combined success flag, split it before attempting to explain a funding or liquidation dispute.
- 04
Turn the model into an integration backlog
Do this
- Keep the successful local result REVIEWABLE_SIMULATION; it deliberately does not say executable or settled.
- List the actual contract needed for each worksheet field and record which source is authoritative.
- Save the worksheet and test output, then ask the venue team to review the missing risk-engine and operational controls.
Expected resultYou finish with a concrete evidence model and missing-system list, not an implied funded-trading capability.
If your result is different
Do not replace unresolved integrations with the local classifier. It has no market, balance, margin or liquidation engine.
Review what you produced.
Save the worksheet, unmodified test output, one deliberately failing case and the explanation of its fix. A useful result includes an unresolved item with an owner; it is not just a screenshot of four green tests.
Map the model to actual systems.
The venue must supply or separately contract matching, margin, funding-rate calculation, liquidation, customer protection, and operational supervision. Confirm product eligibility and legal responsibilities with qualified advisers.
For each worksheet field, name the owning system, exact current operation, permission and error behavior. Put “not available” next to any missing operation and assign a dependency owner. Do not substitute the teaching classifier for that missing integration.
Open the current API reference and inspect each operation’s request, response, scope and implementation status. Code examples on this page are local models only; they do not call those operations.
Take the next technical step.
Use your worksheet and failing-case notes in the next walkthrough. Keep the same reference trail so you can see which assumptions become actual observations—and which remain dependencies.
Practice tracing an execution result