Bring your strategy. Change ~2 lines. Your source code never leaves our server.
Your bot doesn't talk to an exchange directly and never holds API keys. Instead it submits orders to our SDK, and our broker executes them at the real price on the correct account β your account for your live track record, and each customer's account for their copy. That's what lets us give every bot a verified record (independently recorded by us) while keeping your code private.
The one rule for renting: your bot must place its orders through the CodeVaultEx SDK (vault.ccxt().create_order(...) or vault.place_order(...)) as its main order path β not by calling the exchange API directly with its own key.
Why: when a customer rents your bot, their copy runs without any API key inside it (we never put a renter's keys in your code β that's what keeps them safe). A bot that trades the exchange directly has nothing to authenticate with in a renter's copy, so it silently does nothing for them. A bot that goes through the SDK works everywhere: our broker executes each order on the right account with that person's key, which never touches your code.
If you don't: your bot still runs fine on your account and builds its verified track record β but it will show as βNot yet available to rentβ in your dashboard and no one can subscribe to it until you route execution through the SDK. Kalshi, OANDA, Tradier and other βplace the order yourselfβ bots especially need this change.
Keep all your strategy logic. Just route execution through vault:
import vault
ex = vault.ccxt() # drop-in ccxt-style client β no API keys needed
price = get_price("BTC/USDT") # your own logic
if my_signal_is_buy:
ex.create_order("BTC/USDT", "market", "buy", vault.size(price)) # sized to the runner's capital
Already using ccxt? Replace ccxt.binance({...keys...}) with vault.ccxt("binance") and delete your keys β your existing create_order(...) calls keep working. Always pass your venue to vault.ccxt(venue) (it defaults to coinbase) so orders route to the right exchange.
The same SDK works for non-crypto venues β pass the venue and size in whole units. Pick the market in your own logic; the broker fills it on the correct account.
Kalshi β buy/sell whole contracts on a market ticker (price is dollars, 0.00β1.00, so int(vault.size(price)) sizes to capital automatically):
import vault
ex = vault.ccxt("kalshi") # route through the platform β no Kalshi key in your code
ticker = pick_market() # your logic β a Kalshi market ticker (this picks the YES side)
price = get_yes_price(ticker) # 0.00β1.00 (dollars per contract)
count = int(vault.size(price)) # whole contracts, sized to the runner's capital
if my_signal_is_buy and count > 0:
ex.create_order(ticker, "market", "buy", count) # enter the position
# ... later, to close:
ex.create_order(ticker, "market", "sell", count) # exit
Betting the NO side? Append |no to the ticker β e.g. ex.create_order(ticker + "|no", "market", "buy", count) β and the broker places the correct leg and records your fill at the NO price. A plain ticker always means YES. Use the same ticker + "|no" when you sell to close that position.
Forex (OANDA) β signed units; use a dashed pair (the broker converts EUR-USD β EUR_USD). Your OANDA account id is the key you connect:
import vault
ex = vault.ccxt("oanda")
units = int(vault.size(rate)) # base-currency units, sized to capital (rate = the FX price)
if my_signal_is_buy and units > 0:
ex.create_order("EUR-USD", "market", "buy", units) # long (+units)
ex.create_order("EUR-USD", "market", "sell", units) # short / close (-units)
Replace your direct Kalshi/OANDA API calls with these β don't keep both. A bot that still calls the exchange directly with its own key can't trade for renters (their copy has no key), so it stays un-rentable. See What makes a bot rentable.
Paper mode works on every venue. In paper mode we fill your orders at live market prices from public data (Kalshi order books, stock & forex quotes) with an estimated-cost haircut β so you can run any bot risk-free and build a self-reported record before going live. Paper results are always labeled self-reported; only real execution is marked verified.
vault.capital() β the capital of whoever is running this copy (the customer, or you for live proof).vault.size(price, risk_pct=2) β quantity sized to that capital (e.g. 2% per trade). Use this instead of a fixed amount so your bot scales to every customer automatically.vault.ccxt(venue="coinbase") β a ccxt-compatible client whose create_order(symbol, "market", side, amount) routes safely through the broker.vault.place_order(market, side, qty, venue) β lower-level order submit (returns the fill).vault.record_trade(...) β optional self-reported trade (marked unverified; prefer real orders).Supported venues: any major exchange (coinbase, binance, kraken, bybit, okx, kucoin, β¦). Pass the venue to vault.ccxt("binance").
When you list, you choose how your public record is built:
Either way the record is verified by our broker and can't be faked. Live simply carries more weight.
main.py at the top level (or a Dockerfile for any language).requirements.txt β we build your dependencies automatically.import time, vault
MARKET, VENUE = "BTC-USD", "coinbase"
ex = vault.ccxt(VENUE)
def price():
# your data/indicator logic here
...
while True:
p = price()
if buy_signal(p):
ex.create_order(MARKET, "market", "buy", vault.size(p, risk_pct=2))
elif sell_signal(p):
ex.create_order(MARKET, "market", "sell", vault.size(p, risk_pct=2))
time.sleep(60)