agentleFS
MendurimMendurim/strikegrok-trading-desk/skills/strike-orders/SKILL.md

strike-orders

Skill0 starsChanged 2 months agoMITView on GitHub

Placing, protecting and cancelling Strike Finance orders through the signed REST API - limit, market with a slippage bound, bracket strategy orders with attached take-profit and stop-loss, standalone triggers, trailing stops, replace, cancel, client order ids, rounding, and reading the order back from the exchange. Use when executing an approved ticket, attaching protection to a position, or amending a resting order. Write paths - Execution Trader only, after a Risk PASS and the user's approval by ticket id.

The file

We split this skill into the rules it gives an agent

9 rules. About 0 are common, 4 are distinctive, and 5 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈4

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 5

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Every endpoint here writes.

    line 14
  2. Very specific:

    All of these must be true.

    line 22
  3. Very specific:

    Every order carries a client_order_id the desk chooses.

    line 90
  4. Distinctive:

    Use it for an unfilled entry the user has re-priced.

    line 159
  5. Distinctive:

    No entry without a stop in the same strategy order.

    line 174
  6. Very specific:

    No market order without a slippage bound.

    line 175
  7. Distinctive:

    No send whose body differs from the previewed block.

    line 176
  8. Very specific:

    No resend on an unknown result - look it up by client order id first (desk-execution-protocol).

    line 178
  9. Distinctive:

    No size rounded up to clear a minimum, and no leverage raised to make a ticket fit.

    line 179

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Strike orders

Every endpoint here writes. Read strike-auth first: signing, the API wallet and the strike_request.py helper live there, and none of it is repeated below.

Who may run this: the Execution Trader, on a ticket carrying a Risk Manager PASS and the user's approval line by id. Nobody else, for any reason.

Symbols here are the same -USD symbols the Price Service uses. There is no translation on this desk.

1. Before any send

All of these must be true. Same pre-send checklist as desk-execution-protocol, in this API's terms.

  1. The proposal file carries a Risk PASS and the user's approve <ticket id> line.
  2. Live equity and positions read this minute: GET /v2/account, GET /v2/positions.
  3. size respects the market's LOT_SIZE.stepSize; notional clears MIN_NOTIONAL.notional.
  4. price respects PRICE_FILTER.tickSize.
  5. Leverage on the symbol already equals the ticket's (strike-positions), set before the entry.
  6. A fresh client_order_id is generated, written to the proposal file before the send.
  7. The preview block has been posted to the floor and matches the ticket field for field (section 3).

2. Rounding

Constraints come from the market, not from memory: GET /v2/exchangeInfo on the Price Service gives tickSize, stepSize and MIN_NOTIONAL per symbol.

Round size down, never up: rounding up spends risk budget the ticket did not authorise. Round price to the tick in the direction that does not flatter your own fill assumption.

python3 -c "
from decimal import Decimal, ROUND_DOWN
qty, step = Decimal('1234.87'), Decimal('1')      # ADA-USD trades in whole tokens
print((qty / step).to_integral_value(rounding=ROUND_DOWN) * step)
"

A size that rounds to zero, or to a notional under the minimum, is a reject the Execution Trader reports. Never a size nudged up to clear the floor.

Sizes and prices are strings in this API. Send "4800", not 4800.

3. The preview block replaces a dry run

The API has no dry-run mode. Nothing stops a POST but the desk's own discipline, so that discipline is written down and mandatory.

Before every send, build the exact request body, save it to a file, and post its contents to the floor as a PREVIEW block beside the ticket. Send only after the user's approval line refers to that ticket id. The bytes sent must be the bytes previewed.

cat > /workspace/trading-desk/proposals/SG-20260910-01-entry.json <<'JSON'
{
  "strategy_id": "SG-20260910-01",
  "client_order_id": "SG-20260910-01-entry",
  "symbol": "ADA-USD",
  "side": "buy",
  "type": "limit",
  "size": "4800",
  "price": "0.2100",
  "time_in_force": "GTC",
  "sl_order": {
    "client_order_id": "SG-20260910-01-sl",
    "type": "stop",
    "size": "4800",
    "stop_price": "0.1995",
    "working_type": "mark_price"
  },
  "tp_order": {
    "client_order_id": "SG-20260910-01-tp",
    "type": "take_profit",
    "size": "4800",
    "stop_price": "0.2310",
    "working_type": "mark_price"
  }
}
JSON
cat /workspace/trading-desk/proposals/SG-20260910-01-entry.json   # this is the PREVIEW block

Because the file is the request, a preview that differs from the send is a bug the desk can see, not a story it tells.

4. Client order ids

Every order carries a client_order_id the desk chooses. Derive it from the ticket: SG-20260910-01-entry, -sl, -tp, -B-entry for a follow-up ticket. Unique, never reused.

This is the desk's most important reconciliation handle. GET /v2/order?client_order_id=... answers authoritatively whether an order exists, so a send whose response was lost is a lookup, not a guess. Write the id into the proposal file before the send, not after.

Brackets also take a strategy_id, which the desk sets to the ticket id, and a client_order_id per leg.

5. The order shapes

Bracket strategy - the desk's default for a new position

POST /v2/order/strategy. Entry plus take-profit plus stop-loss in one request; the exit legs arm after the entry fills, so they cannot be rejected for having no position to reduce.

python3 scripts/strike_request.py POST /v2/order/strategy \
  --body-file /workspace/trading-desk/proposals/SG-20260910-01-entry.json
  • side is buy or sell for the entry; Strike sets the exit legs opposite and reduce-only.
  • Leg type: stop / stop_limit for the SL, take_profit / take_profit_limit for the TP. The plain forms fill at market on trigger; the _limit forms rest at price after triggering and can fail to fill on a fast move. The desk's default for a stop is stop - a stop that might not fill is not protection, which is exactly why the Risk Manager sizes on a stressed stop.
  • working_type decides what the trigger watches: mark_price (default, and what liquidation settles against) or contract_price. The desk uses mark_price and says so on the ticket.
  • A ticket without a stop does not reach this skill.

Limit entry

POST /v2/order with type: "limit". Add post_only: true when the ticket calls for maker-only - the order is rejected rather than crossing. No attached protection, so prefer a bracket unless the ticket has a reason.

Market entry, with a bound

POST /v2/order with type: "market" and slippage set - a decimal fraction, e.g. "0.005" for 50 bps. Always set it. An unbounded market order on a thin book is how a desk loses more than its ticket said.

Protection on a position that already exists

POST /v2/order with type: "stop" or "take_profit", reduce_only: true, stop_price, and working_type: "mark_price". side is the side of the closing order: sell protects a long, buy protects a short.

close_position: true closes the whole position on trigger regardless of the size field, which keeps protection correct after a partial fill or an add. Prefer it for a stop that is meant to flatten.

Trailing stop

type: "trailing_stop_market" with callback_rate (a percentage, "0.1" to "5") and optionally activation_price. Available, and used only when the ticket says so - a trailing stop changes the risk the Risk Manager sized, so it is a ticket decision, never an execution flourish.

6. The send, and reading it back

Send once. No retry loop. A finite timeout.

python3 scripts/strike_request.py POST /v2/order/strategy --body-file <ticket>.json

Then confirm from the exchange, because the response is a claim and the record is the fact:

python3 scripts/strike_request.py GET /v2/order --query client_order_id=SG-20260910-01-entry
python3 scripts/strike_request.py GET /v2/openOrders
python3 scripts/strike_request.py GET /v2/positions
python3 scripts/strike_request.py GET /v2/history/fill --query symbol=ADA-USD --query limit=20

Report the exchange's numbers: status, filled price and size, order ids, fees, and whether protection is actually resting. Order status values are 2 open, 3 filled, 4 canceled, 5 untriggered, 6 rejected, 7 expired. A resting stop that has not fired is 5, not 2 - a check that counts only 2 will call a protected position unprotected.

A bracket whose entry filled but whose exit legs are not resting is an unprotected position. Incident, immediately, under desk-incident-response.

7. Replace and cancel

POST /v2/order/replace cancels and re-places atomically: cancel takes {order_id, symbol}, new_order is a full order object with a new client_order_id.

python3 scripts/strike_request.py POST /v2/order/replace --body-file amend.json

Use it for an unfilled entry the user has re-priced. For protection, prefer place-new, confirm-resting, then cancel-old, so the position is never unprotected even briefly - an atomic replace that fails leaves nothing behind.

DELETE /v2/order/cancel takes order_id (integer) and symbol. It does not accept a client order id, so look the numeric id up in GET /v2/openOrders or GET /v2/order?client_order_id=... first.

python3 scripts/strike_request.py GET /v2/openOrders
python3 scripts/strike_request.py DELETE /v2/order/cancel --body-file cancel.json

Cancelling protection on a position that stays open increases risk and needs approval like anything else.

DELETE /v2/order/cancel-all is in strike-advanced, and is not a reflex.

8. What this desk does not do

  • No entry without a stop in the same strategy order.
  • No market order without a slippage bound.
  • No send whose body differs from the previewed block.
  • No reused client_order_id.
  • No resend on an unknown result - look it up by client order id first (desk-execution-protocol).
  • No size rounded up to clear a minimum, and no leverage raised to make a ticket fit.
  • No vault_id. The desk trades the user's own account only.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.