Documentação
Marketplace
A superfície Marketplace do SDK ajuda usuários técnicos a empacotar algos criados com o SDK, executar a revisão determinística de publicação, publicar versões aprovadas, assinar algos com controles de risco da plataforma e operar comandos de ciclo de vida.
A execução no Marketplace deve usar controles de risco da própria plataforma. O código do autor não recebe credenciais brutas do assinante no runtime gerenciado, e toda ordem de runtime deve passar pelo risk gate da plataforma.
Revisar e enviar um pacote
from investflex import AsyncInvestflexClient
manifest = {
"id": "breakout-rsi",
"name": "Breakout RSI",
"version": "1.0.0",
"entrypoint": "algo:BreakoutRsiAlgo",
"markets": ["BVMF"],
"permissions": {
"marketdata": ["quotes", "candles"],
"execution": ["orders"],
},
"lifecycle": {
"required_commands": [
"start",
"suspend",
"resume",
"cancel",
"cancel_and_flat",
"stop",
],
},
"risk": {
"requires_stop_loss": True,
"requires_stop_gain": True,
"requires_max_position": True,
"requires_max_order_quantity": True,
"requires_max_orders_per_second": True,
},
"dependencies": {
"allowed_imports": [],
"packages": [],
},
"parameters": {
"symbol": {"type": "string", "required": True},
"quantity": {"type": "integer", "minimum": 1, "required": True},
},
}
code = """
from investflex.marketplace import MarketplaceAlgo, AlgoContext
class BreakoutRsiAlgo(MarketplaceAlgo):
async def start(self, ctx: AlgoContext) -> None:
await ctx.lifecycle.heartbeat("started")
async def suspend(self, ctx: AlgoContext) -> None:
await ctx.lifecycle.heartbeat("suspended")
async def resume(self, ctx: AlgoContext) -> None:
await ctx.lifecycle.heartbeat("resumed")
async def cancel(self, ctx: AlgoContext) -> None:
await ctx.lifecycle.stop("cancelled")
async def cancel_and_flat(self, ctx: AlgoContext) -> None:
await ctx.lifecycle.stop("cancelled and flattened")
async def stop(self, ctx: AlgoContext) -> None:
await ctx.lifecycle.stop("stopped")
"""
async with AsyncInvestflexClient.from_token(token, base_url=backend_url) as client:
review = await client.marketplace.review(manifest=manifest, code=code)
print(review["status"], review["score"])
package = await client.marketplace.submit_package(manifest=manifest, code=code)
print(package["package_id"], package["status"])
import { InvestflexClient } from "@investflex/sdk";
const manifest = {
id: "breakout-rsi",
name: "Breakout RSI",
version: "1.0.0",
entrypoint: "algo:BreakoutRsiAlgo",
markets: ["BVMF"],
permissions: {
marketdata: ["quotes", "candles"],
execution: ["orders", "algos"],
},
lifecycle: {
required_commands: [
"start",
"suspend",
"resume",
"cancel",
"cancel_and_flat",
"stop",
],
},
risk: {
requires_stop_loss: true,
requires_stop_gain: true,
requires_max_position: true,
requires_max_order_quantity: true,
requires_max_orders_per_second: true,
},
dependencies: {
allowed_imports: [],
packages: [],
},
parameters: {
symbol: { type: "string", required: true },
quantity: { type: "integer", minimum: 1, required: true },
},
};
const code = `
import {
type AlgoContext,
ManagedExecution,
MarketplaceAlgo,
} from "@investflex/sdk/marketplace";
async function currentPosition(ctx: AlgoContext): Promise<number> {
const positions = ctx.execution?.positions;
if (!positions) return 0;
return Number(await positions.net(ctx.params.symbol));
}
export class BreakoutRsiAlgo extends MarketplaceAlgo {
private readonly execution = new ManagedExecution();
override async start(ctx: AlgoContext): Promise<void> {
for (const _signal of []) {
await ctx.lifecycle.waitIfSuspended();
await ctx.lifecycle.heartbeat("checking signal");
const position = await currentPosition(ctx);
ctx.risk.checkOrder({ quantity: ctx.params.quantity, currentPosition: position });
await this.execution.createOrder(ctx, {
symbol: ctx.params.symbol,
quantity: ctx.params.quantity,
});
}
}
override async suspend(ctx: AlgoContext): Promise<void> {
await this.execution.cancelAllOrders(ctx, "parent suspended");
await this.execution.suspendAllStrategies(ctx, "parent suspended");
await ctx.lifecycle.heartbeat("suspended");
}
override async resume(ctx: AlgoContext): Promise<void> {
await ctx.lifecycle.heartbeat("resumed");
}
override async cancel(ctx: AlgoContext): Promise<void> {
await this.execution.cancelAllOrders(ctx, "parent cancelled");
await this.execution.cancelAllStrategies(ctx, "parent cancelled");
await ctx.lifecycle.stop("cancelled");
}
override async cancelAndFlat(ctx: AlgoContext): Promise<void> {
await this.execution.cancelAndFlat(ctx, {
symbol: ctx.params.symbol,
reason: "parent cancelled and flattened",
});
await ctx.lifecycle.stop("cancelled and flattened");
}
override async stop(ctx: AlgoContext): Promise<void> {
await this.execution.cancelAllOrders(ctx, "parent stopped");
await this.execution.cancelAllStrategies(ctx, "parent stopped");
await ctx.lifecycle.stop("stopped");
}
}
`;
const client = InvestflexClient.fromToken(token, { baseUrl: backendUrl });
const review = await client.marketplace.review({ manifest, code });
console.log(review.status, review.score);
const pkg = await client.marketplace.submitPackage({ manifest, code });
console.log(pkg.package_id, pkg.status);
Publicar e assinar
listing = await client.marketplace.publish_package(
package["package_id"],
description="Estrategia de rompimento validada no simulador.",
)
subscription = await client.marketplace.subscribe(
listing["listing_id"],
account="99999",
parameters={"symbol": "PETR4", "quantity": 100},
risk={
"stop_loss": 100,
"stop_gain": 150,
"max_position": 500,
"max_order_quantity": 100,
"max_orders_per_second": 2,
},
)
const listing = await client.marketplace.publishPackage(pkg.package_id, {
description: "Estratégia de rompimento validada no simulador.",
});
const subscription = await client.marketplace.subscribe(listing.listing_id, {
account: "99999",
parameters: { symbol: "PETR4", quantity: 100 },
risk: {
stop_loss: 100,
stop_gain: 150,
max_position: 500,
max_order_quantity: 100,
max_orders_per_second: 2,
},
});
Comandos de runtime e auditoria
await client.marketplace.command_subscription(subscription["subscription_id"], "start")
order = await client.marketplace.submit_runtime_order(
subscription["subscription_id"],
symbol="PETR4",
side="BUY",
quantity=1,
price=40.0,
)
events = await client.marketplace.list_events(subscription["subscription_id"])
audit = await client.marketplace.audit(
entity_type="subscription",
entity_id=subscription["subscription_id"],
limit=50,
)
await client.marketplace.commandSubscription(subscription.subscription_id, "start");
const order = await client.marketplace.submitRuntimeOrder(
subscription.subscription_id,
{
symbol: "PETR4",
side: "BUY",
quantity: 1,
price: 40.0,
},
);
const events = await client.marketplace.listEvents(subscription.subscription_id);
const audit = await client.marketplace.audit({
entityType: "subscription",
entityId: subscription.subscription_id,
limit: 50,
});
Use cancel-and-flat quando o runtime precisar cancelar ordens em aberto e zerar a exposição residual por controles aprovados pela plataforma.