marketMaker script places/cancels orders
This commit is contained in:
parent
4949d1aa83
commit
2a2f46131d
|
@ -11,7 +11,7 @@ import { DexMarket, MarketAccounts } from "./market";
|
|||
import { DexInstructions } from "@project-serum/serum";
|
||||
import { getVaultOwnerAndNonce } from "./utils";
|
||||
import { Coin } from "./coin";
|
||||
import { fork } from "child_process";
|
||||
import { ChildProcess, fork } from "child_process";
|
||||
import { FileKeypair } from "./fileKeypair";
|
||||
|
||||
export type MarketArgs = {
|
||||
|
@ -21,6 +21,11 @@ export type MarketArgs = {
|
|||
feeRate: number;
|
||||
quoteDustThreshold: BN;
|
||||
};
|
||||
|
||||
type MarketMakerOpts = {
|
||||
unref: boolean;
|
||||
durationInSecs: number;
|
||||
};
|
||||
export class Dex {
|
||||
public address: PublicKey;
|
||||
|
||||
|
@ -185,7 +190,11 @@ export class Dex {
|
|||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
public async runMarketMaker(market: DexMarket, owner: FileKeypair) {
|
||||
public runMarketMaker(
|
||||
market: DexMarket,
|
||||
owner: FileKeypair,
|
||||
opts: MarketMakerOpts,
|
||||
): ChildProcess {
|
||||
const child = fork("./src/scripts/marketMaker", null, {
|
||||
detached: true,
|
||||
stdio: ["pipe", 0, 0, "ipc"],
|
||||
|
@ -196,7 +205,7 @@ export class Dex {
|
|||
});
|
||||
|
||||
// https://nodejs.org/api/child_process.html#optionsdetached
|
||||
child.unref();
|
||||
if (opts.unref) child.unref();
|
||||
|
||||
child.send({
|
||||
action: "start",
|
||||
|
@ -205,9 +214,10 @@ export class Dex {
|
|||
programID: this.address.toString(),
|
||||
rpcEndpoint: this.connection.rpcEndpoint,
|
||||
ownerFilePath: owner.filePath,
|
||||
duration: opts.durationInSecs * 1000,
|
||||
},
|
||||
});
|
||||
|
||||
console.log(`Market Maker started at process ${child.pid}`);
|
||||
return child;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,3 +2,4 @@ export * from "./dex";
|
|||
export * from "./coin";
|
||||
export * from "./market";
|
||||
export * from "./fileKeypair";
|
||||
export * from "./types";
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
import { Connection, PublicKey } from "@solana/web3.js";
|
||||
import {
|
||||
Connection,
|
||||
Keypair,
|
||||
PublicKey,
|
||||
Signer,
|
||||
Transaction,
|
||||
} from "@solana/web3.js";
|
||||
import { Market as SerumMarket } from "@project-serum/serum";
|
||||
import { FileKeypair } from "../fileKeypair";
|
||||
import { DexMarket } from "../market";
|
||||
|
@ -15,6 +21,86 @@ process.on("message", async (message: MessageType) => {
|
|||
}
|
||||
});
|
||||
|
||||
const cancelOrders = async (
|
||||
owner: Keypair,
|
||||
serumMarket: SerumMarket,
|
||||
connection: Connection,
|
||||
) => {
|
||||
const orders = await serumMarket.loadOrdersForOwner(
|
||||
connection,
|
||||
owner.publicKey,
|
||||
);
|
||||
|
||||
const tx = new Transaction();
|
||||
const signersArray: Signer[][] = [];
|
||||
|
||||
for (const order of orders) {
|
||||
const { transaction, signers } = await DexMarket.getCancelOrderTransaction(
|
||||
connection,
|
||||
owner,
|
||||
serumMarket,
|
||||
order,
|
||||
);
|
||||
tx.add(transaction);
|
||||
signersArray.push(signers);
|
||||
}
|
||||
|
||||
const signersUnion: Signer[] = [...new Set(signersArray.flat())];
|
||||
|
||||
const txSig = await connection.sendTransaction(tx, signersUnion);
|
||||
|
||||
await connection.confirmTransaction(txSig, "confirmed");
|
||||
|
||||
console.log(`----- Cancelled ${orders.length} orders ------`);
|
||||
};
|
||||
|
||||
const placeOrders = async (
|
||||
owner: Keypair,
|
||||
serumMarket: SerumMarket,
|
||||
connection: Connection,
|
||||
opts: {
|
||||
isBuy: boolean;
|
||||
midPrice: number;
|
||||
count: number;
|
||||
},
|
||||
) => {
|
||||
const { isBuy, midPrice, count } = opts;
|
||||
|
||||
const tx = new Transaction();
|
||||
const signersArray: Signer[][] = [];
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
const orderPrice =
|
||||
midPrice +
|
||||
(isBuy ? -1 * (midPrice * 0.01 * (i + 1)) : midPrice * 0.01) * (i + 1);
|
||||
|
||||
const { transaction, signers } = await DexMarket.getPlaceOrderTransaction(
|
||||
connection,
|
||||
owner,
|
||||
serumMarket,
|
||||
isBuy ? "buy" : "sell",
|
||||
10,
|
||||
orderPrice,
|
||||
);
|
||||
tx.add(transaction);
|
||||
signersArray.push(signers);
|
||||
|
||||
console.log(`Order ${i} price: ${orderPrice}`);
|
||||
}
|
||||
|
||||
const signersUnion: Signer[] = [...new Set(signersArray.flat())];
|
||||
|
||||
const txSig = await connection.sendTransaction(tx, signersUnion);
|
||||
|
||||
await connection.confirmTransaction(txSig, "confirmed");
|
||||
|
||||
console.log(
|
||||
`----- Placed ${count} ${
|
||||
isBuy ? "buy" : "sell"
|
||||
} orders at midPrice: ${midPrice} ------c`,
|
||||
);
|
||||
};
|
||||
|
||||
const marketMaker = async (args) => {
|
||||
const connection = new Connection(args.rpcEndpoint, "confirmed");
|
||||
|
||||
|
@ -27,16 +113,25 @@ const marketMaker = async (args) => {
|
|||
|
||||
const owner = FileKeypair.load(args.ownerFilePath);
|
||||
|
||||
const txSig = await DexMarket.placeOrder(
|
||||
connection,
|
||||
owner.keypair,
|
||||
serumMarket,
|
||||
"buy",
|
||||
1,
|
||||
10,
|
||||
);
|
||||
placeOrders(owner.keypair, serumMarket, connection, {
|
||||
isBuy: true,
|
||||
midPrice: 10,
|
||||
count: 3,
|
||||
});
|
||||
|
||||
console.log(`Order Placed: ${txSig}`);
|
||||
setInterval(async () => {
|
||||
await cancelOrders(owner.keypair, serumMarket, connection);
|
||||
await placeOrders(owner.keypair, serumMarket, connection, {
|
||||
isBuy: true,
|
||||
midPrice: 10,
|
||||
count: 3,
|
||||
});
|
||||
}, 10000);
|
||||
|
||||
process.kill(0);
|
||||
if (Number.parseInt(args.duration) > 0) {
|
||||
setTimeout(() => {
|
||||
console.log(`Exiting Market Maker @ ${process.pid}`);
|
||||
process.exit(0);
|
||||
}, Number.parseInt(args.duration));
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue