@tradelayerprotocol/tradelayer 1.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +13 -0
- package/.claude/skills/tl-algo/SKILL.md +255 -0
- package/.gitattributes +2 -0
- package/.github/workflows/publish.yaml +26 -0
- package/4mm.js +163 -0
- package/LICENSE +21 -0
- package/NPMSwapRefactor.zip +0 -0
- package/README.md +217 -0
- package/address.sh +26 -0
- package/algoAPI.js +581 -0
- package/analyzepsbt.js +92 -0
- package/apiEx.js +99 -0
- package/bb_hyperscalper.js +290 -0
- package/bbo_demo.js +111 -0
- package/buyer.js +622 -0
- package/client.js +50 -0
- package/createTxTest.js +26 -0
- package/createWallet.js +75 -0
- package/daytrader.js +531 -0
- package/decodeTest.js +69 -0
- package/fundingManager.js +144 -0
- package/index.js +4 -0
- package/listener.js +27 -0
- package/litecoreTxBuilder.js +1128 -0
- package/mmEx.js +356 -0
- package/networks.js +51 -0
- package/orderbook.js +200 -0
- package/package.json +34 -0
- package/perTradeQueue.js +36 -0
- package/projectsTLNPMTLNPM/package-lock.json +162 -0
- package/projectsTLNPMTLNPM/package.json +5 -0
- package/quick.js +32 -0
- package/quickFut.js +37 -0
- package/quickSell.js +37 -0
- package/relayerClient.js +117 -0
- package/run4mm.js +80 -0
- package/run_bbo_tracker.js +241 -0
- package/seller.js +443 -0
- package/session.js +45 -0
- package/setup-lin-ltc.sh +139 -0
- package/setup-lin.sh +203 -0
- package/setup-win-ltc.bat +108 -0
- package/setup-win.bat +167 -0
- package/spam_screamer_futures.js +222 -0
- package/tradelayer.js/.gitattributes +2 -0
- package/tradelayer.js/README.md +2 -0
- package/tradelayer.js/oldTests/activationTest.js +6 -0
- package/tradelayer.js/oldTests/base58.test.js +23 -0
- package/tradelayer.js/oldTests/base64Decode.test.js +16 -0
- package/tradelayer.js/oldTests/blocksRefactor.js +140 -0
- package/tradelayer.js/oldTests/checkVestBalance.js +25 -0
- package/tradelayer.js/oldTests/consensusHashProto.js +151 -0
- package/tradelayer.js/oldTests/contractOrderbook.js +243 -0
- package/tradelayer.js/oldTests/createPayload.js +0 -0
- package/tradelayer.js/oldTests/createTestnetAddr.js +43 -0
- package/tradelayer.js/oldTests/decode.js +205 -0
- package/tradelayer.js/oldTests/decodeTest.js +50 -0
- package/tradelayer.js/oldTests/displayTallyMap.js +19 -0
- package/tradelayer.js/oldTests/encodeDecode.js +340 -0
- package/tradelayer.js/oldTests/expressTest.js +29 -0
- package/tradelayer.js/oldTests/extractBlocksVanilla.js +214 -0
- package/tradelayer.js/oldTests/extractBlocksVanillaa.js +179 -0
- package/tradelayer.js/oldTests/extractPubkeyTest.js +60 -0
- package/tradelayer.js/oldTests/fillInputCacheProto.js +111 -0
- package/tradelayer.js/oldTests/getRawTxTest.js +22 -0
- package/tradelayer.js/oldTests/indexTest.js +26 -0
- package/tradelayer.js/oldTests/initTokensTest.js +32 -0
- package/tradelayer.js/oldTests/interfaceChild.js +129 -0
- package/tradelayer.js/oldTests/listenerChild.js +112 -0
- package/tradelayer.js/oldTests/opdecode.js +26 -0
- package/tradelayer.js/oldTests/options.js +79 -0
- package/tradelayer.js/oldTests/optxtest.js +116 -0
- package/tradelayer.js/oldTests/optxtest1.js +64 -0
- package/tradelayer.js/oldTests/oracle.test.js +32 -0
- package/tradelayer.js/oldTests/orderbook.test.js +36 -0
- package/tradelayer.js/oldTests/parsing.js +93 -0
- package/tradelayer.js/oldTests/payload.js +13 -0
- package/tradelayer.js/oldTests/persistenceUnitTest.js +23 -0
- package/tradelayer.js/oldTests/property.test.js +53 -0
- package/tradelayer.js/oldTests/propertyLevel.js +75 -0
- package/tradelayer.js/oldTests/propertyTest.js +32 -0
- package/tradelayer.js/oldTests/queryAddressTest.js +17 -0
- package/tradelayer.js/oldTests/salter.js +14 -0
- package/tradelayer.js/oldTests/tally.js +81 -0
- package/tradelayer.js/oldTests/tally.test.js +48 -0
- package/tradelayer.js/oldTests/tally2.js +124 -0
- package/tradelayer.js/oldTests/tally3.js +142 -0
- package/tradelayer.js/oldTests/tallyDiag.js +38 -0
- package/tradelayer.js/oldTests/testGetRaw.js +40 -0
- package/tradelayer.js/oldTests/testHexConvert.js +47 -0
- package/tradelayer.js/oldTests/testNewEncoding.js +96 -0
- package/tradelayer.js/oldTests/testNewEncoding2.js +113 -0
- package/tradelayer.js/oldTests/testNewEncoding3 +112 -0
- package/tradelayer.js/oldTests/testNewEncoding3.js +168 -0
- package/tradelayer.js/oldTests/testOPReturn.js +102 -0
- package/tradelayer.js/oldTests/testPayload.js +23 -0
- package/tradelayer.js/oldTests/testRaw.js +50 -0
- package/tradelayer.js/oldTests/testSendTooMuch.js +20 -0
- package/tradelayer.js/oldTests/testTxBuild +28 -0
- package/tradelayer.js/oldTests/testTxBuild.js +42 -0
- package/tradelayer.js/oldTests/tokenOrderbook.js +243 -0
- package/tradelayer.js/oldTests/txUtilsA.js +515 -0
- package/tradelayer.js/oldTests/validityUnitTest.js +53 -0
- package/tradelayer.js/oldTests/vaults.js +72 -0
- package/tradelayer.js/oldTests/volumeIndex.js +117 -0
- package/tradelayer.js/oldTests/volumeIndex2.js +88 -0
- package/tradelayer.js/output_base64.txt +1 -0
- package/tradelayer.js/package-lock.json +9967 -0
- package/tradelayer.js/package.json +61 -0
- package/tradelayer.js/server/index.js +88 -0
- package/tradelayer.js/server/litecoind.exe +0 -0
- package/tradelayer.js/src/activation.js +303 -0
- package/tradelayer.js/src/adjuster.js +77 -0
- package/tradelayer.js/src/amm.js +400 -0
- package/tradelayer.js/src/base256.js +55 -0
- package/tradelayer.js/src/base94.js +79 -0
- package/tradelayer.js/src/channels.js +1163 -0
- package/tradelayer.js/src/clearing.js +3109 -0
- package/tradelayer.js/src/clearlist.js +364 -0
- package/tradelayer.js/src/client.js +295 -0
- package/tradelayer.js/src/consensus.js +613 -0
- package/tradelayer.js/src/contractRegistry.js +964 -0
- package/tradelayer.js/src/db.js +89 -0
- package/tradelayer.js/src/init.js +24 -0
- package/tradelayer.js/src/insurance.js +347 -0
- package/tradelayer.js/src/interface.js +218 -0
- package/tradelayer.js/src/interfaceExpress.js +178 -0
- package/tradelayer.js/src/iou.js +509 -0
- package/tradelayer.js/src/listener.js +226 -0
- package/tradelayer.js/src/logic.js +1702 -0
- package/tradelayer.js/src/main.js +927 -0
- package/tradelayer.js/src/marginMap.js +2165 -0
- package/tradelayer.js/src/options.js +126 -0
- package/tradelayer.js/src/oracle.js +394 -0
- package/tradelayer.js/src/orderbook.js +4123 -0
- package/tradelayer.js/src/persistence.js +554 -0
- package/tradelayer.js/src/property.js +411 -0
- package/tradelayer.js/src/reOrg.js +41 -0
- package/tradelayer.js/src/scaling.js +145 -0
- package/tradelayer.js/src/tally.js +1275 -0
- package/tradelayer.js/src/tradeHistoryManager.js +552 -0
- package/tradelayer.js/src/txDecoder.js +584 -0
- package/tradelayer.js/src/txEncoder.js +610 -0
- package/tradelayer.js/src/txIndex.js +502 -0
- package/tradelayer.js/src/txUtils.js +1392 -0
- package/tradelayer.js/src/types.js +429 -0
- package/tradelayer.js/src/validity.js +3077 -0
- package/tradelayer.js/src/vaults.js +430 -0
- package/tradelayer.js/src/vesting.js +491 -0
- package/tradelayer.js/src/volumeIndex.js +618 -0
- package/tradelayer.js/src/walletInterface.js +220 -0
- package/tradelayer.js/src/walletListener.js +665 -0
- package/tradelayer.js/tests/256decode.js +82 -0
- package/tradelayer.js/tests/UTXOracle.js +205 -0
- package/tradelayer.js/tests/base94test.js +23 -0
- package/tradelayer.js/tests/cancelTxTest.js +62 -0
- package/tradelayer.js/tests/contractInterfaceTest.js +48 -0
- package/tradelayer.js/tests/decimalTest.js +65 -0
- package/tradelayer.js/tests/decoderTest.js +100 -0
- package/tradelayer.js/tests/deltaCount.js +47 -0
- package/tradelayer.js/tests/deltaCount2.js +60 -0
- package/tradelayer.js/tests/interfaceTest.js +37 -0
- package/tradelayer.js/tests/mainTest.js +53 -0
- package/tradelayer.js/tests/makeActivationTest.js +24 -0
- package/tradelayer.js/tests/maxHeightTest.js +49 -0
- package/tradelayer.js/tests/reverseHash.js +72 -0
- package/tradelayer.js/tests/sensitiveConsoleOutput.txt +267 -0
- package/tradelayer.js/tests/tallyTest.js +40 -0
- package/tradelayer.js/tests/testBuybacks.js +46 -0
- package/tradelayer.js/tests/testCodeHash.js +49 -0
- package/tradelayer.js/tests/testConsensusHash.js +91 -0
- package/tradelayer.js/tests/testDecode.js +30 -0
- package/tradelayer.js/tests/testEncodingLengths.js +129 -0
- package/tradelayer.js/tests/testGetTx +32 -0
- package/tradelayer.js/tests/testGetTx.js +32 -0
- package/tradelayer.js/tests/testHexHash.js +32 -0
- package/tradelayer.js/tests/testIndexHash.js +35 -0
- package/tradelayer.js/tests/testInitContracts.js +38 -0
- package/tradelayer.js/tests/testMaxConsensus.js +12 -0
- package/tradelayer.js/tests/testMaxSynth.js +44 -0
- package/tradelayer.js/tests/testMint.js +21 -0
- package/tradelayer.js/tests/testNetwork.js +33 -0
- package/tradelayer.js/tests/testOrderbookLoad.js +62 -0
- package/tradelayer.js/tests/testRebates.js +32 -0
- package/tradelayer.js/tests/testRedeem.js +22 -0
- package/tradelayer.js/tests/testTokenTrade.js +39 -0
- package/tradelayer.js/tests/testTxBuild.js +42 -0
- package/tradelayer.js/tests/testUTXOTrade.js +27 -0
- package/tradelayer.js/tests/tokenTradeHistory.js +27 -0
- package/tradelayer.js/tests/tradeFutures.js +40 -0
- package/tradelayer.js/tests/tradeHistoryExample.js +35 -0
- package/tradelayer.js/tests/tradeHistoryLoad.js +15 -0
- package/tradelayer.js/tests/txScanTest.js +134 -0
- package/tradelayer.js/tests/validateTest.js +136 -0
- package/tradelayer.js/tests/vestingTest.js +37 -0
- package/tradelayer.js/utils/activateMainnet.js +59 -0
- package/tradelayer.js/utils/activateMainnetDoge.js +63 -0
- package/tradelayer.js/utils/autocompactdb.js +23 -0
- package/tradelayer.js/utils/base64toHex.js +32 -0
- package/tradelayer.js/utils/broadcastDoge.js +38 -0
- package/tradelayer.js/utils/calcRedeem.js +19 -0
- package/tradelayer.js/utils/checkNetwork.js +27 -0
- package/tradelayer.js/utils/createAddress.js +48 -0
- package/tradelayer.js/utils/createAttestation.js +133 -0
- package/tradelayer.js/utils/createContract.js +118 -0
- package/tradelayer.js/utils/createOracle.js +94 -0
- package/tradelayer.js/utils/createwallet.js +20 -0
- package/tradelayer.js/utils/crossFuturesTrades.js +57 -0
- package/tradelayer.js/utils/crossTokenTrades.js +62 -0
- package/tradelayer.js/utils/dumpPriv.js +29 -0
- package/tradelayer.js/utils/generateChannel.js +34 -0
- package/tradelayer.js/utils/getInfo.js +21 -0
- package/tradelayer.js/utils/hardWipe.js +20 -0
- package/tradelayer.js/utils/hexTo64.js +16 -0
- package/tradelayer.js/utils/importAddress.js +28 -0
- package/tradelayer.js/utils/importpriv.js +20 -0
- package/tradelayer.js/utils/issueOracleContract.js +67 -0
- package/tradelayer.js/utils/issueTokens.js +41 -0
- package/tradelayer.js/utils/listunspent.js +66 -0
- package/tradelayer.js/utils/litecoinClient.js +30 -0
- package/tradelayer.js/utils/loadwallet.js +20 -0
- package/tradelayer.js/utils/publishOracle.js +113 -0
- package/tradelayer.js/utils/sendActivation.js +21 -0
- package/tradelayer.js/utils/sendChannelContractTrade.js +34 -0
- package/tradelayer.js/utils/sendChannelTokenTrade.js +34 -0
- package/tradelayer.js/utils/sendCommit.js +24 -0
- package/tradelayer.js/utils/sendDoge.js +62 -0
- package/tradelayer.js/utils/sendDogeMain.js +67 -0
- package/tradelayer.js/utils/sendDogeTx.js +46 -0
- package/tradelayer.js/utils/sendLTC.js +63 -0
- package/tradelayer.js/utils/sendMainnet.js +62 -0
- package/tradelayer.js/utils/sendTransfer.js +19 -0
- package/tradelayer.js/utils/sendVestTest.js +88 -0
- package/tradelayer.js/utils/sendWithdrawal.js +26 -0
- package/tradelayer.js/utils/simpleStart.js +8 -0
- package/tradelayer.js/utils/startStop.js +27 -0
- package/tradelayer.js/utils/structuredTrades.js +136 -0
- package/tradelayer.js/utils/verifySignature.js +90 -0
- package/tradelayer.js/utils/verifyWitnessAndScriptPubkey.js +41 -0
- package/tradelayer.js/utils/walletCache.js +172 -0
- package/tradelayer.js/utils/walletContractInterface.js +48 -0
- package/tradelayer.js/utils/walletFetchTxs.js +66 -0
- package/tradelayer.js/utils/walletUtils.js +97 -0
- package/tradelayer.js/utils/wipeDB.js +55 -0
- package/tradelayer.js/utils/wipeDBNotTx.js +50 -0
- package/txEncoder.js +529 -0
- package/utility.js +28 -0
- package/verifymessage.js +38 -0
- package/ws-transport.js +311 -0
package/apiEx.js
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/* @algo
|
|
2
|
+
{
|
|
3
|
+
"name": "API Ex",
|
|
4
|
+
"symbol": "TLITE/LTC",
|
|
5
|
+
"venue": "TradeLayer",
|
|
6
|
+
"mode": "SPOT",
|
|
7
|
+
"leverage": 1,
|
|
8
|
+
"timeframe": "15m",
|
|
9
|
+
"description": "Simple order placement demo.",
|
|
10
|
+
"tags": ["mean-reversion","btc","futures"],
|
|
11
|
+
|
|
12
|
+
"parameters": {
|
|
13
|
+
"window": { "type": "int", "default": 20, "min": 1, "max": 500 },
|
|
14
|
+
"zEntry": { "type": "number", "default": 1.5, "min": 0, "max": 5, "step": 0.1 },
|
|
15
|
+
"zExit": { "type": "number", "default": 0.3, "min": 0, "max": 2, "step": 0.1 },
|
|
16
|
+
"maxPos": { "type": "int", "default": 1, "min": 1, "max": 10 }
|
|
17
|
+
},
|
|
18
|
+
|
|
19
|
+
"risk": {
|
|
20
|
+
"stopLossPct": 2.0,
|
|
21
|
+
"takeProfitPct": 3.5,
|
|
22
|
+
"maxLeverage": 5
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
"author": "you",
|
|
26
|
+
"version": "1.0.0"
|
|
27
|
+
}
|
|
28
|
+
@algo */
|
|
29
|
+
|
|
30
|
+
// … actual trading code below …
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
const ApiWrapper = require('tradelayer');
|
|
35
|
+
let myInfo = {address:'tltc1q89kkgaslk0lt8l90jkl3cgwg7dkkszn73u4d2t',otherAddrs:[]};
|
|
36
|
+
const api = new ApiWrapper('ws://172.26.37.103', 3001, true,true, myInfo, 'LTCTEST');
|
|
37
|
+
|
|
38
|
+
// Start listening for order matches and handle swaps
|
|
39
|
+
let orderbookSession = []
|
|
40
|
+
let savedOrderUUIDs = []; // Array to store UUIDs of orders
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
async function performTradeOperations(testAddress) {
|
|
44
|
+
console.log("awaiting init and address load")
|
|
45
|
+
await api.delay(2000);
|
|
46
|
+
myInfo = api.getMyInfo()
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
// Call getTokenBalances with your test address
|
|
50
|
+
console.log('checking we have address loaded before tokenBalances load '+myInfo.keypair.address)
|
|
51
|
+
const tokenBalances = await api.getAllTokenBalancesForAddress(myInfo.keypair.address);
|
|
52
|
+
console.log('tokens '+JSON.stringify(tokenBalances))
|
|
53
|
+
// Example of fetching spot markets
|
|
54
|
+
api.getSpotMarkets()
|
|
55
|
+
.then(markets => console.log('Spot Markets:', markets))
|
|
56
|
+
.catch(error => console.error('Error:', error));
|
|
57
|
+
|
|
58
|
+
api.getFuturesMarkets()
|
|
59
|
+
.then(markets => console.log('Futures Markets:', markets))
|
|
60
|
+
.catch(error => console.error('Error:', error));
|
|
61
|
+
|
|
62
|
+
// Example of sending an order
|
|
63
|
+
const orderDetails = {
|
|
64
|
+
type: 'SPOT',
|
|
65
|
+
action: 'BUY',
|
|
66
|
+
props: { id_for_sale: 5, id_desired:0, price: 0.0003, amount: 0.3, transfer: false },
|
|
67
|
+
isLimitOrder:true,
|
|
68
|
+
keypair: {
|
|
69
|
+
address: 'tltc1qn006lvcx89zjnhuzdmj0rjcwnfuqn7eycw40yf',
|
|
70
|
+
pubkey: '03670d8f2109ea83ad09142839a55c77a6f044dab8cb8724949931ae8ab1316677'
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
await api.delay(3000)
|
|
75
|
+
api.sendOrder(orderDetails)
|
|
76
|
+
.then(orderUUID => {
|
|
77
|
+
console.log('Order sent, UUID:', orderUUID+' '+ JSON.stringify(orderDetails));
|
|
78
|
+
|
|
79
|
+
savedOrderUUIDs.push({id: orderUUID, details: orderDetails}); // Save UUID to the array
|
|
80
|
+
})
|
|
81
|
+
console.log('delay and test cancel')
|
|
82
|
+
|
|
83
|
+
console.log(JSON.stringify(savedOrderUUIDs))
|
|
84
|
+
/*console.log('about to cancel this order '+savedOrderUUIDs[0].id)
|
|
85
|
+
api.cancelOrder(savedOrderUUIDs[0].id)
|
|
86
|
+
.then(response => {
|
|
87
|
+
savedOrderUUIDs = savedOrderUUIDs.filter(order => order.id !== savedOrderUUIDs[0].id);
|
|
88
|
+
console.log(`Order with UUID: ${orderToCancel} canceled successfully!`);
|
|
89
|
+
})*/
|
|
90
|
+
|
|
91
|
+
// Example of getting orderbook data
|
|
92
|
+
const filter = { type: 'SPOT', first_token: 0, second_token: 5 };
|
|
93
|
+
api.getOrderbookData(filter)
|
|
94
|
+
.then(orderbookData => console.log('Orderbook Data:', orderbookData))
|
|
95
|
+
.catch(error => console.error('Error fetching orderbook data:', error));
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Example usage of the function
|
|
99
|
+
performTradeOperations(myInfo.address);
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* bb_scalper_binance_tl.js
|
|
5
|
+
*
|
|
6
|
+
* 5-second Bollinger Band scalper:
|
|
7
|
+
* - Price feed: Binance futures aggTrade stream (e.g. BTCUSDT)
|
|
8
|
+
* - Build 5s bars from trades
|
|
9
|
+
* - Compute Bollinger Bands on last N closes
|
|
10
|
+
* - Flat:
|
|
11
|
+
* * close <= lower -> LONG TL market (market order)
|
|
12
|
+
* * close >= upper -> SHORT TL market (market order)
|
|
13
|
+
* - In position:
|
|
14
|
+
* * TP at +TP_BPS
|
|
15
|
+
* * SL at -SL_BPS
|
|
16
|
+
*
|
|
17
|
+
* Execution: TradeLayer via ApiWrapper (same family as run_bbo_tracker.js).
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const WebSocket = require('ws');
|
|
21
|
+
const { ApiWrapper } = require('./algoAPI'); // adjust path if different
|
|
22
|
+
|
|
23
|
+
// -------- TL API SETUP --------
|
|
24
|
+
const tlApi = new ApiWrapper(
|
|
25
|
+
process.env.TL_BASE_URL || 'http://127.0.0.1',
|
|
26
|
+
Number(process.env.TL_PORT || 3001),
|
|
27
|
+
process.env.TL_TEST === 'true',
|
|
28
|
+
process.env.TL_ALREADY_ON === 'true',
|
|
29
|
+
process.env.TL_ADDRESS,
|
|
30
|
+
process.env.TL_PUBKEY,
|
|
31
|
+
process.env.TL_NETWORK || 'LTCTEST'
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
// -------- CONFIG --------
|
|
35
|
+
const CFG = {
|
|
36
|
+
// Binance side (price oracle)
|
|
37
|
+
BINANCE_SYMBOL: (process.env.BINANCE_SYMBOL || 'BTCUSDT').toLowerCase(),
|
|
38
|
+
// Binance futures aggTrade stream
|
|
39
|
+
BINANCE_WS_URL_BASE: 'wss://fstream.binance.com/ws',
|
|
40
|
+
|
|
41
|
+
// TL side
|
|
42
|
+
TL_MARKET: process.env.TL_MARKET || 'BTC-PERP', // your TL futures/synth market
|
|
43
|
+
ORDER_SIZE: Number(process.env.TL_ORDER_SIZE || 1),
|
|
44
|
+
|
|
45
|
+
// Bar / indicator settings
|
|
46
|
+
BAR_MS: 5000, // 5-second bars
|
|
47
|
+
BB_PERIOD: 60, // 60 bars => 5 minutes of history at 5s
|
|
48
|
+
BB_K: 2, // standard deviation multiplier
|
|
49
|
+
|
|
50
|
+
// Risk
|
|
51
|
+
TP_BPS: 3, // take profit at +3 bps
|
|
52
|
+
SL_BPS: 3, // stop loss at -3 bps
|
|
53
|
+
|
|
54
|
+
LOG_EVERY_BAR: true
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
// -------- STATE --------
|
|
58
|
+
|
|
59
|
+
// 5-second bucket
|
|
60
|
+
let bucketStart = null;
|
|
61
|
+
let bucketOpen = null;
|
|
62
|
+
let bucketHigh = null;
|
|
63
|
+
let bucketLow = null;
|
|
64
|
+
let bucketLast = null;
|
|
65
|
+
|
|
66
|
+
// bar history: { t, o, h, l, c }
|
|
67
|
+
const bars = [];
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Position in TL we track locally:
|
|
71
|
+
* { side: 'long' | 'short', qty: number, entryPrice: number }
|
|
72
|
+
*/
|
|
73
|
+
let position = null;
|
|
74
|
+
|
|
75
|
+
// -------- HELPERS --------
|
|
76
|
+
|
|
77
|
+
function bpsDiff(entry, current, side) {
|
|
78
|
+
if (side === 'long') {
|
|
79
|
+
return ((current - entry) / entry) * 10_000;
|
|
80
|
+
}
|
|
81
|
+
return ((entry - current) / entry) * 10_000; // short
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async function tlMarketOrder(side, qty) {
|
|
85
|
+
console.log(`[TL] MARKET ${side} ${qty} ${CFG.TL_MARKET}`);
|
|
86
|
+
|
|
87
|
+
// Adjust this to your real ApiWrapper method.
|
|
88
|
+
if (typeof tlApi.placeOrder === 'function') {
|
|
89
|
+
return tlApi.placeOrder({
|
|
90
|
+
market: CFG.TL_MARKET,
|
|
91
|
+
side, // 'buy' | 'sell'
|
|
92
|
+
type: 'MARKET',
|
|
93
|
+
size: qty
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Fallback example if you have a different signature:
|
|
98
|
+
// return tlApi.spotMarketOrder(CFG.TL_MARKET, side, qty);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
async function openPosition(side, price) {
|
|
102
|
+
if (position) return;
|
|
103
|
+
const qty = CFG.ORDER_SIZE;
|
|
104
|
+
|
|
105
|
+
await tlMarketOrder(side === 'long' ? 'buy' : 'sell', qty);
|
|
106
|
+
position = { side, qty, entryPrice: price };
|
|
107
|
+
|
|
108
|
+
console.log(
|
|
109
|
+
`[ENTRY] ${side.toUpperCase()} qty=${qty} entry=${price.toFixed(8)}`
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async function closePosition(price, reason) {
|
|
114
|
+
if (!position) return;
|
|
115
|
+
|
|
116
|
+
const exitSide = position.side === 'long' ? 'sell' : 'buy';
|
|
117
|
+
await tlMarketOrder(exitSide, position.qty);
|
|
118
|
+
|
|
119
|
+
const pnlBps = bpsDiff(position.entryPrice, price, position.side);
|
|
120
|
+
|
|
121
|
+
console.log(
|
|
122
|
+
`[EXIT] reason=${reason} side=${position.side} qty=${position.qty} entry=${position.entryPrice.toFixed(
|
|
123
|
+
8
|
|
124
|
+
)} exit=${price.toFixed(8)} pnl=${pnlBps.toFixed(2)}bps`
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
position = null;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function computeBollinger() {
|
|
131
|
+
if (bars.length < CFG.BB_PERIOD) return null;
|
|
132
|
+
|
|
133
|
+
const lastN = bars.slice(bars.length - CFG.BB_PERIOD);
|
|
134
|
+
const closes = lastN.map(b => b.c);
|
|
135
|
+
const n = closes.length;
|
|
136
|
+
|
|
137
|
+
const mean =
|
|
138
|
+
closes.reduce((s, x) => s + x, 0) / n;
|
|
139
|
+
|
|
140
|
+
const variance =
|
|
141
|
+
closes.reduce((s, x) => s + (x - mean) * (x - mean), 0) / n;
|
|
142
|
+
|
|
143
|
+
const std = Math.sqrt(variance);
|
|
144
|
+
|
|
145
|
+
return {
|
|
146
|
+
mean,
|
|
147
|
+
upper: mean + CFG.BB_K * std,
|
|
148
|
+
lower: mean - CFG.BB_K * std
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
async function onNewBar(bar) {
|
|
153
|
+
bars.push(bar);
|
|
154
|
+
|
|
155
|
+
// keep history bounded
|
|
156
|
+
const maxBars = CFG.BB_PERIOD * 3;
|
|
157
|
+
if (bars.length > maxBars) {
|
|
158
|
+
bars.splice(0, bars.length - maxBars);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const bb = computeBollinger();
|
|
162
|
+
if (!bb) return;
|
|
163
|
+
|
|
164
|
+
const price = bar.c;
|
|
165
|
+
|
|
166
|
+
if (CFG.LOG_EVERY_BAR) {
|
|
167
|
+
console.log(
|
|
168
|
+
`[BAR] t=${new Date(bar.t).toISOString()} close=${price.toFixed(
|
|
169
|
+
2
|
|
170
|
+
)} mean=${bb.mean.toFixed(2)} upper=${bb.upper.toFixed(
|
|
171
|
+
2
|
|
172
|
+
)} lower=${bb.lower.toFixed(2)}`
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// 1) Manage existing position TP/SL
|
|
177
|
+
if (position) {
|
|
178
|
+
const pnlBps = bpsDiff(position.entryPrice, price, position.side);
|
|
179
|
+
|
|
180
|
+
if (pnlBps >= CFG.TP_BPS) {
|
|
181
|
+
await closePosition(price, 'TP');
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (pnlBps <= -CFG.SL_BPS) {
|
|
186
|
+
await closePosition(price, 'SL');
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return; // still in position
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// 2) Flat: look for entries
|
|
194
|
+
if (price <= bb.lower) {
|
|
195
|
+
await openPosition('long', price);
|
|
196
|
+
} else if (price >= bb.upper) {
|
|
197
|
+
await openPosition('short', price);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// 5-second bar builder from trade ticks
|
|
202
|
+
async function onPriceTick(price, ts = Date.now()) {
|
|
203
|
+
const bucket = Math.floor(ts / CFG.BAR_MS) * CFG.BAR_MS;
|
|
204
|
+
|
|
205
|
+
if (bucketStart === null) {
|
|
206
|
+
bucketStart = bucket;
|
|
207
|
+
bucketOpen = price;
|
|
208
|
+
bucketHigh = price;
|
|
209
|
+
bucketLow = price;
|
|
210
|
+
bucketLast = price;
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (bucket !== bucketStart) {
|
|
215
|
+
// close bar
|
|
216
|
+
const bar = {
|
|
217
|
+
t: bucketStart,
|
|
218
|
+
o: bucketOpen,
|
|
219
|
+
h: bucketHigh,
|
|
220
|
+
l: bucketLow,
|
|
221
|
+
c: bucketLast
|
|
222
|
+
};
|
|
223
|
+
await onNewBar(bar);
|
|
224
|
+
|
|
225
|
+
// new bucket
|
|
226
|
+
bucketStart = bucket;
|
|
227
|
+
bucketOpen = price;
|
|
228
|
+
bucketHigh = price;
|
|
229
|
+
bucketLow = price;
|
|
230
|
+
bucketLast = price;
|
|
231
|
+
} else {
|
|
232
|
+
// update current bucket
|
|
233
|
+
bucketLast = price;
|
|
234
|
+
if (price > bucketHigh) bucketHigh = price;
|
|
235
|
+
if (price < bucketLow) bucketLow = price;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// -------- BINANCE WS WIRING --------
|
|
240
|
+
|
|
241
|
+
function startBinanceStream() {
|
|
242
|
+
const streamName = `${CFG.BINANCE_SYMBOL}@aggTrade`; // futures aggregated trades
|
|
243
|
+
const url = `${CFG.BINANCE_WS_URL_BASE}/${streamName}`;
|
|
244
|
+
|
|
245
|
+
console.log(`[WS] connecting to ${url}`);
|
|
246
|
+
|
|
247
|
+
const ws = new WebSocket(url);
|
|
248
|
+
|
|
249
|
+
ws.on('open', () => {
|
|
250
|
+
console.log('[WS] connected to Binance aggTrade');
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
ws.on('message', async msg => {
|
|
254
|
+
try {
|
|
255
|
+
const data = JSON.parse(msg.toString());
|
|
256
|
+
// aggTrade payload: { p: "price", T: tradeTime, ... }
|
|
257
|
+
const price = Number(data.p);
|
|
258
|
+
if (!price || !isFinite(price)) return;
|
|
259
|
+
|
|
260
|
+
const ts = Number(data.T) || Date.now();
|
|
261
|
+
await onPriceTick(price, ts);
|
|
262
|
+
} catch (e) {
|
|
263
|
+
console.log('[WS] message error:', e.message || e);
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
ws.on('close', () => {
|
|
268
|
+
console.log('[WS] closed. Reconnecting in 5s...');
|
|
269
|
+
setTimeout(startBinanceStream, 5000);
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
ws.on('error', err => {
|
|
273
|
+
console.log('[WS] error:', err.message || err);
|
|
274
|
+
ws.close();
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// -------- ENTRYPOINT --------
|
|
279
|
+
|
|
280
|
+
console.log(
|
|
281
|
+
`BB scalper starting:
|
|
282
|
+
Binance symbol: ${CFG.BINANCE_SYMBOL.toUpperCase()}
|
|
283
|
+
TL market: ${CFG.TL_MARKET}
|
|
284
|
+
Bar: ${CFG.BAR_MS / 1000}s
|
|
285
|
+
BB: period=${CFG.BB_PERIOD}, k=${CFG.BB_K}
|
|
286
|
+
TP/SL: ${CFG.TP_BPS} / ${CFG.SL_BPS} bps
|
|
287
|
+
`
|
|
288
|
+
);
|
|
289
|
+
|
|
290
|
+
startBinanceStream();
|
package/bbo_demo.js
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
const WebSocket = require('ws');
|
|
2
|
+
const ccxt = require('ccxt');
|
|
3
|
+
|
|
4
|
+
//
|
|
5
|
+
// CONFIG
|
|
6
|
+
//
|
|
7
|
+
const OB_URL = 'ws://172.81.181.19:3001/ws';
|
|
8
|
+
const CONTRACT_ID = 2;
|
|
9
|
+
const NETWORK = 'BTC';
|
|
10
|
+
|
|
11
|
+
// dummy keypair (server does NOT verify sigs for demo)
|
|
12
|
+
const KEYP = {
|
|
13
|
+
address: 'btc_demo_bot',
|
|
14
|
+
pubkey: '02aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
// quoting values (adjust for visuals)
|
|
18
|
+
const SIZE = 1; // 1 contract
|
|
19
|
+
const SPREAD = 3; // dollars above/below mark
|
|
20
|
+
const COLLATERAL = 50; // fake
|
|
21
|
+
const MARGIN = 0.1; // 10%
|
|
22
|
+
|
|
23
|
+
//
|
|
24
|
+
// Connect to Orderbook Server
|
|
25
|
+
//
|
|
26
|
+
console.log("[MM] Connecting to OB server:", OB_URL);
|
|
27
|
+
const ws = new WebSocket(OB_URL);
|
|
28
|
+
|
|
29
|
+
ws.on('open', () => {
|
|
30
|
+
console.log("[OB] Connected");
|
|
31
|
+
|
|
32
|
+
// join market (important!)
|
|
33
|
+
ws.send(JSON.stringify({
|
|
34
|
+
event: "orderbook:join",
|
|
35
|
+
data: {
|
|
36
|
+
marketKey: `FUTURES:${CONTRACT_ID}`,
|
|
37
|
+
network: NETWORK
|
|
38
|
+
}
|
|
39
|
+
}));
|
|
40
|
+
|
|
41
|
+
startLoop();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
ws.on('message', (msg) => {
|
|
45
|
+
console.log("[OB] >>", msg.toString());
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
ws.on('close', () => console.log("[OB] Closed"));
|
|
49
|
+
ws.on('error', (e) => console.log("[OB] Error:", e.message));
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
//
|
|
53
|
+
// Binance spot ticker loop (fetchTicker, not WS, simple & stable)
|
|
54
|
+
//
|
|
55
|
+
const binance = new ccxt.binance();
|
|
56
|
+
|
|
57
|
+
async function getMarkPrice() {
|
|
58
|
+
try {
|
|
59
|
+
const t = await binance.fetchTicker('BTC/USDT');
|
|
60
|
+
return t.last; // mid or last is fine for demo
|
|
61
|
+
} catch (err) {
|
|
62
|
+
console.log("[WARN] Binance error:", err.message);
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
//
|
|
68
|
+
// Send an order in TL FUTURES shape
|
|
69
|
+
//
|
|
70
|
+
function sendFuturesOrder(side, price) {
|
|
71
|
+
const msg = {
|
|
72
|
+
event: "new-order",
|
|
73
|
+
keypair: KEYP,
|
|
74
|
+
action: side,
|
|
75
|
+
type: "FUTURES",
|
|
76
|
+
props: {
|
|
77
|
+
contract_id: CONTRACT_ID,
|
|
78
|
+
amount: SIZE,
|
|
79
|
+
price: price,
|
|
80
|
+
collateral: COLLATERAL,
|
|
81
|
+
margin: MARGIN,
|
|
82
|
+
transfer: false
|
|
83
|
+
},
|
|
84
|
+
isLimitOrder: true,
|
|
85
|
+
marketName: `FUTURES:${CONTRACT_ID}`,
|
|
86
|
+
network: NETWORK
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
console.log("[SEND]", side, "@", price);
|
|
90
|
+
ws.send(JSON.stringify(msg));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
//
|
|
94
|
+
// Main quoting loop
|
|
95
|
+
//
|
|
96
|
+
async function startLoop() {
|
|
97
|
+
console.log("[MM] Starting futures MM loop on contract", CONTRACT_ID);
|
|
98
|
+
|
|
99
|
+
setInterval(async () => {
|
|
100
|
+
const mark = await getMarkPrice();
|
|
101
|
+
if (!mark) return;
|
|
102
|
+
|
|
103
|
+
// create BUY and SELL around mark
|
|
104
|
+
const buy = mark - SPREAD;
|
|
105
|
+
const sell = mark + SPREAD;
|
|
106
|
+
|
|
107
|
+
sendFuturesOrder("BUY", buy);
|
|
108
|
+
sendFuturesOrder("SELL", sell);
|
|
109
|
+
|
|
110
|
+
}, 1500);
|
|
111
|
+
}
|