├── .github
└── workflows
│ └── deploy.yml
├── .gitignore
├── README.md
├── README.zh-CN.md
├── docs
├── .vitepress
│ ├── config.js
│ └── theme
│ │ ├── custom.css
│ │ └── index.js
├── README.md
├── config.md
├── developer.md
├── faq.md
├── index.md
├── market.md
├── operation.md
├── panacea.md
├── public
│ └── images
│ │ ├── desktop.jpg
│ │ ├── desktop_cn.jpg
│ │ ├── logo.png
│ │ ├── screenshot.jpg
│ │ ├── screenshot_cn.jpg
│ │ ├── screenshot_large.jpg
│ │ ├── screenshot_large_zh.jpg
│ │ ├── screenshot_mobile.jpg
│ │ ├── screenshot_mobile_zh.jpg
│ │ ├── screenshot_zh.jpg
│ │ ├── web_top.png
│ │ └── web_top_en.png
├── status.md
├── strategy.md
└── zh
│ ├── README.md
│ ├── config.md
│ ├── developer.md
│ ├── faq.md
│ ├── index.md
│ ├── market.md
│ ├── operation.md
│ ├── panacea.md
│ ├── status.md
│ └── strategy.md
├── extensions
└── xcoin
│ ├── README.md
│ ├── README.zh-CN.md
│ └── panacea
│ ├── api
│ ├── api.js
│ ├── backtest.js
│ ├── config.js
│ ├── market.js
│ ├── operation.js
│ ├── panacea.js
│ ├── status.js
│ └── strategy.js
│ └── index.js
├── package.json
└── yarn.lock
/.github/workflows/deploy.yml:
--------------------------------------------------------------------------------
1 | name: Deploy
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 |
8 | jobs:
9 | deploy:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - uses: actions/checkout@v3
13 | - uses: actions/setup-node@v3
14 | with:
15 | node-version: 16
16 | cache: yarn
17 | - run: yarn install --frozen-lockfile
18 |
19 | - name: Build
20 | run: yarn docs:build
21 |
22 | - name: Deploy
23 | uses: peaceiris/actions-gh-pages@v3
24 | with:
25 | github_token: ${{ secrets.GITHUB_TOKEN }}
26 | publish_dir: docs/.vitepress/dist
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 |
9 | # Diagnostic reports (https://nodejs.org/api/report.html)
10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11 |
12 | # Runtime data
13 | pids
14 | *.pid
15 | *.seed
16 | *.pid.lock
17 |
18 | # Directory for instrumented libs generated by jscoverage/JSCover
19 | lib-cov
20 |
21 | # Coverage directory used by tools like istanbul
22 | coverage
23 | *.lcov
24 |
25 | # nyc test coverage
26 | .nyc_output
27 |
28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29 | .grunt
30 |
31 | # Bower dependency directory (https://bower.io/)
32 | bower_components
33 |
34 | # node-waf configuration
35 | .lock-wscript
36 |
37 | # Compiled binary addons (https://nodejs.org/api/addons.html)
38 | build/Release
39 |
40 | # Dependency directories
41 | node_modules/
42 | jspm_packages/
43 |
44 | # TypeScript v1 declaration files
45 | typings/
46 |
47 | # TypeScript cache
48 | *.tsbuildinfo
49 |
50 | # Optional npm cache directory
51 | .npm
52 |
53 | # Optional eslint cache
54 | .eslintcache
55 |
56 | # Microbundle cache
57 | .rpt2_cache/
58 | .rts2_cache_cjs/
59 | .rts2_cache_es/
60 | .rts2_cache_umd/
61 |
62 | # Optional REPL history
63 | .node_repl_history
64 |
65 | # Output of 'npm pack'
66 | *.tgz
67 |
68 | # Yarn Integrity file
69 | .yarn-integrity
70 |
71 | # dotenv environment variables file
72 | .env
73 | .env.test
74 |
75 | # parcel-bundler cache (https://parceljs.org/)
76 | .cache
77 |
78 | # Next.js build output
79 | .next
80 |
81 | # Nuxt.js build / generate output
82 | .nuxt
83 | dist
84 |
85 | # Gatsby files
86 | .cache/
87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js
88 | # https://nextjs.org/blog/next-9-1#public-directory-support
89 | # public
90 |
91 | # vuepress build output
92 | .vuepress/dist
93 |
94 | # Serverless directories
95 | .serverless/
96 |
97 | # FuseBox cache
98 | .fusebox/
99 |
100 | # DynamoDB Local files
101 | .dynamodb/
102 |
103 | # TernJS port file
104 | .tern-port
105 |
106 | /test
107 | /docs/.vitepress/cache
108 | /docs/.vitepress/dist
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |

2 |
3 | Panacea
4 |
5 | Trading Bot Real-time Status Manager
6 |
7 |
8 | **Manage your trading bot anytime anywhere**
9 |
10 | > server side: XCoin,freqtrade,Zenbot or your own bot.
11 | >
12 | > client side: Android,Ios,Web,Linux, macOS and Windows.
13 |
14 | ## Screenshots
15 |
16 | ### Desktop
17 |
18 | 
19 |
20 | ### Mobile
21 |
22 | 
23 |
24 | ## Features
25 |
26 | - Support multiple open source trading bot or commercial trading bot
27 | - Support all platform(android,ios,web,windows,mac,linux)
28 | - Support multiple trading bot manage.
29 | - Support real-time trading, long short trading.
30 | - Support real-time modification of bot configuration.
31 | - Support real-time modification of bot strategies.
32 |
33 | ## Install
34 |
35 | ### Application
36 |
37 | Download application from the official website according to your needs [Desktop](https://www.ciiat.com/download) or [Mobile](https://www.ciiat.com/download)
38 |
39 | ### Developer
40 |
41 | ```bash
42 | git clone https://github.com/markmind/panacea-api.git
43 | ```
44 |
45 | ## Document
46 |
47 | You can use or participate in development through the Panacea user documentation and developer documentation
48 |
49 | - [User Document](docs/README.md)
50 |
51 | - [Developer](docs/developer.md)
52 |
53 | If you have problems and bugs, please submit them through Github, We will try our best to answer your questions in time. Of course, it would be greatly appreciated if you could submit a PR directly.
54 |
55 | You can click here to view the [中文](README.zh-CN.md) document
56 |
57 | ## Contributors
58 |
59 | Thanks to all contributors [[contributors](https://github.com/markmind/panacea-api/graphs/contributors)] who participated to Panacea project.
60 |
61 | ## License
62 |
63 | [**MIT**](https://opensource.org/licenses/MIT).
64 |
--------------------------------------------------------------------------------
/README.zh-CN.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | 灵丹
4 |
5 | 交易机器人实时状态管理
6 |
7 |
8 | **随时随地管理您的交易机器人**
9 |
10 | > 服务器端: XCoin,freqtrade,Zenbot 或您自己创建的机器人.
11 | >
12 | > 客户端: Android,Ios,Web,Linux,macOS and Windows.
13 |
14 | ## 屏幕截图
15 |
16 | ### 桌面
17 |
18 | 
19 |
20 | ### 移动设备
21 |
22 | 
23 |
24 | ## 功能特征
25 |
26 | - 提供统一API,支持多种开源交易机器人或商业闭源机器人.
27 | - 支持所有客户端,任意时间,任意地点管理您的交易.
28 | - 支持管理多个机器人,一键切换
29 | - 支持实时交易,支持多空操作,支持买卖点显示
30 | - 支持配置参数实时修改
31 | - 支持策略参数实时修改
32 |
33 | ## 安装
34 |
35 | ### 客户端安装
36 |
37 | 根据您的需要官网下载 [桌面版](https://www.ciiat.com/download) 或 [移动版](https://www.ciiat.com/download) 灵丹程序
38 |
39 | ### 扩展开发
40 |
41 | ```bash
42 | git clone https://github.com/markmind/panacea-api.git
43 | ```
44 |
45 | ## 文档
46 |
47 | 您可以通过用户文档与开发者文档了解灵丹的运行机制及参与开发.
48 |
49 | - [用户文档](docs/zh/README.md)
50 |
51 | - [开发者](docs/zh/developer.md)
52 |
53 | 如果您有使用上的问题与Bug,欢迎通过 Github 提交,我们会尽量及时回答您的问题。当然,如果您能够直接提交PR,我们将不胜感谢。
54 |
55 | 您可以点击这儿查看 [English](README.md) 文档.
56 |
57 | ## 贡献者
58 |
59 | 感谢所有参与灵丹项目的贡献者[[贡献者](https://github.com/markmind/panacea-api/graphs/contributors)].
60 |
61 | ## License
62 |
63 | [**MIT**](https://opensource.org/licenses/MIT).
64 |
--------------------------------------------------------------------------------
/docs/.vitepress/config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vitepress';
2 |
3 | export default defineConfig({
4 | title: 'Panacea',
5 | description: 'Trading Bot Real-time Status Manager',
6 | appearance: 'dark',
7 | base: '/panacea-api/',
8 | lastUpdated: true,
9 | ignoreDeadLinks: true,
10 | cleanUrls: 'true',
11 | markdown: {
12 | theme: 'material-theme-palenight',
13 | lineNumbers: false
14 | },
15 | locales: {
16 | zh: {
17 | label: '简体中文',
18 | lang: 'zh-CN',
19 | link: '/zh/',
20 | title: "灵丹",
21 | description: '交易机器人实时状态管理',
22 | themeConfig: {
23 | siteTitle: '灵丹',
24 | nav: nav_cn(),
25 | docFooter: {
26 | prev: '上一页',
27 | next: '下一页'
28 | },
29 | outlineTitle: '在此页',
30 | editLink: {
31 | pattern: 'https://github.com/markmind/panacea-api/docs/:path',
32 | text: '在GitHub上编辑此页面'
33 | },
34 | footer: {
35 | message: 'MIT 授权',
36 | copyright: '版权所有 © 2023 Ciiat Tech'
37 | },
38 | darkModeSwitchLabel: '外观',
39 | sidebarMenuLabel: '菜单',
40 | returnToTopLabel: '返回页首',
41 | langMenuLabel: '改变语言',
42 | lastUpdatedText: '最后更新'
43 | }
44 | },
45 | root: {
46 | label: 'English',
47 | lang: 'en-US',
48 | link: '/'
49 | }
50 | },
51 |
52 | // theme related configurations.
53 | themeConfig: {
54 | logo: '/images/logo.png',
55 | siteTitle: 'Panacea',
56 | i18nRouting: true,
57 | aside: 'true',
58 | docFooter: {
59 | prev: 'Previous Page',
60 | next: 'Next Page'
61 | },
62 | outlineTitle: 'On this page',
63 | editLink: {
64 | pattern: 'https://github.com/markmind/panacea-api/docs/:path',
65 | text: 'Edit this page on GitHub'
66 | },
67 | darkModeSwitchLabel: 'Appearance',
68 | sidebarMenuLabel: 'Menu',
69 | returnToTopLabel: 'Return to top',
70 | langMenuLabel: 'Change Language',
71 | lastUpdatedText: 'Last Updated',
72 | outline: 'deep',
73 | nav: nav(),
74 | sidebar: {
75 | '/': sidebarGuide(),
76 | '/zh/': sidebarGuide_cn()
77 | },
78 | footer: {
79 | message: 'Released under the MIT License',
80 | copyright: 'Copyright © 2023-present Ciiat Tech'
81 | },
82 | /* algolia: {
83 | appId: '8J64VVRP8K',
84 | apiKey: 'a18e2f4cc5665f6602c5631fd868adfd',
85 | indexName: 'xcoin'
86 | }, */
87 | socialLinks: [
88 | { icon: 'github', link: 'https://github.com/markmind/panacea-api' }
89 | ]
90 | }
91 | })
92 |
93 | function nav_cn() {
94 | return [
95 | { text: '指南', link: '/zh/panacea.md' },
96 | { text: 'API', link: '/zh/status.md' },
97 | { text: '反馈', link: 'https://github.com/markmind/panacea-api/issues' }
98 | ]
99 | }
100 |
101 | function nav() {
102 | return [
103 | { text: 'Guide', link: '/panacea.md' },
104 | { text: 'API', link: '/status.md' },
105 | { text: 'Feedback', link: 'https://github.com/markmind/panacea-api/issues' }
106 | ]
107 | }
108 |
109 | function sidebarGuide_cn() {
110 | return [
111 | {
112 | text: '简介',
113 | collapsed: false,
114 | items: [
115 | { text: '灵丹', link: '/zh/panacea' },
116 | { text: '开发者', link: '/zh/developer' },
117 | { text: '常见问题', link: '/zh/faq' },
118 | ]
119 | },
120 | {
121 | text: 'API',
122 | collapsed: false,
123 | items: [
124 | { text: '状态', link: '/zh/status' },
125 | { text: '操作', link: '/zh/operation' },
126 | { text: '配置', link: '/zh/config' },
127 | { text: '策略', link: '/zh/strategy' },
128 | { text: '市场', link: '/zh/market' }
129 | ]
130 | }
131 | ]
132 | }
133 |
134 | function sidebarGuide() {
135 | return [
136 | {
137 | text: 'Introduction',
138 | collapsed: false,
139 | items: [
140 | { text: 'Panacea', link: '/panacea' },
141 | { text: 'Developer', link: '/developer' },
142 | { text: 'Faq', link: '/faq' },
143 | ]
144 | },
145 | {
146 | text: 'API',
147 | collapsed: false,
148 | items: [
149 | { text: 'Status', link: '/status' },
150 | { text: 'Operation', link: '/operation' },
151 | { text: 'Config', link: '/config' },
152 | { text: 'Strategy', link: '/strategy' },
153 | { text: 'Market', link: '/market' }
154 | ]
155 | }
156 | ]
157 | }
158 |
--------------------------------------------------------------------------------
/docs/.vitepress/theme/custom.css:
--------------------------------------------------------------------------------
1 | /* .vitepress/theme/custom.css colors */
2 | :root {
3 | --vp-c-brand: #cddc39;
4 | --vp-c-brand-light: #f5d419;
5 | --vp-c-brand-lighter: #fddc99;
6 | --vp-c-brand-lightest: #fddc99;
7 | --vp-c-brand-dark: #535bf2;
8 | --vp-c-brand-darker: #454ce1;
9 | --vp-c-brand-dim: rgba(100, 108, 255, 0.08);
10 | }
11 |
12 | /* .vitepress/theme/custom.css home */
13 |
14 |
15 |
16 | .VPImage.image-src {
17 | position: absolute;
18 | top: 50%;
19 | left: 50%;
20 | max-width: 320px;
21 | max-height: 320px;
22 | transform: translate(-50%, -50%);
23 | }
24 |
25 | @media (min-width: 640px) {
26 | .VPImage.image-src {
27 | max-width: 480px;
28 | max-height: 480px;
29 | }
30 | }
31 |
32 | @media (min-width: 960px) {
33 | .VPImage.image-src {
34 | max-width: 560px;
35 | max-height: 560px;
36 | }
37 | }
--------------------------------------------------------------------------------
/docs/.vitepress/theme/index.js:
--------------------------------------------------------------------------------
1 | // .vitepress/theme/index.js
2 | import DefaultTheme from 'vitepress/theme';
3 | import './custom.css';
4 | export default DefaultTheme;
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # User Document
2 |
3 | **Introduction:**
4 |
5 | - [Panacea](panacea.md)
6 | - [Developer](developer.md)
7 | - [Faq](faq.md)
8 |
9 | **API:**
10 |
11 | - [Status](status.md)
12 | - [Operation](operation.md)
13 | - [Config](config.md)
14 | - [Strategy](strategy.md)
15 | - [Market](market.md)
16 |
--------------------------------------------------------------------------------
/docs/config.md:
--------------------------------------------------------------------------------
1 | # Config API
2 |
3 | Config API provides the necessary data for the configuration module of the client. Through the configuration module, all your configurations on the server can be updated in real time through the client. Currently includes the following APIs
4 |
5 | - init: gets configuration settings and configuration values
6 | - updateConfig: update configuration
7 | - updateSymbolFuture: update trading pair configuration
8 |
9 | ## Implementation
10 |
11 | > **Optional**
12 | > If API is not implemented, the client will not have a configuration module.
13 | > If API is not implemented, please set `hasConfig` to `false` in the `init` of the robot state in the state API
14 |
15 | ## Update process
16 |
17 | - Pass configuration settings and configuration values in the `init` event
18 | - Generate the UI interface on the client side through configuration settings
19 | - Modify the configuration through the UI interface and update the server-side value through `updateConfig`
20 |
21 | ## API List
22 |
23 | ### - init
24 |
25 | When using the configuration module, configuration settings and configuration parameters will be passed to the client through `init`
26 |
27 | #### Request
28 |
29 | > When use connects to the bot, data will push to client.
30 | > When device reconnection (such asresume event),data push to client.
31 |
32 | ```javascript
33 | {
34 | "action": "init",
35 | "apiKey":"YOUR API KEY"
36 | }
37 | ```
38 |
39 | #### Response
40 |
41 | ```javascript
42 | {
43 | "options": { //Bot config ,all values are set buy config settings
44 | "strategy": "BollingerBands",
45 | "period": "10m",
46 | "debug": false
47 | ...
48 | },
49 | "config": { //config settings,include group,subgroup and item
50 | "bot": [//bot group realted
51 | {
52 | "name": "strategy",//config item name such as strategy
53 | "type": "string",//config item type
54 | "value": "BollingerBands"//config item value
55 | },
56 | {
57 | "name": "period",//config item name such as period
58 | "type": "array",//array list
59 | "list": [//list value
60 | "1m",
61 | "3m",
62 | "5m"
63 | ],
64 | "value": "5m"
65 | },
66 | {
67 | "name": "debug",//config item name such as debug
68 | "type": "bool",//bool
69 | "value": false
70 | },
71 | {
72 | "name": "other",//group name
73 | "type": "group"//config item is group
74 | },
75 | {
76 | "name": "poll_scan_time",//config item ,such as poll timeout
77 | "type": "number",//config item type
78 | "step": [//config item step
79 | 1000,//min
80 | 60000,//max
81 | 500//step
82 | ],
83 | "value": 3000,
84 | "des": true//this item has description
85 | },
86 | {
87 | "name": "black_list",//config item name ,such as black_list
88 | "type": "textarea",//config item type
89 | "value": 'binance.BTC-USDT,binance.AAB-USDt', //config item value
90 | "des": true
91 | },
92 | ...
93 | ],
94 | "exchange": [], //exchange related config,
95 | "order": [], //order related config,
96 | "sellPoint": [], //sell point related config,
97 | "watch": [], //watch pool related config
98 | "paper":[],//papaer related config
99 | }
100 | }
101 | ```
102 |
103 | ### - updateConfig
104 |
105 | Update config params and restart bot or not
106 |
107 | #### Request
108 |
109 | ```javascript
110 | {
111 | "action": "updateConfig",
112 | "restart": true, //should restart bot or not
113 | "data": {
114 | "period": "3m", //update params
115 | "buy_pct":30 //update params
116 | },
117 | "apiKey": "YOUR API KEY"
118 | }
119 | ```
120 |
121 | #### Response
122 |
123 | ```javascript
124 | {
125 | "action": "updateConfig",
126 | "data":Object, //response all params object
127 | "toast": "trade.updateConfigOk" //show toast message
128 | }
129 | ```
130 |
131 | ### - updateSymbolFuture
132 |
133 | Update symbol future parmas,now support future leverage and future mode
134 |
135 | #### Request
136 |
137 | ```javascript
138 | {
139 | "action": "updateSymbolFuture",
140 | "symbol":"BTC-USDT", //pair
141 | "data":{
142 | "type":"leverage",//marginMode or leverage
143 | "value":10 //type is marginMode ,value is cross or isolated
144 | },
145 | "apiKey": "YOUR API KEY"
146 | }
147 | ```
148 |
149 | #### Response
150 |
151 | ```javascript
152 | {
153 | "action": "updateSymbolFuture",
154 | "toast": "trade.updateSymbolFutureOk"
155 | }
156 | ```
157 |
158 | > A sample config file for extension/xcoin
159 |
160 | ````json
161 | {
162 | "bot": [
163 | {
164 | "name": "strategy",
165 | "type": "string",
166 | "value": "rain_sar"
167 | },
168 | {
169 | "name": "period",
170 | "type": "array",
171 | "list": [
172 | "1m",
173 | "3m",
174 | "5m",
175 | "15m",
176 | "30m",
177 | "1h",
178 | "2h",
179 | "4h",
180 | "8h",
181 | "12h",
182 | "1d",
183 | "3d",
184 | "1w"
185 | ],
186 | "value": "30m"
187 | },
188 | {
189 | "name": "mode",
190 | "type": "array",
191 | "list": [
192 | "live",
193 | "paper"
194 | ],
195 | "value": "live"
196 | },
197 | {
198 | "name": "trade_type",
199 | "type": "array",
200 | "list": [
201 | "auto",
202 | "autoBuy",
203 | "autoSell",
204 | "manual"
205 | ],
206 | "value": "live"
207 | },
208 | {
209 | "name": "debug",
210 | "type": "bool",
211 | "value": false
212 | },
213 | {
214 | "name": "other",
215 | "type": "group"
216 | },
217 | {
218 | "name": "poll_scan_time",
219 | "type": "number",
220 | "step": [
221 | 1000,
222 | 60000,
223 | 500
224 | ],
225 | "value": 3000,
226 | "des": true
227 | },
228 | {
229 | "name": "poll_broadcast_time",
230 | "type": "number",
231 | "step": [
232 | 3000,
233 | 60000,
234 | 1000
235 | ],
236 | "value": 5000,
237 | "des": true
238 | },
239 | {
240 | "name": "save_bot_time",
241 | "type": "number",
242 | "step": [
243 | 6000,
244 | 6000000,
245 | 6000
246 | ],
247 | "value": 600000,
248 | "des": true
249 | },
250 | {
251 | "name": "min_periods",
252 | "type": "number",
253 | "step": [
254 | 18,
255 | 500,
256 | 1
257 | ],
258 | "value": 32
259 | },
260 | {
261 | "name": "keep_lookback_periods",
262 | "type": "number",
263 | "step": [
264 | 50,
265 | 50000,
266 | 10
267 | ],
268 | "value": 500
269 | },
270 | {
271 | "name": "price_format",
272 | "type": "string",
273 | "value": "0.00000000"
274 | },
275 | {
276 | "name": "same_period_multi_buy",
277 | "type": "bool",
278 | "value": false
279 | },
280 | {
281 | "name": "run_for",
282 | "type": "number",
283 | "step": [
284 | 0,
285 | 1000,
286 | 1
287 | ],
288 | "value": 0,
289 | "des": true
290 | }
291 | ],
292 | "exchange": [
293 | {
294 | "name": "exchange",
295 | "type": "array",
296 | "list": [
297 | "binanceusdm",
298 | "binance",
299 | "mexc"
300 | ],
301 | "value": "binanceusdm"
302 | },
303 | {
304 | "name": "takerFee",
305 | "type": "number",
306 | "step": [
307 | 0.001,
308 | 0.5,
309 | 0.001
310 | ],
311 | "value": 0.1
312 | },
313 | {
314 | "name": "makerFee",
315 | "type": "number",
316 | "step": [
317 | 0.001,
318 | 0.5,
319 | 0.001
320 | ],
321 | "value": 0.1
322 | },
323 | {
324 | "name": "future",
325 | "type": "group"
326 | },
327 | {
328 | "name": "future",
329 | "type": "bool",
330 | "value": false,
331 | "readonly": true
332 | },
333 | {
334 | "name": "market",
335 | "type": "array",
336 | "list": [
337 | "only_long",
338 | "only_short",
339 | "both"
340 | ],
341 | "value": "only_long"
342 | },
343 | {
344 | "name": "leverage",
345 | "type": "number",
346 | "step": [
347 | 2,
348 | 125,
349 | 1
350 | ],
351 | "value": 10
352 | },
353 | {
354 | "name": "marginMode",
355 | "type": "array",
356 | "list": [
357 | "cross",
358 | "isolated"
359 | ],
360 | "value": "isolated"
361 | },
362 | {
363 | "name": "short_buy_pct",
364 | "type": "number",
365 | "step": [
366 | 0,
367 | 100,
368 | 1
369 | ],
370 | "value": 20
371 | },
372 | {
373 | "name": "buy_position_side_when_sell",
374 | "type": "bool",
375 | "value": false
376 | }
377 | ],
378 | "order": [
379 | {
380 | "name": "order_type",
381 | "type": "array",
382 | "list": [
383 | "maker",
384 | "taker"
385 | ],
386 | "value": "maker"
387 | },
388 | {
389 | "name": "max_slippage_pct",
390 | "type": "number",
391 | "step": [
392 | 0.1,
393 | 2,
394 | 0.1
395 | ],
396 | "value": 0.5,
397 | "group": "core"
398 | },
399 | {
400 | "name": "buy",
401 | "type": "group"
402 | },
403 | {
404 | "name": "buy_pct",
405 | "type": "number",
406 | "step": [
407 | 0,
408 | 100,
409 | 1
410 | ],
411 | "value": 20
412 | },
413 | {
414 | "name": "min_buy_size",
415 | "type": "number",
416 | "step": [
417 | 0,
418 | 100,
419 | 1
420 | ],
421 | "value": 10
422 | },
423 | {
424 | "name": "max_buy_size",
425 | "type": "number",
426 | "step": [
427 | 0,
428 | 10000,
429 | 100
430 | ],
431 | "value": 0
432 | },
433 | {
434 | "name": "sell",
435 | "type": "group"
436 | },
437 | {
438 | "name": "sell_pct",
439 | "type": "number",
440 | "step": [
441 | 0,
442 | 100,
443 | 1
444 | ],
445 | "value": 100,
446 | "group": "sell"
447 | },
448 | {
449 | "name": "other",
450 | "type": "group"
451 | },
452 | {
453 | "name": "order_adjust_time",
454 | "type": "number",
455 | "step": [
456 | 1000,
457 | 1000,
458 | 1000
459 | ],
460 | "value": 5000,
461 | "group": "other"
462 | },
463 | {
464 | "name": "max_sell_loss_pct",
465 | "type": "number",
466 | "step": [
467 | 0,
468 | 5,
469 | 0.5
470 | ],
471 | "value": 1,
472 | "group": "other"
473 | },
474 | {
475 | "name": "max_buy_loss_pct",
476 | "type": "number",
477 | "step": [
478 | 0,
479 | 5,
480 | 0.5
481 | ],
482 | "value": 1,
483 | "group": "other"
484 | },
485 | {
486 | "name": "order_poll_time",
487 | "type": "number",
488 | "step": [
489 | 1000,
490 | 60000,
491 | 1000
492 | ],
493 | "value": 5000,
494 | "group": "other"
495 | },
496 | {
497 | "name": "wait_for_settlement",
498 | "type": "number",
499 | "step": [
500 | 1000,
501 | 60000,
502 | 1000
503 | ],
504 | "value": 5000,
505 | "group": "other",
506 | "des": true
507 | },
508 | {
509 | "name": "markdown_buy_pct",
510 | "type": "number",
511 | "step": [
512 | 0,
513 | 5,
514 | 0.1
515 | ],
516 | "value": 0,
517 | "group": "other"
518 | },
519 | {
520 | "name": "markup_sell_pct",
521 | "type": "number",
522 | "step": [
523 | 0,
524 | 5,
525 | 0.1
526 | ],
527 | "value": 0,
528 | "group": "other"
529 | },
530 | {
531 | "name": "post_only",
532 | "type": "bool",
533 | "value": false,
534 | "group": "other"
535 | },
536 | {
537 | "name": "use_fee_asset",
538 | "type": "bool",
539 | "value": false,
540 | "group": "other"
541 | },
542 | {
543 | "name": "avg_slippage_pct",
544 | "type": "number",
545 | "value": 0.045,
546 | "step": [
547 | 0,
548 | 0.1,
549 | 0.005
550 | ],
551 | "group": "other"
552 | },
553 | {
554 | "name": "quarentine_time",
555 | "type": "number",
556 | "step": [
557 | 0,
558 | 100000,
559 | 1000
560 | ],
561 | "value": 0,
562 | "group": "other"
563 | }
564 | ],
565 | "sellPoint": [
566 | {
567 | "name": "sell_stop_pct",
568 | "type": "number",
569 | "step": [
570 | 0,
571 | 30,
572 | 0.1
573 | ],
574 | "value": 5
575 | },
576 | {
577 | "name": "profitStop",
578 | "type": "group"
579 | },
580 | {
581 | "name": "profit_stop_enable",
582 | "type": "bool",
583 | "value": true
584 | },
585 | {
586 | "name": "profit_stop_percent",
587 | "type": "number",
588 | "step": [
589 | 0,
590 | 100,
591 | 1
592 | ],
593 | "value": 50
594 | },
595 | {
596 | "name": "profit_stop_first_rate",
597 | "type": "number",
598 | "step": [
599 | 0,
600 | 500,
601 | 1
602 | ],
603 | "value": 10
604 | },
605 | {
606 | "name": "profit_stop_first_percent",
607 | "type": "number",
608 | "step": [
609 | 0,
610 | 100,
611 | 1
612 | ],
613 | "value": 30
614 | },
615 | {
616 | "name": "profit_stop_second_rate",
617 | "type": "number",
618 | "step": [
619 | 0,
620 | 500,
621 | 1
622 | ],
623 | "value": 20
624 | },
625 | {
626 | "name": "profit_stop_second_percent",
627 | "type": "number",
628 | "step": [
629 | 0,
630 | 100,
631 | 1
632 | ],
633 | "value": 40
634 | },
635 | {
636 | "name": "profit_stop_third_rate",
637 | "type": "number",
638 | "step": [
639 | 0,
640 | 500,
641 | 1
642 | ],
643 | "value": 50
644 | },
645 | {
646 | "name": "profit_stop_third_percent",
647 | "type": "number",
648 | "step": [
649 | 0,
650 | 100,
651 | 1
652 | ],
653 | "value": 50
654 | },
655 | {
656 | "name": "profit_stop_max_rate",
657 | "type": "number",
658 | "step": [
659 | 0,
660 | 500,
661 | 1
662 | ],
663 | "value": 100
664 | },
665 | {
666 | "name": "profit_stop_max_percent",
667 | "type": "number",
668 | "step": [
669 | 0,
670 | 100,
671 | 1
672 | ],
673 | "value": 70
674 | },
675 | {
676 | "name": "profitSell",
677 | "type": "group"
678 | },
679 | {
680 | "name": "profit_win_enable",
681 | "type": "bool",
682 | "value": true
683 | },
684 | {
685 | "name": "profit_win_first_rate",
686 | "type": "number",
687 | "step": [
688 | 0,
689 | 500,
690 | 1
691 | ],
692 | "value": 25
693 | },
694 | {
695 | "name": "profit_win_first_percent",
696 | "type": "number",
697 | "step": [
698 | 0,
699 | 100,
700 | 1
701 | ],
702 | "value": 50
703 | },
704 | {
705 | "name": "profit_win_second_rate",
706 | "type": "number",
707 | "step": [
708 | 0,
709 | 500,
710 | 1
711 | ],
712 | "value": 50
713 | },
714 | {
715 | "name": "profit_win_second_percent",
716 | "type": "number",
717 | "step": [
718 | 0,
719 | 100,
720 | 1
721 | ],
722 | "value": 50
723 | },
724 | {
725 | "name": "profit_win_third_rate",
726 | "type": "number",
727 | "step": [
728 | 0,
729 | 500,
730 | 1
731 | ],
732 | "value": 100
733 | },
734 | {
735 | "name": "profit_win_third_percent",
736 | "type": "number",
737 | "step": [
738 | 0,
739 | 100,
740 | 1
741 | ],
742 | "value": 50
743 | },
744 | {
745 | "name": "profit_win_max_rate",
746 | "type": "number",
747 | "step": [
748 | 0,
749 | 500,
750 | 1
751 | ],
752 | "value": 200
753 | },
754 | {
755 | "name": "profit_win_max_percent",
756 | "type": "number",
757 | "step": [
758 | 0,
759 | 100,
760 | 1
761 | ],
762 | "value": 50
763 | }
764 | ],
765 | "watch": [
766 | {
767 | "name": "max_watch_size",
768 | "type": "number",
769 | "step": [
770 | 0,
771 | 30,
772 | 5
773 | ],
774 | "value": 10
775 | },
776 | {
777 | "name": "watch_symbols",
778 | "type": "textarea",
779 | "value": "",
780 | "placeholder": true
781 | },
782 | {
783 | "name": "watchInit",
784 | "type": "group"
785 | },
786 | {
787 | "name": "watch_include_bought",
788 | "type": "bool",
789 | "value": true
790 | },
791 | {
792 | "name": "watch_with_black_list",
793 | "type": "bool",
794 | "value": true
795 | },
796 | {
797 | "name": "black_list",
798 | "type": "textarea",
799 | "value": "",
800 | "placeholder": true
801 | }
802 | ],
803 | "paper": [
804 | {
805 | "name": "currency_capital",
806 | "type": "number",
807 | "step": [
808 | 0,
809 | 10000,
810 | 1000
811 | ],
812 | "value": 1000
813 | },
814 | {
815 | "name": "asset_capital",
816 | "type": "number",
817 | "step": [
818 | 0,
819 | 10000,
820 | 1000
821 | ],
822 | "value": 0
823 | }
824 | ]
825 | }
826 | ````
827 |
--------------------------------------------------------------------------------
/docs/developer.md:
--------------------------------------------------------------------------------
1 | # Developer
2 |
3 | Panacea provides a easy way to manage your real-time trading bot status. You can adapt to your own bots by developing extensions. Your are welcome to add extensions based on Freqtrade, Zenbot, and others
4 |
5 | ## Development process
6 |
7 | 1. Understand the Panacea API and decide which APIs you need to adapt to
8 |
9 | 2. Add an extension based on Panacea to your bot code
10 |
11 | 3. Download the Panacea application [Download Panacea](https://www.ciiat.com/en/download) and add your trading bot for testing
12 |
13 | 4. You can also directly use the [Web version of Panacea](https://www.ciiat.com/app/www) Directly add your trading bot for testing
14 |
15 | 5. Download the Panacea API code and place your relevant code in the 'extensions' directory
16 |
17 | ```bash
18 | git clone https://github.com/markmind/panacea-api.git
19 | ```
20 |
21 | 6. Submit a PR and we will merge as soon as possible
22 |
23 | ## Precautions
24 |
25 | - When adding code, it is necessary to add the README.md file in the root directory to help users understand the details of using the extension
26 | - All extensions need to follow 'MIT' license
27 | - You can download and run [XCoin](https://github.com/rianfu/xcoin) to learn how to use api.
28 |
--------------------------------------------------------------------------------
/docs/faq.md:
--------------------------------------------------------------------------------
1 | # FAQ
2 |
3 | Here are some frequently asked questions and responses from the community.
4 |
5 | If you have a question that isn't answered here, please ask it in the community
6 |
7 | Thanks!
8 |
9 | ## Question
10 |
11 | ### [Develop](#develop)
12 |
13 | ## Answer
14 |
15 | ### Develop
16 |
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: home
3 |
4 | hero:
5 | name: Panacea
6 | text: Trading Bot Real-time Status Manager
7 | tagline: Manage your trading bot anytime, anywhere
8 | image:
9 | src: /images/web_top_en.png
10 | alt: Panacea
11 |
12 | actions:
13 | - theme: brand
14 | text: Get Started
15 | link: /panacea
16 | - theme: sponsor
17 | text: Demo
18 | link: https://www.ciiat.com/app/www
19 | - theme: sponsor
20 | text: Download
21 | link: https://www.ciiat.com/en/download
22 | - theme: alt
23 | text: View on GitHub
24 | link: https://github.com/markmind/panacea-api
25 |
26 | features:
27 | - title: Provide Unified API
28 | details: Support multiple open source trading bot or commercial trading bots.
29 | - title: Supports all platform
30 | details: Manage your transactions anytime, anywhere on your desktop or mobile device.
31 | - title: Multi trading bot management
32 | details: Supports managing multiple bot with one click switching.
33 | - title: Support real-time trading
34 | details: Support long short operations and display of buying and selling points。
35 | - title: Supports real-time modification of configuration
36 | details: Support changing parameters at runtime and remote start stop to apply parameters
37 | - title: Supports real-time modification of strategies
38 | details: Support changing strategies or adjusting strategy parameters at runtime, and support remote start stop to use new strategy.
39 | ---
40 |
--------------------------------------------------------------------------------
/docs/market.md:
--------------------------------------------------------------------------------
1 | # Market API
2 |
3 | Market API provide data for client market module,Inclues APIs
4 |
5 | - getProducts Get products
6 | - getTickers Get products tickers
7 | - getKlines Get kline for symbol
8 | - getPickerNormal Get hot products in exchange
9 |
10 | ## Implementation
11 |
12 | >**Optional**
13 | >If this API is not implemented, the client will not have a market module
14 | >If this API is not implemented, please set `hasMarket` to `false` in the `init` of the bot's status`
15 |
16 | ## API List
17 |
18 | ### - getProducts
19 |
20 | Get all products in bot exchange
21 |
22 | #### Request
23 |
24 | ```javascript
25 | {
26 | "action": "getProducts",
27 | "apiKey":"YOUR API KEY"
28 | }
29 | ```
30 |
31 | #### Response
32 |
33 | ```javascript
34 | {
35 | "action": "getProducts",
36 | "data":[{
37 | "id": "1INCH_USDT", //pair id
38 | "asset": "1INCH",//asset
39 | "currency": "USDT",//currency
40 | "active": true,
41 | "min_size": "0.01",//min asset size
42 | "increment": "0.0001",//price increment
43 | "asset_increment": "0.01",//asset increment
44 | "label": "1INCH/USDT",
45 | "exchagne_id": "mexc",
46 | "product_id": "1INCH-USDT",
47 | "normalized": "mexc.1INCH-USDT"
48 | },
49 | ...
50 | ]
51 | }
52 | ```
53 |
54 | ### - getTickers
55 |
56 | Get tickers for request symbols or all products in exchange,
57 |
58 | > response all products tickers when no symbols input
59 |
60 | #### Request
61 |
62 | ```javascript
63 | {
64 | "action": "getTickers",
65 | "data": {
66 | "symbols": [
67 | {
68 | "product_id": "1INCH-USDT"
69 | },
70 | ...
71 | ]
72 | },
73 | "apiKey": "YOUR API KEY"
74 | }
75 | ```
76 |
77 | #### Response
78 |
79 | ```javascript
80 | {
81 | "action": "getTickers",
82 | "data": [
83 | {
84 | "symbol": "GDO/USDT",//symbol name
85 | "price": 8.98e-8, //real-time price
86 | "percentage": 1 //24hr price changed rate
87 | }
88 | ...
89 | ]
90 | }
91 | ```
92 |
93 | ### - getPickerNormal
94 |
95 | Get hot products in the bot exchange
96 |
97 | > Get some featured products ,such as Maximum amplitude...
98 |
99 | #### Request
100 |
101 | ```javascript
102 | {
103 | "action": "getPickerNormal",
104 | "data": {
105 | "period": "1d", //kline period
106 | "limit": 10,// result data length
107 | "number": 8 //min kline data length
108 | },
109 | "apiKey": "YOUR API KEY"
110 | }
111 | ```
112 |
113 | #### Response
114 |
115 | ```javascript
116 | {
117 | "action": "getPickerNormal",
118 | "data": {
119 | "maxSum": [//Maximum amplitude
120 | {
121 | "index": 1, //order
122 | "product_id": "ARB-USDT",
123 | "price": 1.3181,
124 | "extra": "12400.37%", //Total amplitude rate
125 | "klines": [
126 | {
127 | "time": 1679529600000,
128 | "close": 1.3181
129 | }
130 | ...
131 | ]
132 | }
133 | ...
134 | ],
135 | "minSum": [//Minimum amplitude
136 | {
137 | "index": 1,//order
138 | "product_id": "BUSD-USDT",
139 | "price": 0.9982,
140 | "extra": "2.04%", //Total amplitude rate
141 | "klines": [
142 | {
143 | "time": 1678752000000,
144 | "close": 0.9965
145 | },
146 | ...
147 | ]
148 | },
149 | ...
150 | ],
151 | "fastUp": [//Maximum Up
152 | {
153 | "index": 1,//order
154 | "product_id": "ID-USDT",
155 | "price": 0.5285,
156 | "extra": "2014.00%",//total up rate
157 | "klines": [
158 | {
159 | "time": 1679443200000,
160 | "close": 0.40696
161 | },
162 | ...
163 | ]
164 | },
165 | ...
166 | ],
167 | "moreUp": [//More up
168 | {
169 | "index": 1,// order
170 | "product_id": "LOOP-USDT",
171 | "price": 0.12923,
172 | "extra": "9/10",// up line length
173 | "klines": [
174 | {
175 | "time": 1679529600000,
176 | "close": 0.12923
177 | },
178 | ...
179 | ]
180 | },
181 | ...
182 | ],
183 | "continueUp": [//Continue Up
184 | {
185 | "index": 1, //order
186 | "product_id": "LOOP-USDT",
187 | "price": 0.12923,
188 | "extra": 9, //continue up length
189 | "klines": [
190 | {
191 | "time": 1678752000000,
192 | "close": 0.03596
193 | },
194 | ...
195 | ],
196 | ...
197 | }
198 | ]
199 | }
200 | }
201 | ```
202 |
203 | ### getKlines
204 |
205 | Get klines for symbol
206 |
207 | #### Request
208 |
209 | ```javascript
210 | {
211 | "action": "getKlines",
212 | "symbol": "ALGO-USDT", //symbol
213 | "data": {
214 | "product_id": "ALGO-USDT",
215 | "limit": 60, //kline data length
216 | "period": "30m" //kline period
217 | },
218 | "apiKey": "YOUR API KEY"
219 | }
220 | ```
221 |
222 | #### Response
223 |
224 | ```javascript
225 | {
226 | "action": "getKlines",
227 | "data": {
228 | "period": "30m", //kline period
229 | "klines": [
230 | {
231 | "period_id": "30m933888",//kline id
232 | "time": 1680768000,//kline start time
233 | "size": "30m",//period
234 | "close_time": 1681000199999,//kline close time
235 | "open": 0.216,
236 | "high": 0.2169,
237 | "low": 0.2157,
238 | "close": 0.2169,
239 | "volume": 12943.41
240 | }
241 | ...
242 | ]
243 | }
244 | }
245 | ```
246 |
--------------------------------------------------------------------------------
/docs/operation.md:
--------------------------------------------------------------------------------
1 | # Operation API
2 |
3 | Operation API provide interaction with the server, which can be divided into several types according to different functions
4 |
5 | - Watch symbols
6 | - addSymbol
7 | - removeSymbol
8 | - removeAllSymbol
9 | - Trade for symbol
10 | - buy
11 | - sell
12 | - sellAll
13 |
14 | ## Implementation
15 |
16 | > **Must**
17 |
18 | ## API List
19 |
20 | ### - addSymbol
21 |
22 | Add new symbol to watch symbols
23 |
24 | #### Request
25 |
26 | ```javascript
27 | {
28 | "action": "addSymbol",
29 | "symbols": [
30 | "mexc.ACM-USDT" //add symbol name
31 | ],
32 | "data": {},
33 | "apiKYOUR API KEYJYOyKq"
34 | }
35 | ```
36 |
37 | #### Response
38 |
39 | ```javascript
40 | {
41 | "action": "addSymbol",
42 | "toast": "trade.addSymbolOk",//toast to show
43 | "data": {
44 | "success": true
45 | }
46 | }
47 | ```
48 |
49 | ### - removeSymbol
50 |
51 | Remove symbols for watch symbols,
52 |
53 | #### Request
54 |
55 | ```javascript
56 | {
57 | "action": "removeSymbol",
58 | "symbol": "mexc.ETH-USDT", //remove symbol name
59 | "apiKey": "YOUR API KEY"
60 | }
61 | ```
62 |
63 | #### Response
64 |
65 | ```javascript
66 | {
67 | "action": "removeSymbol",
68 | "toast": "trade.removeSymbolOk",
69 | "data": {
70 | "success": true
71 | }
72 | }
73 | ```
74 |
75 | ### - removeAllSymbol
76 |
77 | Remove all symbols from watch symbols
78 |
79 | #### Request
80 |
81 | ```javascript
82 | {
83 | "action": "removeAllSymbol",
84 | "apiKey": "YOUR API KEY"
85 | }
86 | ```
87 |
88 | #### Response
89 |
90 | ```javascript
91 | {
92 | "action": "removeAllSymbol",
93 | "toast": "trade.removeAllSymbolOk"
94 | }
95 | ```
96 |
97 | ### buy
98 |
99 | buy symbol
100 |
101 | #### Request
102 |
103 | ```javascript
104 | {
105 | "action": "buy",
106 | "symbol": "BTC-USDT",
107 | "data": {
108 | "position_side": "LONG", //LONG buy OR SHORT buy
109 | "size":20//buy size
110 | },
111 | "apiKey": "YOUR API KEY"
112 | }
113 | ```
114 |
115 | #### Response
116 |
117 | ```javascript
118 | {
119 | "action": "buy",
120 | "toast": "trade.buyOk" //toast to show
121 | }
122 | ```
123 |
124 | ### -Sell
125 |
126 | sell symbol
127 |
128 | #### Request
129 |
130 | ```javascript
131 | {
132 | "action": "sell",
133 | "symbol": "BTC-USDT",
134 | "data": {
135 | "position_side": "LONG", //LONG sell OR SHORT sell
136 | "size":20// sell size
137 | },
138 | "apiKey": "YOUR API KEY"
139 | }
140 | ```
141 |
142 | #### Response
143 |
144 | ```javascript
145 | {
146 | "action": "sell",
147 | "toast": "trade.sellOk" //toast to show
148 | }
149 | ```
150 |
151 | ### - sellAll
152 |
153 | sell all symbols
154 |
155 | #### Request
156 |
157 | ```javascript
158 | {
159 | "action": "sellAll",
160 | "apiKey": "YOUR API KEY"
161 | }
162 | ```
163 |
164 | #### Response
165 |
166 | ```javascript
167 | {
168 | "action": "sellAll",
169 | "toast": "trade.sellAllOk" //toast to show
170 | }
171 | ```
172 |
--------------------------------------------------------------------------------
/docs/panacea.md:
--------------------------------------------------------------------------------
1 | # About Panacea
2 |
3 | Panacea expands the functions of your trading bot through a simple method, allowing you to control and observe your bot at any time and any place through desktop or mobile devices, through the status, operation, config, strategy, etc. you can find out the ideal trading method more quickly and reasonably, greatly reducing the risk of quantitative trading and improving the profitability of trading.
4 |
5 | ## Screenshot
6 |
7 | ### Desktop
8 |
9 | includes Windows,Osx and Linux client
10 |
11 | 
12 |
13 | ### Mobile
14 |
15 | includes Android and Ios client
16 |
17 | 
18 |
19 | Before you can adapt your trading bot to Panacea, there are a few things you need to know about how we work.
20 |
21 | ## Page Architecture
22 |
23 | Depending on what you implement the API, Panacea will display different page content
24 |
25 | > Status and Operation API is the core function of panacea that must be implemented
26 | > If you do not implement the configuration function, the panacea configuration module will not be enabled
27 |
28 | - bot
29 | - Bot management
30 | - Config management
31 | - Strategy management
32 | - Watch list
33 | - Trading pair
34 | - Trading history
35 | - market
36 | - Trading pair list
37 | - Trading pair
38 | - Hot products
39 |
40 | ## API support
41 |
42 | - Bot status `Required`
43 | - Bot operation `Required`
44 | - Bot config `Optional`
45 | - Bot strategy `Optional`
46 | - Bot Exchange Market `Optional`
47 |
--------------------------------------------------------------------------------
/docs/public/images/desktop.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/markmind/panacea-api/ac40fc5d3657019cbf7ae306d34024dd880be7b5/docs/public/images/desktop.jpg
--------------------------------------------------------------------------------
/docs/public/images/desktop_cn.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/markmind/panacea-api/ac40fc5d3657019cbf7ae306d34024dd880be7b5/docs/public/images/desktop_cn.jpg
--------------------------------------------------------------------------------
/docs/public/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/markmind/panacea-api/ac40fc5d3657019cbf7ae306d34024dd880be7b5/docs/public/images/logo.png
--------------------------------------------------------------------------------
/docs/public/images/screenshot.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/markmind/panacea-api/ac40fc5d3657019cbf7ae306d34024dd880be7b5/docs/public/images/screenshot.jpg
--------------------------------------------------------------------------------
/docs/public/images/screenshot_cn.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/markmind/panacea-api/ac40fc5d3657019cbf7ae306d34024dd880be7b5/docs/public/images/screenshot_cn.jpg
--------------------------------------------------------------------------------
/docs/public/images/screenshot_large.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/markmind/panacea-api/ac40fc5d3657019cbf7ae306d34024dd880be7b5/docs/public/images/screenshot_large.jpg
--------------------------------------------------------------------------------
/docs/public/images/screenshot_large_zh.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/markmind/panacea-api/ac40fc5d3657019cbf7ae306d34024dd880be7b5/docs/public/images/screenshot_large_zh.jpg
--------------------------------------------------------------------------------
/docs/public/images/screenshot_mobile.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/markmind/panacea-api/ac40fc5d3657019cbf7ae306d34024dd880be7b5/docs/public/images/screenshot_mobile.jpg
--------------------------------------------------------------------------------
/docs/public/images/screenshot_mobile_zh.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/markmind/panacea-api/ac40fc5d3657019cbf7ae306d34024dd880be7b5/docs/public/images/screenshot_mobile_zh.jpg
--------------------------------------------------------------------------------
/docs/public/images/screenshot_zh.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/markmind/panacea-api/ac40fc5d3657019cbf7ae306d34024dd880be7b5/docs/public/images/screenshot_zh.jpg
--------------------------------------------------------------------------------
/docs/public/images/web_top.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/markmind/panacea-api/ac40fc5d3657019cbf7ae306d34024dd880be7b5/docs/public/images/web_top.png
--------------------------------------------------------------------------------
/docs/public/images/web_top_en.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/markmind/panacea-api/ac40fc5d3657019cbf7ae306d34024dd880be7b5/docs/public/images/web_top_en.png
--------------------------------------------------------------------------------
/docs/status.md:
--------------------------------------------------------------------------------
1 | # Status API
2 |
3 | Status API provides the necessary data for the bot module of the client, currently includes the following APIs
4 |
5 | - init:get all bot initial data
6 | - refresh:get bot update data
7 |
8 | ## Implementation
9 |
10 | > **Required**
11 | > When the server uses websocket communication, `init` will get all the initial data and initialize the client, and websocket will continuously pass `refrsh` data to the client through broadcasting
12 |
13 | ## API List
14 |
15 | ### - init
16 |
17 | Get all current bot init data
18 |
19 | #### Request
20 |
21 | > When user successfully connects to the bot, data will be pushed to client.
22 | > When device reconnection (such as resume event), data will be pushed to client again.
23 |
24 | ```javascript
25 | {
26 | "action": "init",
27 | "apiKey":"YOUR API KEY"
28 | }
29 | ```
30 |
31 | #### Response
32 |
33 | ```javascript
34 | {
35 | "exchange": { //exchange
36 | "name": "sim", //name 'sim' is paper trading
37 | "makerFee": 0.1, //exchange maker fee
38 | "takerFee": 0.1//exchange taker fee
39 | },
40 | "symbols": [ // watch symbols
41 | {
42 | "product_id": "ETH-USDT", //pair name
43 | "price": 1858.08, //pair price
44 | "normalized": "mexc.ETH-USDT",//pair full name
45 | "min_size": "0.00001",//pair min size
46 | "asset": "ETH",
47 | "currency": "USDT",
48 | "assetCaptial": 0,
49 | "leverage": 10,//future leverage
50 | "isolated": false,//future mode
51 | "usdtProfit": 0,//USDT profit
52 | "dynamicProfit": 0,//unrealized USDT profit
53 | "dynamicUsdtProfit": 0,//unrealized USDT profit rate
54 | "profit": 0,//USDT profit reate
55 | "signal": null,//signal include 'buying','selling','bought','sold'
56 | "win": 0,//win count
57 | "lost": 0,//lost count
58 | "winLostRate": 0,//win rate
59 | "trades": [{//pair order list
60 | "order_id": 1001, //order ID
61 | "time": 1681111866476,//order time
62 | "execution_time": 5001,//order execution time
63 | "slippage": 0,//order slippage
64 | "type": "buy",//order position type, buy or sell
65 | "size": "0.10757",//order size
66 | "fee": 0.19980051799999998,//order fee usdt
67 | "price": "1857.40", //order price
68 | "order_type": "maker",//order type 'maker' or 'taker'
69 | "action": "BollingerBands_buy_long",//order buy or send strategy type
70 | "profit": -0.0009999999999999998, //order porfit
71 | "usdtProfit": -0.19980051799999998,//order profit rate
72 | "position_side": "long",//order position side 'long' or 'short'
73 | },
74 | ...
75 | ],
76 | "lastTradeTime": 0,//last trade time
77 | "klines": [//kline data
78 | {
79 | "period_id": "m28018427",
80 | "time": 1681105620000,
81 | "size": "1m",
82 | "close_time": 1681105679999,
83 | "open": 1863.3,
84 | "high": 1863.38,
85 | "low": 1862.22,
86 | "close": 1862.22,
87 | "volume": 45.16688,
88 | "strategy": { //kline data straegy
89 | "BollingerBands_buyCrossCount": 0,//bb buy point count in this period
90 | "BollingerBands_sellCrossCount": 1,//bb sell point count in this period
91 | "BollingerBands_buy": false,//if bb has buy point
92 | "BollingerBands_sell": false//if bb has sell point
93 | }
94 | },
95 | ...
96 | ]
97 | },
98 | ...
99 | ],
100 | "status": { //bot status
101 | "hasConfig": true,//if has config module
102 | "hasStrategy": true,//if has strategy module
103 | "hasMarket": true,//if has market module
104 | "hasBacktest": true,//if has backtest module
105 | "tradeListLen": 1,//watch pair length
106 | "startCapital": 1000,//start capital
107 | "currentCapital": 800.10957177,//current useful capital
108 | "tradeNum": 12,//traded pair number
109 | "dynamicUsdtProfit": -0.0290142,//unrealized profit
110 | "dynamicProfit": -0.0000290142,//unrealized profit rate
111 | "usdtProfit": -0.19980051799999998,//USDT profit
112 | "profit": -0.000199800518,//profit rate
113 | "exchange": "mexc",//bot exchange
114 | "startTime": 1681111671975,//bot start time
115 | "timeZoneOffset": -480,//server timezone offset
116 | "status": "work",//current bot status
117 | "win": 4,
118 | "lost": 1,
119 | "winLostRate": 0.8,
120 | "totalCapital":999.32 //current capital,include profit and unrealized profit
121 | }
122 | }
123 | ```
124 |
125 | ### - refresh
126 |
127 | Get current bot update data
128 |
129 | > The server regularly broadcasts real-time data to the client
130 | > Broadcast data to the client when a specific event occurs, such as new order is created
131 |
132 | #### Request
133 |
134 | ```javascript
135 | {
136 | "action": "refresh",
137 | "apiKey": "YOUR API KEY"
138 | }
139 | ```
140 |
141 | #### Response
142 |
143 | ```javascript
144 | {
145 | "action": "refresh",
146 | "data": {
147 | "symbols": [ //all pairs
148 | {
149 | "product_id": "ETH-USDT", //pair name
150 | "price": 1858.08, //pair price
151 | "normalized": "mexc.ETH-USDT",//pair full name
152 | "min_size": "0.00001",//pair min size
153 | "asset": "ETH",
154 | "currency": "USDT",
155 | "assetCaptial": 0,
156 | "leverage": 10,// future leverage
157 | "isolated": false,//future mode
158 | "usdtProfit": 0,//USDT profit
159 | "dynamicProfit": 0,//unrealized USDT profit
160 | "dynamicUsdtProfit": 0,//unrealized USDT profit rate
161 | "profit": 0,//USDT USDT profit rate
162 | "signal": null,//signal include 'buying','selling','bought','sold'
163 | "win": 0,//win count
164 | "lost": 0,//lost count
165 | "winLostRate": 0,//win rate
166 | "trades": [{// pair order list
167 | "order_id": 1001, //order ID
168 | "time": 1681111866476,//order time
169 | "execution_time": 5001,//order execution time
170 | "slippage": 0,//order slippage
171 | "type": "buy",//order position type, buy or sell
172 | "size": "0.10757",//order size
173 | "fee": 0.19980051799999998,//order fee usdt
174 | "price": "1857.40", //order price
175 | "order_type": "maker",//order type 'maker' or 'taker'
176 | "action": "BollingerBands_buy_long",//order buy or send strategy type
177 | "profit": -0.0009999999999999998, //order porfit
178 | "usdtProfit": -0.19980051799999998,//order profit rate
179 | "position_side": "long",//order position side 'long' or 'short'
180 | },
181 | ...
182 | ],
183 | "lastTradeTime": 0,//last trade time
184 | "klines": [//Kline data
185 | {
186 | "period_id": "m28018427",
187 | "time": 1681105620000,
188 | "size": "1m",
189 | "close_time": 1681105679999,
190 | "open": 1863.3,
191 | "high": 1863.38,
192 | "low": 1862.22,
193 | "close": 1862.22,
194 | "volume": 45.16688,
195 | "strategy": { //kline data for strategy
196 | "BollingerBands_buyCrossCount": 0,//bb buy point count in this period
197 | "BollingerBands_sellCrossCount": 1,//bb sell point count in this period
198 | "BollingerBands_buy": false,//if bb has buy point
199 | "BollingerBands_sell": false//if bb has sell point
200 | "middle": 1856.3892857142853,//bb middle
201 | "upper": 1858.8566899522384,//bb uper
202 | "lower": 1853.9218814763321,//bb lower
203 | "pw": 0.26582832134842305,//bb pw
204 | }
205 | }
206 | ...
207 | ]
208 | },
209 | ...
210 | ],
211 | "status": { //bot status
212 | "tradeListLen": 1,//watch pair length
213 | "startCapital": 1000,//start capital
214 | "currentCapital": 800.10957177,//current useful capital
215 | "tradeNum": 12,//traded pair number
216 | "dynamicUsdtProfit": -0.0290142,//unrealized profit
217 | "dynamicProfit": -0.0000290142,//unrealized profit rate
218 | "usdtProfit": -0.19980051799999998,//USDT profit
219 | "profit": -0.000199800518,//profit rate
220 | "exchange": "mexc",//bot exchange
221 | "startTime": 1681111671975,//bot start time
222 | "timeZoneOffset": -480,//server timezone offset
223 | "status": "work",//current bot status
224 | "win": 4,
225 | "lost": 1,
226 | "winLostRate": 0.8,
227 | "totalCapital":999.32 //current capital,include profit and unrealized profit
228 | }
229 | }
230 | }
231 | ```
232 |
--------------------------------------------------------------------------------
/docs/zh/README.md:
--------------------------------------------------------------------------------
1 | # 用户文档
2 |
3 | **简介:**
4 |
5 | - [关于灵丹](panacea.md)
6 | - [开发者](developer.md)
7 | - [常见问题](faq.md)
8 |
9 | **API:**
10 |
11 | - [状态](status.md)
12 | - [操作](operation.md)
13 | - [配置](config.md)
14 | - [策略](strategy.md)
15 | - [行情](market.md)
16 |
--------------------------------------------------------------------------------
/docs/zh/config.md:
--------------------------------------------------------------------------------
1 | # 配置API
2 |
3 | 配置API为客户端的配置模块提供必要数据,通过配置模块,您在服务器的所有配置均可通过客户端进行实时更新。目前包括以下API
4 |
5 | - init 获得配置设置与配置值
6 | - updateConfig 更新配置
7 | - updateSymbolFuture 更新交易对配置
8 |
9 | ## 必需实现
10 |
11 | > **可选**
12 | > 如果不实现此API,客户端将不会有配置模块.
13 | > 如果未实现此API,在状态API请将机器人状态的`init`中请将`hasConfig`设置为`false`
14 |
15 | ## 更新流程
16 |
17 | - 在`init`事件中传递配置设置与配置值
18 | - 通过配置设置在客户端生成相关联的UI界面
19 | - 通过UI界面修改配置并通过`updateConfig`更新服务器端值
20 |
21 | ## API列表
22 |
23 | ### - init
24 |
25 | 当使用配置模块时,配置设置与配置参数将通过`init`传递至客户端
26 |
27 | #### 请求参数
28 |
29 | > 用户初次连接机器人成功时,服务器将主动推送。
30 | > 用户设备重新连接(比如浏览器移动设备resume事件)也会主动推送
31 |
32 | ```javascript
33 | {
34 | "action": "init",
35 | "apiKey":"YOUR API KEY"
36 | }
37 | ```
38 |
39 | #### 返回结果
40 |
41 | ```javascript
42 | {
43 | "options": { //机器人配置 ,用户提交config并在此处传入实时值,详见 config组
44 | "strategy": "BollingerBands",
45 | "period": "10m",
46 | "debug": false
47 | ...
48 | },
49 | "config": { //机器人配置设置,结构为分组,小分组,条目 ,可查看XCoin相关配置
50 | "bot": [//机器人相关配置分组,以下例子使用了不同种类的
51 | {
52 | "name": "strategy",//配置名称 比如策略名称
53 | "type": "string",//字符类型
54 | "value": "BollingerBands"//配置值
55 | },
56 | {
57 | "name": "period",//配置名称,比如周期选择
58 | "type": "array",//列表类型
59 | "list": [//列表值
60 | "1m",
61 | "3m",
62 | "5m"
63 | ],
64 | "value": "5m"
65 | },
66 | {
67 | "name": "debug",//配置名称,比如是否调试
68 | "type": "bool",//布尔类型
69 | "value": false
70 | },
71 | {
72 | "name": "other",//分组名称,比如其它
73 | "type": "group"//分组类型,分组类型下的所有设置将在分组中显示
74 | },
75 | {
76 | "name": "poll_scan_time",//配置名称,比如轮循时间
77 | "type": "number",//数值类型
78 | "step": [//通过step设置
79 | 1000,//最小值
80 | 60000,//最大值
81 | 500//步长
82 | ],
83 | "value": 3000,
84 | "des": true//存在描述
85 | },
86 | {
87 | "name": "black_list",//配置名称,比如黑名单列
88 | "type": "textarea",//长字符串类型
89 | "value": 'binance.BTC-USDT,binance.AAB-USDt', //配置值
90 | "des": true//存在描述
91 | },
92 | ...
93 | ],
94 | "exchange": [], //交易所相关,
95 | "order": [], //订单相关,
96 | "sellPoint": [], //止赢止损相关相关,
97 | "watch": [], //监控池相关
98 | "paper":[],//模拟交易相关
99 | }
100 | }
101 | ```
102 |
103 | ### - updateConfig
104 |
105 | 更新机器人参数
106 |
107 | #### 请求参数
108 |
109 | ```javascript
110 | {
111 | "action": "updateConfig",
112 | "restart": true, //本次更新需要重启机器人
113 | "data": {
114 | "period": "3m", //更新的参数
115 | "buy_pct":30 //更新的参数
116 | },
117 | "apiKey": "YOUR API KEY"
118 | }
119 | ```
120 |
121 | #### 返回结果
122 |
123 | ```javascript
124 | {
125 | "action": "updateConfig",
126 | "data":Object, //返回全部配置参数 方便更
127 | "toast": "trade.updateConfigOk"
128 | }
129 | ```
130 |
131 | ### - updateSymbolFuture
132 |
133 | 更新指定交易对的期货参数,目前支持杠杆倍数与全仓逐仓模式的更新
134 |
135 | #### 请求参数
136 |
137 | ```javascript
138 | {
139 | "action": "updateSymbolFuture",
140 | "symbol":"BTC-USDT", //交易对
141 | "data":{
142 | "type":"leverage",//marginMode or leverage
143 | "value":10 //type为marginMode时,值为 cross或isolated
144 | },
145 | "apiKey": "YOUR API KEY"
146 | }
147 | ```
148 |
149 | #### 返回结果
150 |
151 | ```javascript
152 | {
153 | "action": "updateSymbolFuture",
154 | "toast": "trade.updateSymbolFutureOk"
155 | }
156 | ```
157 |
158 | > 一个示例的配置设置文件
159 |
160 | ````json
161 | {
162 | "bot": [
163 | {
164 | "name": "strategy",
165 | "type": "string",
166 | "value": "rain_sar"
167 | },
168 | {
169 | "name": "period",
170 | "type": "array",
171 | "list": [
172 | "1m",
173 | "3m",
174 | "5m",
175 | "15m",
176 | "30m",
177 | "1h",
178 | "2h",
179 | "4h",
180 | "8h",
181 | "12h",
182 | "1d",
183 | "3d",
184 | "1w"
185 | ],
186 | "value": "30m"
187 | },
188 | {
189 | "name": "mode",
190 | "type": "array",
191 | "list": [
192 | "live",
193 | "paper"
194 | ],
195 | "value": "live"
196 | },
197 | {
198 | "name": "trade_type",
199 | "type": "array",
200 | "list": [
201 | "auto",
202 | "autoBuy",
203 | "autoSell",
204 | "manual"
205 | ],
206 | "value": "live"
207 | },
208 | {
209 | "name": "debug",
210 | "type": "bool",
211 | "value": false
212 | },
213 | {
214 | "name": "other",
215 | "type": "group"
216 | },
217 | {
218 | "name": "poll_scan_time",
219 | "type": "number",
220 | "step": [
221 | 1000,
222 | 60000,
223 | 500
224 | ],
225 | "value": 3000,
226 | "des": true
227 | },
228 | {
229 | "name": "poll_broadcast_time",
230 | "type": "number",
231 | "step": [
232 | 3000,
233 | 60000,
234 | 1000
235 | ],
236 | "value": 5000,
237 | "des": true
238 | },
239 | {
240 | "name": "save_bot_time",
241 | "type": "number",
242 | "step": [
243 | 6000,
244 | 6000000,
245 | 6000
246 | ],
247 | "value": 600000,
248 | "des": true
249 | },
250 | {
251 | "name": "min_periods",
252 | "type": "number",
253 | "step": [
254 | 18,
255 | 500,
256 | 1
257 | ],
258 | "value": 32
259 | },
260 | {
261 | "name": "keep_lookback_periods",
262 | "type": "number",
263 | "step": [
264 | 50,
265 | 50000,
266 | 10
267 | ],
268 | "value": 500
269 | },
270 | {
271 | "name": "price_format",
272 | "type": "string",
273 | "value": "0.00000000"
274 | },
275 | {
276 | "name": "same_period_multi_buy",
277 | "type": "bool",
278 | "value": false
279 | },
280 | {
281 | "name": "run_for",
282 | "type": "number",
283 | "step": [
284 | 0,
285 | 1000,
286 | 1
287 | ],
288 | "value": 0,
289 | "des": true
290 | }
291 | ],
292 | "exchange": [
293 | {
294 | "name": "exchange",
295 | "type": "array",
296 | "list": [
297 | "binanceusdm",
298 | "binance",
299 | "mexc"
300 | ],
301 | "value": "binanceusdm"
302 | },
303 | {
304 | "name": "takerFee",
305 | "type": "number",
306 | "step": [
307 | 0.001,
308 | 0.5,
309 | 0.001
310 | ],
311 | "value": 0.1
312 | },
313 | {
314 | "name": "makerFee",
315 | "type": "number",
316 | "step": [
317 | 0.001,
318 | 0.5,
319 | 0.001
320 | ],
321 | "value": 0.1
322 | },
323 | {
324 | "name": "future",
325 | "type": "group"
326 | },
327 | {
328 | "name": "future",
329 | "type": "bool",
330 | "value": false,
331 | "readonly": true
332 | },
333 | {
334 | "name": "market",
335 | "type": "array",
336 | "list": [
337 | "only_long",
338 | "only_short",
339 | "both"
340 | ],
341 | "value": "only_long"
342 | },
343 | {
344 | "name": "leverage",
345 | "type": "number",
346 | "step": [
347 | 2,
348 | 125,
349 | 1
350 | ],
351 | "value": 10
352 | },
353 | {
354 | "name": "marginMode",
355 | "type": "array",
356 | "list": [
357 | "cross",
358 | "isolated"
359 | ],
360 | "value": "isolated"
361 | },
362 | {
363 | "name": "short_buy_pct",
364 | "type": "number",
365 | "step": [
366 | 0,
367 | 100,
368 | 1
369 | ],
370 | "value": 20
371 | },
372 | {
373 | "name": "buy_position_side_when_sell",
374 | "type": "bool",
375 | "value": false
376 | }
377 | ],
378 | "order": [
379 | {
380 | "name": "order_type",
381 | "type": "array",
382 | "list": [
383 | "maker",
384 | "taker"
385 | ],
386 | "value": "maker"
387 | },
388 | {
389 | "name": "max_slippage_pct",
390 | "type": "number",
391 | "step": [
392 | 0.1,
393 | 2,
394 | 0.1
395 | ],
396 | "value": 0.5,
397 | "group": "core"
398 | },
399 | {
400 | "name": "buy",
401 | "type": "group"
402 | },
403 | {
404 | "name": "buy_pct",
405 | "type": "number",
406 | "step": [
407 | 0,
408 | 100,
409 | 1
410 | ],
411 | "value": 20
412 | },
413 | {
414 | "name": "min_buy_size",
415 | "type": "number",
416 | "step": [
417 | 0,
418 | 100,
419 | 1
420 | ],
421 | "value": 10
422 | },
423 | {
424 | "name": "max_buy_size",
425 | "type": "number",
426 | "step": [
427 | 0,
428 | 10000,
429 | 100
430 | ],
431 | "value": 0
432 | },
433 | {
434 | "name": "sell",
435 | "type": "group"
436 | },
437 | {
438 | "name": "sell_pct",
439 | "type": "number",
440 | "step": [
441 | 0,
442 | 100,
443 | 1
444 | ],
445 | "value": 100,
446 | "group": "sell"
447 | },
448 | {
449 | "name": "other",
450 | "type": "group"
451 | },
452 | {
453 | "name": "order_adjust_time",
454 | "type": "number",
455 | "step": [
456 | 1000,
457 | 1000,
458 | 1000
459 | ],
460 | "value": 5000,
461 | "group": "other"
462 | },
463 | {
464 | "name": "max_sell_loss_pct",
465 | "type": "number",
466 | "step": [
467 | 0,
468 | 5,
469 | 0.5
470 | ],
471 | "value": 1,
472 | "group": "other"
473 | },
474 | {
475 | "name": "max_buy_loss_pct",
476 | "type": "number",
477 | "step": [
478 | 0,
479 | 5,
480 | 0.5
481 | ],
482 | "value": 1,
483 | "group": "other"
484 | },
485 | {
486 | "name": "order_poll_time",
487 | "type": "number",
488 | "step": [
489 | 1000,
490 | 60000,
491 | 1000
492 | ],
493 | "value": 5000,
494 | "group": "other"
495 | },
496 | {
497 | "name": "wait_for_settlement",
498 | "type": "number",
499 | "step": [
500 | 1000,
501 | 60000,
502 | 1000
503 | ],
504 | "value": 5000,
505 | "group": "other",
506 | "des": true
507 | },
508 | {
509 | "name": "markdown_buy_pct",
510 | "type": "number",
511 | "step": [
512 | 0,
513 | 5,
514 | 0.1
515 | ],
516 | "value": 0,
517 | "group": "other"
518 | },
519 | {
520 | "name": "markup_sell_pct",
521 | "type": "number",
522 | "step": [
523 | 0,
524 | 5,
525 | 0.1
526 | ],
527 | "value": 0,
528 | "group": "other"
529 | },
530 | {
531 | "name": "post_only",
532 | "type": "bool",
533 | "value": false,
534 | "group": "other"
535 | },
536 | {
537 | "name": "use_fee_asset",
538 | "type": "bool",
539 | "value": false,
540 | "group": "other"
541 | },
542 | {
543 | "name": "avg_slippage_pct",
544 | "type": "number",
545 | "value": 0.045,
546 | "step": [
547 | 0,
548 | 0.1,
549 | 0.005
550 | ],
551 | "group": "other"
552 | },
553 | {
554 | "name": "quarentine_time",
555 | "type": "number",
556 | "step": [
557 | 0,
558 | 100000,
559 | 1000
560 | ],
561 | "value": 0,
562 | "group": "other"
563 | }
564 | ],
565 | "sellPoint": [
566 | {
567 | "name": "sell_stop_pct",
568 | "type": "number",
569 | "step": [
570 | 0,
571 | 30,
572 | 0.1
573 | ],
574 | "value": 5
575 | },
576 | {
577 | "name": "profitStop",
578 | "type": "group"
579 | },
580 | {
581 | "name": "profit_stop_enable",
582 | "type": "bool",
583 | "value": true
584 | },
585 | {
586 | "name": "profit_stop_percent",
587 | "type": "number",
588 | "step": [
589 | 0,
590 | 100,
591 | 1
592 | ],
593 | "value": 50
594 | },
595 | {
596 | "name": "profit_stop_first_rate",
597 | "type": "number",
598 | "step": [
599 | 0,
600 | 500,
601 | 1
602 | ],
603 | "value": 10
604 | },
605 | {
606 | "name": "profit_stop_first_percent",
607 | "type": "number",
608 | "step": [
609 | 0,
610 | 100,
611 | 1
612 | ],
613 | "value": 30
614 | },
615 | {
616 | "name": "profit_stop_second_rate",
617 | "type": "number",
618 | "step": [
619 | 0,
620 | 500,
621 | 1
622 | ],
623 | "value": 20
624 | },
625 | {
626 | "name": "profit_stop_second_percent",
627 | "type": "number",
628 | "step": [
629 | 0,
630 | 100,
631 | 1
632 | ],
633 | "value": 40
634 | },
635 | {
636 | "name": "profit_stop_third_rate",
637 | "type": "number",
638 | "step": [
639 | 0,
640 | 500,
641 | 1
642 | ],
643 | "value": 50
644 | },
645 | {
646 | "name": "profit_stop_third_percent",
647 | "type": "number",
648 | "step": [
649 | 0,
650 | 100,
651 | 1
652 | ],
653 | "value": 50
654 | },
655 | {
656 | "name": "profit_stop_max_rate",
657 | "type": "number",
658 | "step": [
659 | 0,
660 | 500,
661 | 1
662 | ],
663 | "value": 100
664 | },
665 | {
666 | "name": "profit_stop_max_percent",
667 | "type": "number",
668 | "step": [
669 | 0,
670 | 100,
671 | 1
672 | ],
673 | "value": 70
674 | },
675 | {
676 | "name": "profitSell",
677 | "type": "group"
678 | },
679 | {
680 | "name": "profit_win_enable",
681 | "type": "bool",
682 | "value": true
683 | },
684 | {
685 | "name": "profit_win_first_rate",
686 | "type": "number",
687 | "step": [
688 | 0,
689 | 500,
690 | 1
691 | ],
692 | "value": 25
693 | },
694 | {
695 | "name": "profit_win_first_percent",
696 | "type": "number",
697 | "step": [
698 | 0,
699 | 100,
700 | 1
701 | ],
702 | "value": 50
703 | },
704 | {
705 | "name": "profit_win_second_rate",
706 | "type": "number",
707 | "step": [
708 | 0,
709 | 500,
710 | 1
711 | ],
712 | "value": 50
713 | },
714 | {
715 | "name": "profit_win_second_percent",
716 | "type": "number",
717 | "step": [
718 | 0,
719 | 100,
720 | 1
721 | ],
722 | "value": 50
723 | },
724 | {
725 | "name": "profit_win_third_rate",
726 | "type": "number",
727 | "step": [
728 | 0,
729 | 500,
730 | 1
731 | ],
732 | "value": 100
733 | },
734 | {
735 | "name": "profit_win_third_percent",
736 | "type": "number",
737 | "step": [
738 | 0,
739 | 100,
740 | 1
741 | ],
742 | "value": 50
743 | },
744 | {
745 | "name": "profit_win_max_rate",
746 | "type": "number",
747 | "step": [
748 | 0,
749 | 500,
750 | 1
751 | ],
752 | "value": 200
753 | },
754 | {
755 | "name": "profit_win_max_percent",
756 | "type": "number",
757 | "step": [
758 | 0,
759 | 100,
760 | 1
761 | ],
762 | "value": 50
763 | }
764 | ],
765 | "watch": [
766 | {
767 | "name": "max_watch_size",
768 | "type": "number",
769 | "step": [
770 | 0,
771 | 30,
772 | 5
773 | ],
774 | "value": 10
775 | },
776 | {
777 | "name": "watch_symbols",
778 | "type": "textarea",
779 | "value": "",
780 | "placeholder": true
781 | },
782 | {
783 | "name": "watchInit",
784 | "type": "group"
785 | },
786 | {
787 | "name": "watch_include_bought",
788 | "type": "bool",
789 | "value": true
790 | },
791 | {
792 | "name": "watch_with_black_list",
793 | "type": "bool",
794 | "value": true
795 | },
796 | {
797 | "name": "black_list",
798 | "type": "textarea",
799 | "value": "",
800 | "placeholder": true
801 | }
802 | ],
803 | "paper": [
804 | {
805 | "name": "currency_capital",
806 | "type": "number",
807 | "step": [
808 | 0,
809 | 10000,
810 | 1000
811 | ],
812 | "value": 1000
813 | },
814 | {
815 | "name": "asset_capital",
816 | "type": "number",
817 | "step": [
818 | 0,
819 | 10000,
820 | 1000
821 | ],
822 | "value": 0
823 | }
824 | ]
825 | }
826 | ````
827 |
--------------------------------------------------------------------------------
/docs/zh/developer.md:
--------------------------------------------------------------------------------
1 | # 开发者
2 |
3 | 灵丹为交易机器人提供一个统一的易管理的实时反映交易状态的界面,您可以通过开发扩展来适应您自己的机器人,我们也欢迎您添加基于Freqtrade,zenbot等的功能扩展
4 |
5 | ## 扩展开发流程
6 |
7 | 1. 了解灵丹API并决定您需要适配哪些API
8 | 2. 在您的机器人代码里添加基于灵丹的扩展
9 | 3. 下载灵丹应用程序 [下载灵丹](https://www.ciiat.com/download),添加您的交易机器人进行测试
10 | 4. 您也可以直接通过 [Web版灵丹](https://www.ciiat.com/app/www) 直接添加您的交易机器人进行测试
11 | 5. 下载灵丹API代码,将您的相关代码放置在 `extensions` 目录
12 | 6. 提交一个PR,我们会尽快进行合并
13 |
14 | ## 注意事项
15 |
16 | - 添加代码时需要在根目录添加README.md文件以帮助用户了解使用扩展的细节
17 | - 所有扩展均需要遵循 `MIT` 授权
18 | - 您可以随时通过运行 [XCoin](https://github.com/rianfu/xcoin) 来对比扩展传递内容.
19 |
--------------------------------------------------------------------------------
/docs/zh/faq.md:
--------------------------------------------------------------------------------
1 | # 常见问题
2 |
3 | 以下是一些经常被问到的问题以及来自社区的回答。
4 |
5 | 如果您有此处未回答的问题,请随时在社区中提问,并建议将其放在此处。
6 |
7 | 谢谢!
8 |
9 | ## 问题
10 |
11 | ### [开发](#开发)
12 |
13 | ## 答案
14 |
15 | ### 开发
16 |
--------------------------------------------------------------------------------
/docs/zh/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: home
3 |
4 | hero:
5 | name: 灵丹
6 | text: 交易机器人实时状态管理
7 | tagline: 随时随地管理您的交易机器人。
8 | image:
9 | src: /images/web_top.png
10 | alt: 灵丹
11 |
12 | actions:
13 | - theme: brand
14 | text: 快速开始
15 | link: /zh/panacea
16 | - theme: sponsor
17 | text: 演示
18 | link: https://www.ciiat.com/app/www
19 | - theme: sponsor
20 | text: 下载
21 | link: https://www.ciiat.com/download
22 | - theme: alt
23 | text: 在 GitHub 上查看
24 | link: https://github.com/markmind/panacea-api
25 |
26 | features:
27 | - title: 提供统一API
28 | details: 支持多种开源交易机器人或商业闭源机器人。
29 | - title: 支持所有客户端
30 | details: 任意时间,任意地点通过桌面或移动设备管理您的交易。
31 | - title: 多机器人管理
32 | details: 支持管理多个机器人,一键切换。
33 | - title: 支持实时交易
34 | details: 支持多空操作,支持买卖点显示。
35 | - title: 支持配置参数实时修改
36 | details: 支持在运行时更改参数,支持远程启停以应用参数。
37 | - title: 支持策略参数实时修改
38 | details: 支持在运行时更改策略或调整策略参数,支持远程启停以策略。
39 | ---
--------------------------------------------------------------------------------
/docs/zh/market.md:
--------------------------------------------------------------------------------
1 | # 市场API
2 |
3 | 市场API为客户端的市场模块提供必要数据,目前包括以下API
4 |
5 | - getProducts 获得产品列表
6 | - getTickers 获得产品价格
7 | - getKlines 获得特定交易对的K线
8 | - getPickerNormal 获得热门产品
9 |
10 | ## 必需实现
11 |
12 | > **可选**
13 | > 如果不实现此API,客户端将不会有市场模块
14 | > 如果未实现此API,在状态API请将机器人状态的`init`中请将`hasMarket`设置为`false`
15 |
16 | ## API列表
17 |
18 | ### - getProducts
19 |
20 | 获取当前机器人所在交易所的所有产品
21 |
22 | #### 请求参数
23 |
24 | ```javascript
25 | {
26 | "action": "getProducts",
27 | "apiKey":"YOUR API KEY"
28 | }
29 | ```
30 |
31 | #### 返回结果
32 |
33 | ```javascript
34 | {
35 | "action": "getProducts",
36 | "data":[{
37 | "id": "1INCH_USDT", //交易对
38 | "asset": "1INCH",//asset
39 | "currency": "USDT",//currency
40 | "active": true,
41 | "min_size": "0.01",//最小交易对单位
42 | "increment": "0.0001",//最小价格单位
43 | "asset_increment": "0.01",//最小交易对增量
44 | "label": "1INCH/USDT",
45 | "exchagne_id": "mexc",
46 | "product_id": "1INCH-USDT",
47 | "normalized": "mexc.1INCH-USDT"
48 | },
49 | ...
50 | ]
51 | }
52 | ```
53 |
54 | ### - getTickers
55 |
56 | 获取当前机器人所在交易所的所有或指定产品的实时价格,
57 |
58 | > 不传symbols参数时将返回所有产品的价格
59 |
60 | #### 请求参数
61 |
62 | ```javascript
63 | {
64 | "action": "getTickers",
65 | "data": {
66 | "symbols": [
67 | {
68 | "product_id": "1INCH-USDT" //交易对名称
69 | },
70 | ...
71 | ]
72 | },
73 | "apiKey": "YOUR API KEY"
74 | }
75 | ```
76 |
77 | #### 返回结果
78 |
79 | ```javascript
80 | {
81 | "action": "getTickers",
82 | "data": [
83 | {
84 | "symbol": "GDO/USDT",//交易对名称
85 | "price": 8.98e-8, //当前价格
86 | "percentage": 1 //24hr价格变化率
87 | }
88 | ...
89 | ]
90 | }
91 | ```
92 |
93 | ### - getPickerNormal
94 |
95 | 获取当前机器人所在交易所的热门产品
96 |
97 | > 目前支持的热门产品为指定周期内的最大涨幅,最大,最小振幅,连续上涨与阳线最多5个部分
98 |
99 | #### 请求参数
100 |
101 | ```javascript
102 | {
103 | "action": "getPickerNormal",
104 | "data": {
105 | "period": "1d", //K线周期
106 | "limit": 10,// 返回结果数量
107 | "number": 8 // K线长度
108 | },
109 | "apiKey": "YOUR API KEY"
110 | }
111 | ```
112 |
113 | #### 返回结果
114 |
115 | ```javascript
116 | {
117 | "action": "getPickerNormal",
118 | "data": {
119 | "maxSum": [//最大振幅
120 | {
121 | "index": 1, //排名
122 | "product_id": "ARB-USDT",
123 | "price": 1.3181,
124 | "extra": "12400.37%", //总振幅
125 | "klines": [
126 | {
127 | "time": 1679529600000,
128 | "close": 1.3181
129 | }
130 | ...
131 | ]
132 | }
133 | ...
134 | ],
135 | "minSum": [//最小振幅
136 | {
137 | "index": 1,//排名
138 | "product_id": "BUSD-USDT",
139 | "price": 0.9982,
140 | "extra": "2.04%", //总振幅
141 | "klines": [
142 | {
143 | "time": 1678752000000,
144 | "close": 0.9965
145 | },
146 | ...
147 | ]
148 | },
149 | ...
150 | ],
151 | "fastUp": [//最大涨幅
152 | {
153 | "index": 1,//排名
154 | "product_id": "ID-USDT",
155 | "price": 0.5285,
156 | "extra": "2014.00%",//总涨幅
157 | "klines": [
158 | {
159 | "time": 1679443200000,
160 | "close": 0.40696
161 | },
162 | ...
163 | ]
164 | },
165 | ...
166 | ],
167 | "moreUp": [//最多阳线
168 | {
169 | "index": 1,// 排名
170 | "product_id": "LOOP-USDT",
171 | "price": 0.12923,
172 | "extra": "9/10",// 阳线数量
173 | "klines": [
174 | {
175 | "time": 1679529600000,
176 | "close": 0.12923
177 | },
178 | ...
179 | ]
180 | },
181 | ...
182 | ],
183 | "continueUp": [//连续涨
184 | {
185 | "index": 1, //排名
186 | "product_id": "LOOP-USDT",
187 | "price": 0.12923,
188 | "extra": 9, //连续涨数量
189 | "klines": [
190 | {
191 | "time": 1678752000000,
192 | "close": 0.03596
193 | },
194 | ...
195 | ],
196 | ...
197 | }
198 | ]
199 | }
200 | }
201 | ```
202 |
203 | ### getKlines
204 |
205 | 获取当前机器人所在交易所的某一产品的K线图
206 |
207 | #### 请求参数
208 |
209 | ```javascript
210 | {
211 | "action": "getKlines",
212 | "symbol": "ALGO-USDT", //交易对名称
213 | "data": {
214 | "product_id": "ALGO-USDT",
215 | "limit": 60, //K线长度
216 | "period": "30m" //K线周期
217 | },
218 | "apiKey": "YOUR API KEY"
219 | }
220 | ```
221 |
222 | #### 返回结果
223 |
224 | ```javascript
225 | {
226 | "action": "getKlines",
227 | "data": {
228 | "period": "30m", //K线周期
229 | "klines": [
230 | {
231 | "period_id": "30m933888",//kline id
232 | "time": 1680768000,//K线开始时间
233 | "size": "30m",//K线周期
234 | "close_time": 1681000199999,//k线结束时间
235 | "open": 0.216,
236 | "high": 0.2169,
237 | "low": 0.2157,
238 | "close": 0.2169,
239 | "volume": 12943.41
240 | }
241 | ...
242 | ]
243 | }
244 | }
245 | ```
246 |
--------------------------------------------------------------------------------
/docs/zh/operation.md:
--------------------------------------------------------------------------------
1 | # 操作API
2 |
3 | 操作API为客户端的机器人模块提供与服务器的交互,根据功能的不同可分为几个类型
4 |
5 | - 对监控池的交易对的操作
6 | - 添加新交易对
7 | - 删除交易对
8 | - 清空交易池
9 | - 特定交易对的交易
10 | - 买
11 | - 卖
12 | - 清仓
13 |
14 | ## 必需实现
15 |
16 | > **必选**
17 |
18 | ## API列表
19 |
20 | ### - addSymbol
21 |
22 | 将新的交易对添加至交易池
23 |
24 | #### 请求参数
25 |
26 | ```javascript
27 | {
28 | "action": "addSymbol",
29 | "symbols": [
30 | "mexc.ACM-USDT" //添加的交易对数组
31 | ],
32 | "data": {},
33 | "apiKYOUR API KEYJYOyKq"
34 | }
35 | ```
36 |
37 | #### 返回结果
38 |
39 | ```javascript
40 | {
41 | "action": "addSymbol",
42 | "toast": "trade.addSymbolOk",//成功后消息提醒信息
43 | "data": {
44 | "success": true
45 | }
46 | }
47 | ```
48 |
49 | ### - removeSymbol
50 |
51 | 将指定交晚对从监控池移除,
52 |
53 | #### 请求参数
54 |
55 | ```javascript
56 | {
57 | "action": "removeSymbol",
58 | "symbol": "mexc.ETH-USDT", //清除交易对名称
59 | "apiKey": "YOUR API KEY"
60 | }
61 | ```
62 |
63 | #### 返回结果
64 |
65 | ```javascript
66 | {
67 | "action": "removeSymbol",
68 | "toast": "trade.removeSymbolOk",
69 | "data": {
70 | "success": true
71 | }
72 | }
73 | ```
74 |
75 | ### - removeAllSymbol
76 |
77 | 清空交易池中的交易对
78 |
79 | #### 请求参数
80 |
81 | ```javascript
82 | {
83 | "action": "removeAllSymbol",
84 | "apiKey": "YOUR API KEY"
85 | }
86 | ```
87 |
88 | #### 返回结果
89 |
90 | ```javascript
91 | {
92 | "action": "removeAllSymbol",
93 | "toast": "trade.removeAllSymbolOk"
94 | }
95 | ```
96 |
97 | ### buy
98 |
99 | 购买指定交易对
100 |
101 | #### 请求参数
102 |
103 | ```javascript
104 | {
105 | "action": "buy",
106 | "symbol": "BTC-USDT",
107 | "data": {
108 | "position_side": "LONG", //LONG 买多 OR SHORT 买空
109 | "size":20//买入数量
110 | },
111 | "apiKey": "YOUR API KEY"
112 | }
113 | ```
114 |
115 | #### 返回结果
116 |
117 | ```javascript
118 | {
119 | "action": "buy",
120 | "toast": "trade.buyOk" //返回消息提醒
121 | }
122 | ```
123 |
124 | ### -Sell
125 |
126 | 卖出指定交易对
127 |
128 | #### 请求参数
129 |
130 | ```javascript
131 | {
132 | "action": "sell",
133 | "symbol": "BTC-USDT",
134 | "data": {
135 | "position_side": "LONG", //LONG 卖多 OR SHORT 卖空
136 | "size":20//卖出数量
137 | },
138 | "apiKey": "YOUR API KEY"
139 | }
140 | ```
141 |
142 | #### 返回结果
143 |
144 | ```javascript
145 | {
146 | "action": "sell",
147 | "toast": "trade.sellOk" //返回消息提醒
148 | }
149 | ```
150 |
151 | ### - sellAll
152 |
153 | 卖出所有交易对
154 |
155 | #### 请求参数
156 |
157 | ```javascript
158 | {
159 | "action": "sellAll",
160 | "apiKey": "YOUR API KEY"
161 | }
162 | ```
163 |
164 | #### 返回结果
165 |
166 | ```javascript
167 | {
168 | "action": "sellAll",
169 | "toast": "trade.sellAllOk" //返回消息提醒
170 | }
171 | ```
172 |
--------------------------------------------------------------------------------
/docs/zh/panacea.md:
--------------------------------------------------------------------------------
1 | # 关于灵丹
2 |
3 | 灵丹通过一个简易的方法来扩展您的交易机器人的功能,让您可以通过桌面或移动设备在任何时间、任何地点都能操控与观察您的机器人,通过对状态、交互、配置、策略等的合理配置,您能更快速更合理地找出理想的交易方式,极大地减小了量化交易的风险,提升了交易的赢利能力。
4 |
5 | 在将你的交易机器人适配至灵丹之前,您需要了解一些我们的工作方式。
6 |
7 | ## 屏幕截图
8 |
9 | ### 桌面版
10 |
11 | 包括 Windows,Osx and Linux 客户端
12 |
13 | 
14 |
15 | ### 移动版
16 |
17 | 包括 Android and Ios 客户端
18 |
19 | 
20 |
21 | ## 页面架构
22 |
23 | 根据您实现API的内容,灵丹将显示不同的页面内容
24 |
25 | >状态与操作API是必需实现的灵丹的核心功能
26 | >如果您未实现配置功能,灵丹配置管理模块将不会被启用
27 |
28 | - 机器人
29 | - 机器人管理
30 | - 配置管理
31 | - 策略管理
32 | - 监控列表
33 | - 交易对交易
34 | - 交易对历史成交
35 | - 市场
36 | - 全部交易对
37 | - 交易队详情
38 | - 获得热门产品
39 |
40 | ## API支持
41 |
42 | - 机器人实时状态初始化与更新 `必选`
43 | - 机器人操作 `必选`
44 | - 机器人配置 `可选`
45 | - 机器人策略 `可选`
46 | - 机器人所在交易市场行情 `可选`
47 |
--------------------------------------------------------------------------------
/docs/zh/status.md:
--------------------------------------------------------------------------------
1 | # 状态API
2 |
3 | 状态API为客户端的机器人模块提供必要数据,目前包括以下API
4 |
5 | - init 获得机器人所有初始数据
6 | - refresh 机器人数据更新数据
7 |
8 | ## 实现
9 |
10 | > **必选**
11 | > 服务器端使用websocket通讯时,`init`将获得所有初始数据并初始化客户端,websocket 通过广播不断将`refrsh`数据传递给客户端
12 |
13 | ## API列表
14 |
15 | ### - init
16 |
17 | 获取当前机器人所在初始数据
18 |
19 | #### 请求参数
20 |
21 | > 用户初次连接机器人成功时,服务器将主动推送。
22 | > 用户设备重新连接(比如浏览器移动设备resume事件)也会主动推送
23 |
24 | ```javascript
25 | {
26 | "action": "init",
27 | "apiKey":"YOUR API KEY"
28 | }
29 | ```
30 |
31 | #### 返回结果
32 |
33 | ```javascript
34 | {
35 | "exchange": { //交易所
36 | "name": "sim", //交易所名称 'sim'为模拟交易
37 | "makerFee": 0.1, //交易所市价费率
38 | "takerFee": 0.1//交易所限价费率
39 | },
40 | "symbols": [ // 监控池交易对
41 | {
42 | "product_id": "ETH-USDT", //交易对名称
43 | "price": 1858.08, //价格
44 | "normalized": "mexc.ETH-USDT",//全称
45 | "min_size": "0.00001",//最小交易价格
46 | "asset": "ETH",
47 | "currency": "USDT",
48 | "assetCaptial": 0,
49 | "leverage": 10,//杠杆大小
50 | "isolated": false,//是否全仓
51 | "usdtProfit": 0,//USDT 利润
52 | "dynamicProfit": 0,//未实现 USDT 利润
53 | "dynamicUsdtProfit": 0,//未实现 USDT 利润率
54 | "profit": 0,//USDT 利润率
55 | "signal": null,//信号 包括 'buying','selling','bought','sold'
56 | "win": 0,//赢次数
57 | "lost": 0,//输次数
58 | "winLostRate": 0,//赢率
59 | "trades": [{//成交订单列表
60 | "order_id": 1001, //订单ID
61 | "time": 1681111866476,//订单时间
62 | "execution_time": 5001,//订单执行时间
63 | "slippage": 0,//订单滑点
64 | "type": "buy",//订单类型 buy or sell
65 | "size": "0.10757",//订单数量
66 | "fee": 0.19980051799999998,//订单费用 usdt计价
67 | "price": "1857.40", //订单成交价
68 | "order_type": "maker",//订单成交方式 'maker' 或 'taker'
69 | "action": "BollingerBands_buy_long",//订单成交策略
70 | "profit": -0.0009999999999999998, //订单利润
71 | "usdtProfit": -0.19980051799999998,//订单利润率
72 | "position_side": "long",//订单多还是空 'long' 或 'short'
73 | },
74 | ...
75 | ],
76 | "lastTradeTime": 0,//最后交易时间
77 | "klines": [//K线数据
78 | {
79 | "period_id": "m28018427",
80 | "time": 1681105620000,
81 | "size": "1m",
82 | "close_time": 1681105679999,
83 | "open": 1863.3,
84 | "high": 1863.38,
85 | "low": 1862.22,
86 | "close": 1862.22,
87 | "volume": 45.16688,
88 | "strategy": { //K线中的策略数据
89 | "BollingerBands_buyCrossCount": 0,//策略BollingerBands同一周期内买点次数
90 | "BollingerBands_sellCrossCount": 0,//策略BollingerBands同一周期内卖点次数
91 | "BollingerBands_buy": false,//策略BollingerBands是否有买点
92 | "BollingerBands_sell": false//策略BollingerBands是否有卖点
93 | }
94 | },
95 | ...
96 | ]
97 | },
98 | ...
99 | ],
100 | "status": { //机器人状态
101 | "hasConfig": true,//是否实现配置模块
102 | "hasStrategy": true,//是否实现策略模块
103 | "hasMarket": true,//是否实现市场模块
104 | "hasBacktest": true,//是否实现回测模块
105 | "tradeListLen": 1,//交易中交易对数量
106 | "startCapital": 1000,//初始资金
107 | "currentCapital": 800.10957177,//当前可用资金
108 | "tradeNum": 12,//成交数量
109 | "dynamicUsdtProfit": -0.0290142,//未实现USDT利润
110 | "dynamicProfit": -0.0000290142,//未实现USDT利润率
111 | "usdtProfit": -0.19980051799999998,//USDT利润
112 | "profit": -0.000199800518,//利润率
113 | "exchange": "mexc",//当前交易所
114 | "startTime": 1681111671975,//机器人启动时间
115 | "timeZoneOffset": -480,//服务器时间偏移
116 | "status": "work",//当前机器人状态,
117 | "win": 4,
118 | "lost": 1,
119 | "winLostRate": 0.8,
120 | "totalCapital":999.32 //当前资金,包括已实现与未实现利润
121 | }
122 | }
123 | ```
124 |
125 | ### - refresh
126 |
127 | 获取当前机器人实时更新数据
128 |
129 | > 服务器定时向客户端广播实时数据
130 | > 特定事件发生时可向客户端广播数据,比如订单成交时
131 |
132 | #### 请求参数
133 |
134 | ```javascript
135 | {
136 | "action": "refresh",
137 | "apiKey": "YOUR API KEY"
138 | }
139 | ```
140 |
141 | #### 返回结果
142 |
143 | ```javascript
144 | {
145 | "action": "refresh",
146 | "data": {
147 | "symbols": [ //所有交易对
148 | {
149 | "product_id": "ETH-USDT", //交易对名称
150 | "price": 1858.08, //价格
151 | "normalized": "mexc.ETH-USDT",//全称
152 | "min_size": "0.00001",//最小交易价格
153 | "asset": "ETH",
154 | "currency": "USDT",
155 | "assetCaptial": 0,
156 | "leverage": 10,//杠杆大小
157 | "isolated": false,//是否全仓
158 | "usdtProfit": 0,//USDT 利润
159 | "dynamicProfit": 0,//未实现 USDT 利润
160 | "dynamicUsdtProfit": 0,//未实现 USDT 利润率
161 | "profit": 0,//USDT 利润率
162 | "signal": null,//信号 包括 'buying','selling','bought','sold'
163 | "win": 0,//赢次数
164 | "lost": 0,//输次数
165 | "winLostRate": 0,//赢率
166 | "trades": [{//成交订单列表
167 | "order_id": 1001, //订单ID
168 | "time": 1681111866476,//订单时间
169 | "execution_time": 5001,//订单执行时间
170 | "slippage": 0,//订单滑点
171 | "type": "buy",//订单类型 buy or sell
172 | "size": "0.10757",//订单数量
173 | "fee": 0.19980051799999998,//订单费用 usdt计价
174 | "price": "1857.40", //订单成交价
175 | "order_type": "maker",//订单成交方式 'maker' 或 'taker'
176 | "action": "BollingerBands_buy_long",//订单成交策略
177 | "profit": -0.0009999999999999998, //订单利润
178 | "usdtProfit": -0.19980051799999998,//订单利润率
179 | "position_side": "long",//订单多还是空 'long' 或 'short'
180 | },
181 | ...
182 | ],
183 | "lastTradeTime": 0,//最后交易时间
184 | "klines": [//K线数据
185 | {
186 | "period_id": "m28018427",
187 | "time": 1681105620000,
188 | "size": "1m",
189 | "close_time": 1681105679999,
190 | "open": 1863.3,
191 | "high": 1863.38,
192 | "low": 1862.22,
193 | "close": 1862.22,
194 | "volume": 45.16688,
195 | "strategy": { //K线中的策略数据
196 | "BollingerBands_buyCrossCount": 0,//策略BollingerBands同一周期内买点次数
197 | "BollingerBands_sellCrossCount": 1,//策略BollingerBands同一周期内卖点次数
198 | "BollingerBands_buy": false,//策略BollingerBands是否有买点
199 | "BollingerBands_sell": false//策略BollingerBands是否有卖点
200 | "middle": 1856.3892857142853,//布林线中轨
201 | "upper": 1858.8566899522384,//布林线上轨
202 | "lower": 1853.9218814763321,//布林线轨
203 | "pb": 0.8203192775226102,//布林带偏移
204 | "pw": 0.26582832134842305,//布林带宽度
205 | }
206 | }
207 | ...
208 | ]
209 | },
210 | ...
211 | ],
212 | "status": { //机器人当前状态
213 | "tradeListLen": 1,//交易中交易对数量
214 | "startCapital": 1000,//初始资金
215 | "currentCapital": 800.10957177,//当前可用资金
216 | "tradeNum": 12,//成交数量
217 | "dynamicUsdtProfit": -0.0290142,//未实现USDT利润
218 | "dynamicProfit": -0.0000290142,//未实现USDT利润率
219 | "usdtProfit": -0.19980051799999998,//USDT利润
220 | "profit": -0.000199800518,//利润率
221 | "exchange": "mexc",//当前交易所
222 | "startTime": 1681111671975,//机器人启动时间
223 | "timeZoneOffset": -480,//服务器时间偏移
224 | "status": "work",//当前机器人状态,
225 | "win": 4,
226 | "lost": 1,
227 | "winLostRate": 0.8,
228 | "totalCapital":999.32 //当前资金,包括已实现与未实现利润
229 | }
230 | }
231 | }
232 | ```
233 |
--------------------------------------------------------------------------------
/docs/zh/strategy.md:
--------------------------------------------------------------------------------
1 | # 策略API
2 |
3 | 策略API为客户端的策略模块提供必要数据,通过策略模块,您在服务器的所有策略均可通过客户端进行实时更新。目前包括以下API
4 |
5 | - init 获得策略列表与策略值
6 | - updateConfig 更新策略
7 |
8 | ## 必需实现
9 |
10 | > **可选**
11 | > 您需要先启用配置模块.
12 | > 如果不实现此API,客户端将不会有策略模块.
13 | > 如果未实现此API,在状态API请将机器人状态的`init`中请将`hasStrategy`设置为`false`
14 |
15 | ## 更新流程
16 |
17 | - 在`init`事件中传递策略列表
18 | - 通过策略设置在客户端生成相关联的UI界面
19 | - 通过UI界面修改策略并通过`updateConfig`更新服务器端值
20 |
21 | ## API列表
22 |
23 | ### - init
24 |
25 | 当使用策略模块时,策略列表与策略参数将通过`init`传递至客户端
26 |
27 | #### 请求参数
28 |
29 | > 用户初次连接机器人成功时,服务器将主动推送。
30 | > 用户设备重新连接(比如浏览器移动设备resume事件)也会主动推送
31 |
32 | ```javascript
33 | {
34 | "action": "init",
35 | "apiKey":"YOUR API KEY"
36 | }
37 | ```
38 |
39 | #### 返回结果
40 |
41 | ```javascript
42 | {
43 | "options": {
44 | "strategy": Object,//当前策略会通过配置值传递至客户端
45 | ...
46 | },
47 | "strategies": [//策略列表
48 | {
49 | "id": "BollingerBands",// 策略ID
50 | "name": "BollingerBands",//策略名称
51 | "des": "BollingerBands",//策略描述
52 | "editable": false,//可编辑
53 | "group": "custom",//策略分组
54 | "order": 20,//策略权重
55 | "strategies": [//子策略,本示例使用布林带与RSI组合来判断买卖点
56 | {
57 | "name": "BollingerBands",//布林带
58 | "group": "volatility",//分组
59 | "input": [//输入
60 | {
61 | "name": "period",//布林带周期
62 | "type": "number",//数值类型
63 | "step": [//最大最小与步长
64 | 2,
65 | 100,
66 | 1
67 | ],
68 | "value": 14//默认值
69 | },
70 | {
71 | "name": "stdDev",//布林带偏移
72 | "type": "number",
73 | "step": [
74 | -1,
75 | 30,
76 | 1
77 | ],
78 | "value": 2
79 | },
80 | {
81 | "name": "valType",//输入数据
82 | "type": "array",//数组类型,可多选
83 | "list": [
84 | "open",
85 | "high",
86 | "low",
87 | "close",
88 | "volume"
89 | ],
90 | "value": [
91 | "close"//默认使用收盘价
92 | ]
93 | }
94 | ],
95 | "output": [//输出
96 | {
97 | "name": "upper",//上轨
98 | "report": true,//在服务端report中显示
99 | "show": true,//在客户端显示
100 | "pos": "main",//显示在主图上
101 | "type": "line"//显示类型为线图
102 | },
103 | {
104 | "name": "middle",
105 | "report": true,
106 | "show": true,
107 | "pos": "main",
108 | "type": "line"
109 | },
110 | {
111 | "name": "lower",
112 | "report": true,
113 | "show": true,
114 | "pos": "main",
115 | "type": "line"
116 | },
117 | {
118 | "name": "pw",
119 | "report": true,
120 | "mark": true,//买卖点将显示在本图
121 | "show": true,
122 | "pos": "sub",//显示在副图上
123 | "type": "line"
124 | },
125 | {
126 | "name": "signals",//买卖点信息
127 | "report": false,
128 | "show": true,
129 | "pos": "sub",
130 | "type": "marker"//显示为标识
131 | }
132 | ],
133 | "buyPoint": {//买点
134 | "connect": "base",//多个子策略时,本策略为基础策略
135 | "source": "close",//收盘价
136 | "op": "crossUp",//上穿
137 | "target": "lower"//下轨
138 | },
139 | "sellPoint": {//卖点
140 | "connect": "base",//多个子策略时,本策略为基础策略
141 | "source": "close",//收盘价
142 | "op": "crossDown",//下穿
143 | "target": "upper"//上轨
144 | }
145 | },
146 | {
147 | "name": "RSI",//另一个子策略名称
148 | "des": "RSI",
149 | "editable": false,
150 | "group": "oscillators",
151 | "input": [
152 | {
153 | "name": "period",
154 | "type": "number",
155 | "step": [
156 | 2,
157 | 100,
158 | 1
159 | ],
160 | "value": 8
161 | },
162 | {
163 | "name": "overBoughtThreshold",//超买点
164 | "type": "number",
165 | "step": [
166 | 0,
167 | 100,
168 | 1
169 | ],
170 | "value": 75,
171 | "show": true,
172 | "pos": "bottom",
173 | "owner": "RSI",//显示图为RSI
174 | "priceline": true //显示类型为价格线
175 | },
176 | {
177 | "name": "overSoldThreshold",//超卖点
178 | "type": "number",
179 | "step": [
180 | 0,
181 | 100,
182 | 1
183 | ],
184 | "value": 25,
185 | "show": true,
186 | "pos": "bottom",
187 | "owner": "RSI",//显示图为RSI
188 | "priceline": true//显示类型为价格线
189 | },
190 | {
191 | "name": "valType",
192 | "type": "array",
193 | "list": [
194 | "open",
195 | "high",
196 | "low",
197 | "close",
198 | "volume"
199 | ],
200 | "value": [
201 | "close"
202 | ]
203 | }
204 | ],
205 | "output": [
206 | {
207 | "name": "RSI",
208 | "report": true,
209 | "show": true,
210 | "pos": "bottom",//显示在底图中
211 | "type": "line",
212 | "mark": true
213 | },
214 | {
215 | "name": "signals",
216 | "report": false,
217 | "show": true,
218 | "pos": "bottom",//显示在底图中
219 | "type": "marker"
220 | }
221 | ],
222 | "buyPoint": {
223 | "connect": "and",//买点之间为和关系 'none','and','or',
224 | "source": "RSI",//RSI
225 | "op": "crossUp",//上穿
226 | "target": "overSoldThreshold"//超卖点
227 | },
228 | "sellPoint": {
229 | "connect": "or",//卖点之间为或关系 'none'为不启用,'and','or',
230 | "source": "RSI",//RSI
231 | "op": "crossDown",//下穿
232 | "target": "overBoughtThreshold"//超买点
233 | }
234 | }
235 | ]
236 | },
237 | ...
238 | ]
239 | }
240 | ```
241 |
242 | ### - updateConfig
243 |
244 | 更新机器人策略参数
245 |
246 | #### 请求参数
247 |
248 | ```javascript
249 | {
250 | "action": "updateConfig",
251 | "restart": true, //本次更新需要重启机器人
252 | "data": {
253 | "strategy": Object, //更新策略
254 | },
255 | "apiKey": "YOUR API KEY"
256 | }
257 | ```
258 |
259 | #### 返回结果
260 |
261 | ```json
262 | {
263 | "action": "updateConfig",
264 | "data":Object, //返回全部配置参数 方便更
265 | "toast": "trade.updateConfigOk"
266 | }
267 | ```
268 |
269 | > 一些示例的策略文件
270 |
271 | ````javascript
272 | [
273 | {
274 | "id": "RSI",
275 | "name": "RSI",
276 | "des": "RSI",
277 | "editable": false,
278 | "group": "custom",
279 | "order": 10,
280 | "strategies": [
281 | {
282 | "name": "RSI",
283 | "des": "RSI",
284 | "editable": false,
285 | "group": "oscillators",
286 | "input": [
287 | {
288 | "name": "period",
289 | "type": "number",
290 | "step": [
291 | 2,
292 | 100,
293 | 1
294 | ],
295 | "value": 8
296 | },
297 | {
298 | "name": "overBoughtThreshold",
299 | "type": "number",
300 | "step": [
301 | 0,
302 | 100,
303 | 1
304 | ],
305 | "value": 75,
306 | "show": true,
307 | "pos": "bottom",
308 | "owner": "RSI",
309 | "priceline": true
310 | },
311 | {
312 | "name": "overSoldThreshold",
313 | "type": "number",
314 | "step": [
315 | 0,
316 | 100,
317 | 1
318 | ],
319 | "value": 25,
320 | "show": true,
321 | "pos": "bottom",
322 | "owner": "RSI",
323 | "priceline": true
324 | },
325 | {
326 | "name": "valType",
327 | "type": "array",
328 | "list": [
329 | "open",
330 | "high",
331 | "low",
332 | "close",
333 | "volume"
334 | ],
335 | "value": [
336 | "close"
337 | ]
338 | }
339 | ],
340 | "output": [
341 | {
342 | "name": "RSI",
343 | "report": true,
344 | "show": true,
345 | "pos": "bottom",
346 | "type": "line",
347 | "mark": true
348 | },
349 | {
350 | "name": "signals",
351 | "report": false,
352 | "show": true,
353 | "pos": "bottom",
354 | "type": "marker"
355 | }
356 | ],
357 | "buyPoint": {
358 | "connect": "base",
359 | "source": "RSI",
360 | "op": "crossUp",
361 | "target": "overSoldThreshold"
362 | },
363 | "sellPoint": {
364 | "connect": "base",
365 | "source": "RSI",
366 | "op": "crossDown",
367 | "target": "overBoughtThreshold"
368 | }
369 | }
370 | ]
371 | },
372 | {
373 | "id": "BollingerBands",
374 | "name": "BollingerBands",
375 | "des": "BollingerBands",
376 | "editable": false,
377 | "group": "custom",
378 | "order": 20,
379 | "strategies": [
380 | {
381 | "name": "BollingerBands",
382 | "group": "volatility",
383 | "input": [
384 | {
385 | "name": "period",
386 | "type": "number",
387 | "step": [
388 | 2,
389 | 100,
390 | 1
391 | ],
392 | "value": 14
393 | },
394 | {
395 | "name": "stdDev",
396 | "type": "number",
397 | "step": [
398 | -1,
399 | 30,
400 | 1
401 | ],
402 | "value": 2
403 | },
404 | {
405 | "name": "valType",
406 | "type": "array",
407 | "list": [
408 | "open",
409 | "high",
410 | "low",
411 | "close",
412 | "volume"
413 | ],
414 | "value": [
415 | "close"
416 | ]
417 | }
418 | ],
419 | "output": [
420 | {
421 | "name": "upper",
422 | "report": true,
423 | "show": true,
424 | "pos": "main",
425 | "type": "line"
426 | },
427 | {
428 | "name": "middle",
429 | "report": true,
430 | "show": true,
431 | "pos": "main",
432 | "type": "line"
433 | },
434 | {
435 | "name": "lower",
436 | "report": true,
437 | "show": true,
438 | "pos": "main",
439 | "type": "line"
440 | },
441 | {
442 | "name": "pw",
443 | "report": true,
444 | "mark": true,
445 | "show": true,
446 | "pos": "sub",
447 | "type": "line"
448 | },
449 | {
450 | "name": "signals",
451 | "report": false,
452 | "show": true,
453 | "pos": "sub",
454 | "type": "marker"
455 | }
456 | ],
457 | "buyPoint": {
458 | "connect": "base",
459 | "source": "close",
460 | "op": "crossUp",
461 | "target": "lower"
462 | },
463 | "sellPoint": {
464 | "connect": "base",
465 | "source": "close",
466 | "op": "crossDown",
467 | "target": "upper"
468 | }
469 | },
470 | {
471 | "name": "RSI",
472 | "des": "RSI",
473 | "editable": false,
474 | "group": "oscillators",
475 | "input": [
476 | {
477 | "name": "period",
478 | "type": "number",
479 | "step": [
480 | 2,
481 | 100,
482 | 1
483 | ],
484 | "value": 8
485 | },
486 | {
487 | "name": "overBoughtThreshold",
488 | "type": "number",
489 | "step": [
490 | 0,
491 | 100,
492 | 1
493 | ],
494 | "value": 75,
495 | "show": true,
496 | "pos": "bottom",
497 | "owner": "RSI",
498 | "priceline": true
499 | },
500 | {
501 | "name": "overSoldThreshold",
502 | "type": "number",
503 | "step": [
504 | 0,
505 | 100,
506 | 1
507 | ],
508 | "value": 25,
509 | "show": true,
510 | "pos": "bottom",
511 | "owner": "RSI",
512 | "priceline": true
513 | },
514 | {
515 | "name": "valType",
516 | "type": "array",
517 | "list": [
518 | "open",
519 | "high",
520 | "low",
521 | "close",
522 | "volume"
523 | ],
524 | "value": [
525 | "close"
526 | ]
527 | }
528 | ],
529 | "output": [
530 | {
531 | "name": "RSI",
532 | "report": true,
533 | "show": true,
534 | "pos": "bottom",
535 | "type": "line",
536 | "mark": true
537 | },
538 | {
539 | "name": "signals",
540 | "report": false,
541 | "show": true,
542 | "pos": "bottom",
543 | "type": "marker"
544 | }
545 | ],
546 | "buyPoint": {
547 | "connect": "none",
548 | "source": "RSI",
549 | "op": "crossUp",
550 | "target": "overSoldThreshold"
551 | },
552 | "sellPoint": {
553 | "connect": "none",
554 | "source": "RSI",
555 | "op": "crossDown",
556 | "target": "overBoughtThreshold"
557 | }
558 | }
559 | ]
560 | },
561 | {
562 | "id": "PSAR",
563 | "name": "PSAR",
564 | "des": "PSAR",
565 | "editable": false,
566 | "group": "custom",
567 | "order": 30,
568 | "strategies": [
569 | {
570 | "name": "PSAR",
571 | "group": "momentum",
572 | "input": [
573 | {
574 | "name": "step",
575 | "type": "number",
576 | "step": [
577 | 0.01,
578 | 1,
579 | 0.005
580 | ],
581 | "value": 0.02
582 | },
583 | {
584 | "name": "max",
585 | "type": "number",
586 | "step": [
587 | 0.05,
588 | 1,
589 | 0.05
590 | ],
591 | "value": 0.2
592 | },
593 | {
594 | "name": "valType",
595 | "type": "array",
596 | "list": [
597 | "open",
598 | "high",
599 | "low",
600 | "close",
601 | "volume"
602 | ],
603 | "value": [
604 | "high",
605 | "low"
606 | ]
607 | }
608 | ],
609 | "output": [
610 | {
611 | "name": "PSAR",
612 | "report": true,
613 | "mark": false,
614 | "show": true,
615 | "pos": "main",
616 | "type": "line",
617 | "dot": true
618 | },
619 | {
620 | "name": "trend",
621 | "report": true,
622 | "mark": true,
623 | "show": true,
624 | "pos": "sub",
625 | "type": "line"
626 | },
627 | {
628 | "name": "signals",
629 | "report": false,
630 | "show": true,
631 | "pos": "main",
632 | "type": "marker"
633 | }
634 | ],
635 | "buyPoint": {
636 | "connect": "base",
637 | "source": "PSAR",
638 | "op": "crossDown",
639 | "target": "close"
640 | },
641 | "sellPoint": {
642 | "connect": "base",
643 | "source": "PSAR",
644 | "op": "crossUp",
645 | "target": "close"
646 | }
647 | },
648 | {
649 | "name": "RSI",
650 | "des": "RSI",
651 | "editable": false,
652 | "group": "oscillators",
653 | "input": [
654 | {
655 | "name": "period",
656 | "type": "number",
657 | "step": [
658 | 2,
659 | 100,
660 | 1
661 | ],
662 | "value": 8
663 | },
664 | {
665 | "name": "overBoughtThreshold",
666 | "type": "number",
667 | "step": [
668 | 0,
669 | 100,
670 | 1
671 | ],
672 | "value": 75,
673 | "show": true,
674 | "pos": "bottom",
675 | "owner": "RSI",
676 | "priceline": true
677 | },
678 | {
679 | "name": "overSoldThreshold",
680 | "type": "number",
681 | "step": [
682 | 0,
683 | 100,
684 | 1
685 | ],
686 | "value": 25,
687 | "show": true,
688 | "pos": "bottom",
689 | "owner": "RSI",
690 | "priceline": true
691 | },
692 | {
693 | "name": "valType",
694 | "type": "array",
695 | "list": [
696 | "open",
697 | "high",
698 | "low",
699 | "close",
700 | "volume"
701 | ],
702 | "value": [
703 | "close"
704 | ]
705 | }
706 | ],
707 | "output": [
708 | {
709 | "name": "RSI",
710 | "report": true,
711 | "show": true,
712 | "pos": "bottom",
713 | "type": "line",
714 | "mark": true
715 | },
716 | {
717 | "name": "signals",
718 | "report": false,
719 | "show": true,
720 | "pos": "bottom",
721 | "type": "marker"
722 | }
723 | ],
724 | "buyPoint": {
725 | "connect": "none",
726 | "source": "RSI",
727 | "op": "crossUp",
728 | "target": "overSoldThreshold"
729 | },
730 | "sellPoint": {
731 | "connect": "none",
732 | "source": "RSI",
733 | "op": "crossDown",
734 | "target": "overBoughtThreshold"
735 | }
736 | }
737 | ]
738 | },
739 | {
740 | "id": "MACD",
741 | "name": "MACD",
742 | "des": "MACD",
743 | "editable": false,
744 | "group": "custom",
745 | "order": 40,
746 | "strategies": [
747 | {
748 | "name": "MACD",
749 | "group": "moving_averages",
750 | "input": [
751 | {
752 | "name": "fastPeriod",
753 | "type": "number",
754 | "step": [
755 | 1,
756 | 200,
757 | 1
758 | ],
759 | "value": 5
760 | },
761 | {
762 | "name": "slowPeriod",
763 | "type": "number",
764 | "step": [
765 | 1,
766 | 200,
767 | 1
768 | ],
769 | "value": 8
770 | },
771 | {
772 | "name": "signalPeriod",
773 | "type": "number",
774 | "step": [
775 | 1,
776 | 200,
777 | 1
778 | ],
779 | "value": 3
780 | },
781 | {
782 | "name": "SimpleMAOscillator",
783 | "type": "bool",
784 | "value": false
785 | },
786 | {
787 | "name": "SimpleMASignal",
788 | "type": "bool",
789 | "value": false
790 | },
791 | {
792 | "name": "valType",
793 | "type": "array",
794 | "list": [
795 | "open",
796 | "high",
797 | "low",
798 | "close",
799 | "volume"
800 | ],
801 | "value": [
802 | "close"
803 | ]
804 | }
805 | ],
806 | "output": [
807 | {
808 | "name": "MACD",
809 | "report": true,
810 | "show": true,
811 | "pos": "sub",
812 | "type": "line"
813 | },
814 | {
815 | "name": "histogram",
816 | "report": true,
817 | "show": true,
818 | "pos": "sub",
819 | "mark": true,
820 | "type": "line"
821 | },
822 | {
823 | "name": "signal",
824 | "report": true,
825 | "show": true,
826 | "pos": "sub",
827 | "type": "line"
828 | },
829 | {
830 | "name": "signals",
831 | "report": false,
832 | "show": true,
833 | "pos": "sub",
834 | "type": "marker"
835 | }
836 | ],
837 | "buyPoint": {
838 | "connect": "base",
839 | "source": "histogram",
840 | "op": "crossUp",
841 | "target": 0
842 | },
843 | "sellPoint": {
844 | "connect": "base",
845 | "source": "histogram",
846 | "op": "crossDown",
847 | "target": 0
848 | }
849 | },
850 | {
851 | "name": "RSI",
852 | "des": "RSI",
853 | "editable": false,
854 | "group": "oscillators",
855 | "input": [
856 | {
857 | "name": "period",
858 | "type": "number",
859 | "step": [
860 | 2,
861 | 100,
862 | 1
863 | ],
864 | "value": 8
865 | },
866 | {
867 | "name": "overBoughtThreshold",
868 | "type": "number",
869 | "step": [
870 | 0,
871 | 100,
872 | 1
873 | ],
874 | "value": 75,
875 | "show": true,
876 | "pos": "bottom",
877 | "owner": "RSI",
878 | "priceline": true
879 | },
880 | {
881 | "name": "overSoldThreshold",
882 | "type": "number",
883 | "step": [
884 | 0,
885 | 100,
886 | 1
887 | ],
888 | "value": 25,
889 | "show": true,
890 | "pos": "bottom",
891 | "owner": "RSI",
892 | "priceline": true
893 | },
894 | {
895 | "name": "valType",
896 | "type": "array",
897 | "list": [
898 | "open",
899 | "high",
900 | "low",
901 | "close",
902 | "volume"
903 | ],
904 | "value": [
905 | "close"
906 | ]
907 | }
908 | ],
909 | "output": [
910 | {
911 | "name": "RSI",
912 | "report": true,
913 | "show": true,
914 | "pos": "bottom",
915 | "type": "line",
916 | "mark": true
917 | },
918 | {
919 | "name": "signals",
920 | "report": false,
921 | "show": true,
922 | "pos": "bottom",
923 | "type": "marker"
924 | }
925 | ],
926 | "buyPoint": {
927 | "connect": "none",
928 | "source": "RSI",
929 | "op": "crossUp",
930 | "target": "overSoldThreshold"
931 | },
932 | "sellPoint": {
933 | "connect": "none",
934 | "source": "RSI",
935 | "op": "crossDown",
936 | "target": "overBoughtThreshold"
937 | }
938 | }
939 | ]
940 | },
941 | {
942 | "id": "CandleStick",
943 | "name": "CandleStick",
944 | "des": "CandleStick",
945 | "editable": false,
946 | "group": "custom",
947 | "order": 50,
948 | "strategies": [
949 | {
950 | "name": "CandleStick",
951 | "group": "candlestick",
952 | "input": [
953 | {
954 | "name": "buyPatterns",
955 | "type": "array",
956 | "list": [
957 | "BullishEngulfingPattern",
958 | "DownsideTasukiGap",
959 | "BullishHarami",
960 | "BullishHaramiCross",
961 | "MorningDojiStar",
962 | "MorningStar",
963 | "BullishMarubozu",
964 | "PiercingLine",
965 | "ThreeWhiteSoldiers",
966 | "BullishHammerStick",
967 | "BullishInvertedHammerStick",
968 | "HammerPattern",
969 | "HammerPatternUnconfirmed",
970 | "TweezerBottom"
971 | ],
972 | "value": [
973 | "ThreeWhiteSoldiers",
974 | "HammerPattern",
975 | "TweezerBottom"
976 | ]
977 | },
978 | {
979 | "name": "sellPatterns",
980 | "type": "array",
981 | "list": [
982 | "BearishEngulfingPattern",
983 | "BearishHarami",
984 | "BearishHaramiCross",
985 | "EveningDojiStar",
986 | "EveningStar",
987 | "BearishMarubozu",
988 | "ThreeBlackCrows",
989 | "BearishHammerStick",
990 | "BearishInvertedHammerStick",
991 | "HangingMan",
992 | "HangingManUnconfirmed",
993 | "ShootingStar",
994 | "ShootingStarUnconfirmed",
995 | "TweezerTop"
996 | ],
997 | "value": [
998 | "ThreeBlackCrows",
999 | "HangingMan",
1000 | "ShootingStar",
1001 | "TweezerTop"
1002 | ]
1003 | },
1004 | {
1005 | "name": "valType",
1006 | "type": "array",
1007 | "list": [
1008 | "open",
1009 | "high",
1010 | "low",
1011 | "close",
1012 | "volume"
1013 | ],
1014 | "value": [
1015 | "close",
1016 | "high",
1017 | "low",
1018 | "open"
1019 | ]
1020 | }
1021 | ],
1022 | "output": [
1023 | {
1024 | "name": "pattern",
1025 | "mark": true,
1026 | "report": true,
1027 | "show": true,
1028 | "pos": "sub",
1029 | "type": "line"
1030 | },
1031 | {
1032 | "name": "patternname",
1033 | "report": true,
1034 | "show": false,
1035 | "pos": "sub",
1036 | "type": "none"
1037 | },
1038 | {
1039 | "name": "signals",
1040 | "report": false,
1041 | "show": true,
1042 | "pos": "sub",
1043 | "type": "marker"
1044 | }
1045 | ],
1046 | "buyPoint": {
1047 | "connect": "base",
1048 | "source": "pattern",
1049 | "op": "equal",
1050 | "target": -1
1051 | },
1052 | "sellPoint": {
1053 | "connect": "base",
1054 | "source": "pattern",
1055 | "op": "equal",
1056 | "target": 1
1057 | }
1058 | },
1059 | {
1060 | "name": "RSI",
1061 | "des": "RSI",
1062 | "editable": false,
1063 | "group": "oscillators",
1064 | "input": [
1065 | {
1066 | "name": "period",
1067 | "type": "number",
1068 | "step": [
1069 | 2,
1070 | 100,
1071 | 1
1072 | ],
1073 | "value": 8
1074 | },
1075 | {
1076 | "name": "overBoughtThreshold",
1077 | "type": "number",
1078 | "step": [
1079 | 0,
1080 | 100,
1081 | 1
1082 | ],
1083 | "value": 75,
1084 | "show": true,
1085 | "pos": "bottom",
1086 | "owner": "RSI",
1087 | "priceline": true
1088 | },
1089 | {
1090 | "name": "overSoldThreshold",
1091 | "type": "number",
1092 | "step": [
1093 | 0,
1094 | 100,
1095 | 1
1096 | ],
1097 | "value": 25,
1098 | "show": true,
1099 | "pos": "bottom",
1100 | "owner": "RSI",
1101 | "priceline": true
1102 | },
1103 | {
1104 | "name": "valType",
1105 | "type": "array",
1106 | "list": [
1107 | "open",
1108 | "high",
1109 | "low",
1110 | "close",
1111 | "volume"
1112 | ],
1113 | "value": [
1114 | "close"
1115 | ]
1116 | }
1117 | ],
1118 | "output": [
1119 | {
1120 | "name": "RSI",
1121 | "report": true,
1122 | "show": true,
1123 | "pos": "bottom",
1124 | "type": "line",
1125 | "mark": true
1126 | },
1127 | {
1128 | "name": "signals",
1129 | "report": false,
1130 | "show": true,
1131 | "pos": "bottom",
1132 | "type": "marker"
1133 | }
1134 | ],
1135 | "buyPoint": {
1136 | "connect": "none",
1137 | "source": "RSI",
1138 | "op": "crossUp",
1139 | "target": "overSoldThreshold"
1140 | },
1141 | "sellPoint": {
1142 | "connect": "none",
1143 | "source": "RSI",
1144 | "op": "crossDown",
1145 | "target": "overBoughtThreshold"
1146 | }
1147 | }
1148 | ]
1149 | },
1150 | {
1151 | "id": "CUSTOM",
1152 | "name": "CUSTOM",
1153 | "des": "CUSTOM",
1154 | "editable": false,
1155 | "group": "custom",
1156 | "order": 100,
1157 | "strategies": [
1158 | {
1159 | "name": "PSAR",
1160 | "group": "momentum",
1161 | "input": [
1162 | {
1163 | "name": "step",
1164 | "type": "number",
1165 | "step": [
1166 | 0.01,
1167 | 1,
1168 | 0.005
1169 | ],
1170 | "value": 0.02
1171 | },
1172 | {
1173 | "name": "max",
1174 | "type": "number",
1175 | "step": [
1176 | 0.05,
1177 | 1,
1178 | 0.05
1179 | ],
1180 | "value": 0.2
1181 | },
1182 | {
1183 | "name": "valType",
1184 | "type": "array",
1185 | "list": [
1186 | "open",
1187 | "high",
1188 | "low",
1189 | "close",
1190 | "volume"
1191 | ],
1192 | "value": [
1193 | "high",
1194 | "low"
1195 | ]
1196 | }
1197 | ],
1198 | "output": [
1199 | {
1200 | "name": "PSAR",
1201 | "report": true,
1202 | "show": true,
1203 | "pos": "main",
1204 | "type": "line",
1205 | "dot": true
1206 | },
1207 | {
1208 | "name": "trend",
1209 | "report": true,
1210 | "mark": true,
1211 | "show": true,
1212 | "pos": "sub",
1213 | "type": "line"
1214 | },
1215 | {
1216 | "name": "signals",
1217 | "report": false,
1218 | "show": true,
1219 | "pos": "main",
1220 | "type": "marker"
1221 | }
1222 | ],
1223 | "buyPoint": {
1224 | "connect": "base",
1225 | "source": "PSAR",
1226 | "op": "crossDown",
1227 | "target": "close"
1228 | },
1229 | "sellPoint": {
1230 | "connect": "base",
1231 | "source": "PSAR",
1232 | "op": "crossUp",
1233 | "target": "close"
1234 | }
1235 | },
1236 | {
1237 | "name": "RSI",
1238 | "des": "RSI",
1239 | "editable": false,
1240 | "group": "oscillators",
1241 | "input": [
1242 | {
1243 | "name": "period",
1244 | "type": "number",
1245 | "step": [
1246 | 2,
1247 | 100,
1248 | 1
1249 | ],
1250 | "value": 8
1251 | },
1252 | {
1253 | "name": "overBoughtThreshold",
1254 | "type": "number",
1255 | "step": [
1256 | 0,
1257 | 100,
1258 | 1
1259 | ],
1260 | "value": 75,
1261 | "show": true,
1262 | "pos": "bottom",
1263 | "owner": "RSI",
1264 | "priceline": true
1265 | },
1266 | {
1267 | "name": "overSoldThreshold",
1268 | "type": "number",
1269 | "step": [
1270 | 0,
1271 | 100,
1272 | 1
1273 | ],
1274 | "value": 25,
1275 | "show": true,
1276 | "pos": "bottom",
1277 | "owner": "RSI",
1278 | "priceline": true
1279 | },
1280 | {
1281 | "name": "valType",
1282 | "type": "array",
1283 | "list": [
1284 | "open",
1285 | "high",
1286 | "low",
1287 | "close",
1288 | "volume"
1289 | ],
1290 | "value": [
1291 | "close"
1292 | ]
1293 | }
1294 | ],
1295 | "output": [
1296 | {
1297 | "name": "RSI",
1298 | "report": true,
1299 | "show": true,
1300 | "pos": "bottom",
1301 | "type": "line",
1302 | "mark": true
1303 | },
1304 | {
1305 | "name": "signals",
1306 | "report": false,
1307 | "show": true,
1308 | "pos": "bottom",
1309 | "type": "marker"
1310 | }
1311 | ],
1312 | "buyPoint": {
1313 | "connect": "and",
1314 | "source": "RSI",
1315 | "op": "crossUp",
1316 | "target": "overSoldThreshold"
1317 | },
1318 | "sellPoint": {
1319 | "connect": "and",
1320 | "source": "RSI",
1321 | "op": "crossDown",
1322 | "target": "overBoughtThreshold"
1323 | }
1324 | }
1325 | ]
1326 | }
1327 | ]
1328 | ````
1329 |
--------------------------------------------------------------------------------
/extensions/xcoin/README.md:
--------------------------------------------------------------------------------
1 | # Panacea's preferred server-side program XCoin
2 |
3 | XCoin implements all the APIs of Panacea, you can directly use XCoin as your background bot, or learn how to adapts your bot by learning the source code of XCoin
4 |
5 | ## Install
6 |
7 | copy `panacea` folder to your xcoin project `extensions/output/` folder
8 |
9 | ## About XCoin
10 |
11 | A simple and powerful trading bot based on nodejs
12 |
13 | ## Features
14 |
15 | - Support trading multiple trading pairs at the same time, as long as the server has enough computing power, theoretically you can trade all trading pairs at the same time.
16 |
17 | - Support all exchanges supported by [ccxt](https://github.com/ccxt/ccxt), [Binance](https://www.binance.com),[BinanceUsdm](https://www.binance.com), [Mexc](https://www.mexc.com/) have been fully tested.
18 |
19 | - Support all trading strategies supported by [technicalindicators](https://github.com/anandanand84/technicalindicators), easily extend new strategies through JSON files.
20 |
21 | - Supports futures trading and can control whether it is long or short or both trading.
22 |
23 | - Support multiple trading methods, automatic buying, manual buying, manual selling or full manual mode.
24 |
25 | - Supports monitoring of purchased items, blacklist, and dynamic addition of monitoring items
26 |
27 | - Support getting price updates on a separate thread, and support deploying multiple bots on the same machine on the same exchange.
28 |
29 | - Support real transactions, virtual transactions and backtest transactions
30 |
31 | - Support all mobile devices and desktop devices through [Panacea](https://github.com/markmind/panacea-api), control all the states and operations of the bot in real time
32 |
33 | - Based on [Zenbot](https://github.com/DeviaVir/zenbot), Supports most of the functions of zenbot.
34 |
35 | ## Documentation
36 |
37 | - [User Documentation](https://rainfu.github.io/xcoin)
38 |
--------------------------------------------------------------------------------
/extensions/xcoin/README.zh-CN.md:
--------------------------------------------------------------------------------
1 | # 灵丹首选服务器端程序 XCoin
2 |
3 | XCoin实现了灵丹所有的API,您可以直接使用XCoin作为您的后台机器人,也可以通过学习XCoin的源码了解如何使用适配您的机器人
4 |
5 | ## 安装
6 |
7 | 复制 `panacea` 目录 to 您的XCoin项目的 `extensions/output/` 目录
8 |
9 | ## 关于XCoin
10 |
11 | 基于nodejs的简洁强大的交易机器人
12 |
13 | ## 功能特征
14 |
15 | - 支持同时交易多个交易对,只要服务器有足够算力,理论上你可以同时交易所有交易对.
16 | - 支持 [ccxt](https://github.com/ccxt/ccxt) 支持的所有交易所,[Binance](https://www.binance.com),[BinanceUsdm](https://www.binance.com),[Mexc](https://www.mexc.com/)已完整测试.
17 | - 支持 [technicalindicators](https://github.com/anandanand84/technicalindicators) 支持的所有交易策略,轻松通过JSON文件扩展新的策略.
18 | - 支持期货交易并可控制是多空双方还是仅交易多方,空方.
19 | - 支持多种交易方式,自动买,手动买,手动卖或完全手动模式.
20 | - 支持监控已购项目,支持黑名单,支持动态添加监控项目
21 | - 支持在单独线程上获取价格更新,支持同一机器同一交易所部署多个机器人.
22 | - 支持真实交易,虚拟交易及对交易进行回测
23 | - 基于 [Zenbot](https://github.com/DeviaVir/zenbot) ,支持 zenbot 的绝大部分功能.
24 |
25 | ## 文档
26 |
27 | - [用户文档](https://rainfu.github.io/xcoin)
28 |
--------------------------------------------------------------------------------
/extensions/xcoin/panacea/api/api.js:
--------------------------------------------------------------------------------
1 | var { getInitData, getRefreshData } = require('./status')
2 | , { getBacktestList, delBacktest, getSimList, delSim, backtestSim } = require('./backtest')
3 | , { addSymbol, removeAllSymbol, removeSymbol, sellAll, buy, sell, getBalance, getDemoBot } = require('./operation')
4 | , { updateConfig, updateSymbolFuture } = require('./config')
5 | , { checkVersion } = require('./panacea')
6 | , { getProducts, getKlines, getTickers, getPickerNormal } = require('./market')
7 | module.exports = function api() {
8 | return {
9 | getInitData,
10 | getRefreshData,
11 | getBacktestList,
12 | delBacktest,
13 | getSimList,
14 | delSim,
15 | backtestSim,
16 | addSymbol,
17 | removeAllSymbol,
18 | removeSymbol,
19 | buy,
20 | sell,
21 | sellAll,
22 | updateConfig,
23 | updateSymbolFuture,
24 | checkVersion,
25 | getProducts,
26 | getKlines,
27 | getTickers,
28 | getPickerNormal,
29 | getBalance,
30 | getDemoBot
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/extensions/xcoin/panacea/api/backtest.js:
--------------------------------------------------------------------------------
1 | const collectionService = require('../../../../lib/mongo-service')
2 | , spawn = require('child_process').spawn
3 | , path = require('path')
4 |
5 | const getBacktestList = (message, cb, s, conf) => {
6 | let collectionServiceInstance = collectionService(conf)
7 | let bots = collectionServiceInstance.getBots()
8 | bots.find({ "status.status": 'finished' }).skip(message.data.from).limit(message.data.limit).sort({ startTime: -1 }).toArray((err, botArray) => {
9 | if (err) return
10 | let data = {
11 | action: message.action,
12 | data: botArray
13 | }
14 | if (cb) cb(data)
15 | })
16 | }
17 | const delBacktest = (message, cb, s, conf) => {
18 | let collectionServiceInstance = collectionService(conf)
19 | let bots = collectionServiceInstance.getBots()
20 | bots.deleteOne({ "_id": message.data.id }).then((res) => {
21 | if (res.deletedCount) {
22 | let data = {
23 | action: message.action,
24 | data: {
25 | id: message.data.id
26 | },
27 | toast: 'backtest.' + message.action + 'Ok'
28 | }
29 | if (cb) cb(data)
30 | }
31 | })
32 | }
33 | const getSimList = (message, cb, s, conf) => {
34 | let simCollection = collectionService(conf).getSims()
35 | simCollection.find({ bid: message.data.bid }).skip(message.data.from).limit(message.data.limit).sort({ time: -1 }).toArray((err, simArray) => {
36 | console.log('getSimList', message.data, err, simArray)
37 | if (err) return
38 | let data = {
39 | action: message.action,
40 | data: simArray
41 | }
42 | if (cb) cb(data)
43 | })
44 | }
45 | const delSim = (message, cb, s, conf) => {
46 | let collectionServiceInstance = collectionService(conf)
47 | let simList = collectionServiceInstance.getSims()
48 | simList.deleteOne({ "_id": message.data.id }).then((res) => {
49 | if (res.deletedCount) {
50 | let data = {
51 | action: message.action,
52 | data: {
53 | id: message.data.id
54 | },
55 | toast: 'backtest.' + message.action + 'Ok'
56 | }
57 | if (cb) cb(data)
58 | }
59 | })
60 | }
61 | const backtestSim = (message, cb) => {
62 | var xcoin_cmd = process.platform === 'win32' ? 'xcoin.bat' : 'xcoin.sh'
63 | var command_args = ['sim', message.data.exchange, '--bot', message.data.bid, '--sim_options', message.data.options]
64 | console.log('Start backtest for bot '.green)
65 | var simProcess = spawn(path.resolve(__dirname, '../../', xcoin_cmd), command_args)
66 | simProcess.stdout.pipe(process.stdout)
67 | simProcess.stderr.pipe(process.stderr)
68 | simProcess.on('exit', (code) => {
69 | if (code) {
70 | console.log('simProcess exit with code'.green, code)
71 | process.exit(code)
72 | return
73 | }
74 | let data = {
75 | action: message.action,
76 | toast: 'trade.' + message.action + 'Ok'
77 | }
78 | if (cb) cb(data)
79 | })
80 | }
81 | module.exports = {
82 | backtestSim,
83 | getBacktestList,
84 | getSimList,
85 | delBacktest,
86 | delSim
87 | }
--------------------------------------------------------------------------------
/extensions/xcoin/panacea/api/config.js:
--------------------------------------------------------------------------------
1 |
2 | var _ = require('lodash')
3 | , moment = require('moment')
4 | , debug = require('../../../../lib/debug')
5 |
6 | /** update config group */
7 | const updateConfig = (message, cb, s) => {
8 | Object.assign(s.options, message.data)
9 | s.options.modified = message.data
10 | if (message.data.strategy) {
11 | s.options.strategy = message.data.strategy
12 | }
13 | if (!_.isUndefined(message.data.debug)) {
14 | debug.flip()
15 | s.options.debug = debug.on
16 | }
17 | if (message.data.takerFee || message.data.makerFee) {
18 | s.exchange.initFees()
19 | }
20 | try {
21 | let newConfig = _.defaultsDeep({ modified: message.data }, s.options)
22 | // let filename = s.options.strategy.name + "_" + s.options.period + "_" + (new Date().getTime())
23 | var target = require('path').resolve(__dirname, '../../../' + s.options.conf)
24 | require('fs').writeFileSync(target, JSON.stringify(newConfig, null, 2))
25 | var target2 = require('path').resolve(__dirname, '../../../data/config/last_config.json')
26 | require('fs').writeFileSync(target2, JSON.stringify(newConfig, null, 2))
27 | // console.log('wrote config', target)
28 | if (message.restart) {
29 | console.log('\nSome Core Param changed .should restart process...'.orange)
30 | var target3 = require('path').resolve(__dirname, '../../../data/pm2/restart_' + s.options.exchange + "_" + (s.options.name || '') + '.json')
31 | require('fs').writeFileSync(target3, JSON.stringify({ event: 'updateConfig', time: moment().format('MMDD HH:mm:ss') }, null, 2))
32 | }
33 | } catch (e) {
34 | console.log('updateConfig error', e)
35 | }
36 | let data = {
37 | action: message.action,
38 | data: s.options,
39 | toast: 'trade.' + message.action + 'Ok'
40 | }
41 | if (cb) cb(data)
42 | }
43 | const updateSymbolFuture = (message, cb, s) => {
44 | if (message.data.type === 'marginMode') {
45 | s.exchange.updateMarginMode({
46 | marginType: message.data.value,
47 | product_id: message.symbol
48 | }, (err) => {
49 | if (err) return
50 | let data = {
51 | action: message.action,
52 | toast: 'trade.' + message.action + 'Ok'
53 | }
54 | if (cb) cb(data)
55 | })
56 | } else if (message.data.type === 'leverage') {
57 | s.exchange.updateLeverage({
58 | leverage: message.data.value,
59 | product_id: message.symbol
60 | }, (err) => {
61 | if (err) return
62 | let data = {
63 | action: message.action,
64 | toast: 'trade.' + message.action + 'Ok'
65 | }
66 | if (cb) cb(data)
67 | })
68 | }
69 | }
70 |
71 |
72 | module.exports = {
73 | updateConfig,
74 | updateSymbolFuture
75 | }
--------------------------------------------------------------------------------
/extensions/xcoin/panacea/api/market.js:
--------------------------------------------------------------------------------
1 | var coreFactory = require('../../../../lib/core')
2 | /**
3 | * get exchagne all products
4 | * @param {*} message
5 | * @param {*} cb
6 | * @param {*} s
7 | */
8 | const getProducts = (message, cb, s, conf, engine) => {
9 | let core = coreFactory(s, conf, engine)
10 | let pData = core.getExchangeProducts(s.options.exchange, 'USDT', 'detail')
11 | let data = {
12 | action: message.action,
13 | data: pData[0].products
14 | }
15 | if (cb) cb(data)
16 | }
17 | /**
18 | * get exchange symbols real-time price
19 | * @param {*} message
20 | * @param {*} cb
21 | * @param {*} s
22 | */
23 | const getTickers = (message, cb, s) => {
24 | s.exchange.getTickers(message.data, (err, realTickers) => {
25 | if (realTickers) {
26 | let tickers = Object.keys(realTickers).map(t => {
27 | return {
28 | symbol: realTickers[t].symbol,
29 | price: realTickers[t].close,
30 | percentage: realTickers[t].percentage,
31 | }
32 | })
33 | let data = {
34 | action: message.action,
35 | data: tickers
36 | }
37 | if (cb) cb(data)
38 | }
39 | })
40 | }
41 | /**
42 | * get exchange hot products
43 | * @param {} message
44 | * @param {*} cb
45 | */
46 | const getPickerNormal = (message, cb, s) => {
47 | let data = {
48 | action: message.action,
49 | data: require(`../../../../data/exchanges/${s.options.exchange}_hot_products.json`)
50 | }
51 | if (cb) cb(data)
52 | }
53 | /**
54 | * get exchange symbol klines
55 | * @param {*} message
56 | * @param {*} cb
57 | * @param {*} s
58 | */
59 | const getKlines = (message, cb, s) => {
60 | s.exchange.getKLines(message.data, (err, klines) => {
61 | if (err) {
62 | return
63 | }
64 | let data = {
65 | action: message.action,
66 | data: {
67 | period: message.data.period,
68 | klines
69 | }
70 | }
71 | if (cb) cb(data)
72 | })
73 | }
74 | module.exports = {
75 | getKlines,
76 | getProducts,
77 | getPickerNormal,
78 | getTickers
79 | }
--------------------------------------------------------------------------------
/extensions/xcoin/panacea/api/operation.js:
--------------------------------------------------------------------------------
1 |
2 | var coreFactory = require('../../../../lib/core')
3 | , { getInitData } = require('./status')
4 | , _ = require('lodash')
5 |
6 | , moment = require('moment')
7 | , debug = require('../../../../lib/debug')
8 | , helpers = require('../../../../lib/helpers')
9 | /**dynamic update watch list group */
10 | const addSymbol = (message, cb, s, conf, engine) => {
11 | let shouldAddSymbols = message.symbols.filter(m => s.options.symbols.every(p => p.normalized !== m))
12 | if (!shouldAddSymbols.length) return
13 | let symbols = shouldAddSymbols.map(p => helpers.objectifySelector(p))
14 | engine.initSymbols(symbols)
15 | var core = coreFactory(s, conf, engine)
16 | core.getInitKLines(() => {
17 | s.options.symbols.push(...symbols)
18 | if (s.options.symbols && s.options.symbols.length) {
19 | let i = 1
20 | s.options.symbols.forEach(symbol => {
21 | if (s.symbols[symbol.product_id]) {
22 | s.symbols[symbol.product_id].index = i
23 | i++
24 | }
25 | })
26 | let data = {
27 | action: 'init',
28 | data: getInitData(s)
29 | }
30 | if (cb) cb(data)
31 | data = {
32 | action: message.action,
33 | toast: 'trade.' + message.action + 'Ok',
34 | data: {
35 | success: true,
36 | buy: message.data.buy
37 | }
38 | }
39 | if (cb) cb(data)
40 |
41 | }
42 | }, JSON.parse(JSON.stringify(symbols)), {
43 | limit: s.options.min_periods
44 | })
45 | }
46 | const removeAllSymbol = (message, cb, s) => {
47 | while (s.options.symbols.length > 1) {
48 | let symbol = s.options.symbols.pop()
49 | delete s.symbols[symbol.product_id]
50 | }
51 | let data = {
52 | action: 'init',
53 | data: getInitData(s)
54 | }
55 | if (cb) cb(data)
56 | data = {
57 | action: message.action,
58 | toast: 'trade.' + message.action + 'Ok'
59 | }
60 | if (cb) cb(data)
61 | }
62 | const removeSymbol = (message, cb, s) => {
63 | let find = s.options.symbols.find(s => s.normalized === message.symbol)
64 | if (find) {
65 | let index = s.options.symbols.indexOf(find)
66 | s.options.symbols.splice(index, 1)
67 | delete s.symbols[find.product_id]
68 | let i = 1
69 | s.options.symbols.forEach(symbol => {
70 | if (s.symbols[symbol.product_id]) {
71 | s.symbols[symbol.product_id].index = i
72 | i++
73 | }
74 | })
75 | let data = {
76 | action: 'init',
77 | data: getInitData(s)
78 | }
79 | if (cb) cb(data)
80 | data = {
81 | action: message.action,
82 | toast: 'trade.' + message.action + 'Ok'
83 | }
84 | if (cb) cb(data)
85 | }
86 | }
87 | /** bot group */
88 | const getDemoBot = (message, cb) => {
89 | let data = {
90 | action: message.action,
91 | data: [{
92 | "name": "demoName",
93 | "des": "demoDes",
94 | "protocol": "ws",
95 | "host": "43.153.178.133",
96 | "port": "17832",
97 | "id": "bot-demo",
98 | "type": "xcoin",
99 | "isDemo": true
100 | }]
101 | }
102 | if (cb) cb(data)
103 | }
104 | const getBalance = (message, cb) => {
105 | s.exchange.getBalance({
106 | position_side: "LONG",
107 | currency: message.data.currency || s.options.symbols[0].currency,
108 | asset: message.data.asset || s.options.symbols[0].asset
109 | }, (err, balance) => {
110 | if (err) {
111 | return
112 | }
113 | if (s.options.future) {
114 | s.exchange.getBalance({
115 | position_side: "SHORT",
116 | currency: message.data.currency || 'BTC',
117 | asset: message.data.asset || 'USDt'
118 | }, (err, shortBalance) => {
119 | if (err) {
120 | return
121 | }
122 | let data = {
123 | balance,
124 | shortBalance
125 | }
126 | if (cb) cb(data)
127 | return
128 | })
129 | }
130 | else {
131 | let data = {
132 | balance
133 | }
134 | if (cb) cb(data)
135 | return
136 | }
137 | })
138 | }
139 | /** buy sell group */
140 | const buy = (message, cb, s, conf, engine) => {
141 | let find = s.options.symbols.find(s => s.product_id === message.symbol)
142 | if (find) {
143 | var core = coreFactory(s, conf, engine)
144 | core.buy(() => {
145 | let data = {
146 | action: message.action,
147 | toast: 'trade.' + message.action + 'Ok'
148 | }
149 | if (cb) cb(data)
150 | }, find, message.data.position_side, message.data.size)
151 | }
152 | }
153 | /** buy sell group */
154 | const sell = (message, cb, s, conf, engine) => {
155 | let find = s.options.symbols.find(s => s.product_id === message.symbol)
156 | if (find) {
157 | var core = coreFactory(s, conf, engine)
158 | core.sell(() => {
159 | let data = {
160 | action: message.action,
161 | toast: 'trade.' + message.action + 'Ok'
162 | }
163 | if (cb) cb(data)
164 | }, find, message.data.position_side, message.data.size)
165 | }
166 | }
167 | const sellAll = (message, cb, s, conf, engine) => {
168 | let boughtSymbols = s.options.symbols.filter((ss) => {
169 | // console.log('realTickers', s.normalized, realTickers[t].normalized, s.normalized === realTickers[t].normalized)
170 | if (s.symbols[ss.product_id] && s.symbols[ss.product_id].action && (s.symbols[ss.product_id].action === 'bought' || s.symbols[ss.product_id].action === 'partSell')) {
171 | return true
172 | }
173 | return false
174 | })
175 | var core = coreFactory(s, conf, engine)
176 | core.sellAll(() => {
177 | let data = {
178 | action: message.action,
179 | toast: 'trade.' + message.action + 'Ok'
180 | }
181 | if (cb) cb(data)
182 | }, boughtSymbols)
183 | }
184 |
185 | module.exports = {
186 | addSymbol,
187 | removeAllSymbol,
188 | removeSymbol,
189 | buy,
190 | sell,
191 | sellAll,
192 | getDemoBot,
193 | getBalance
194 | }
--------------------------------------------------------------------------------
/extensions/xcoin/panacea/api/panacea.js:
--------------------------------------------------------------------------------
1 | const checkVersion = (message, cb) => {
2 | let versionObj = require('../../../../data/panacea/version.json')
3 | function versionCompare(oldVer, newVer) {
4 | let v1s = oldVer.split('.')
5 | let v2s = newVer.split('.')
6 | let oldV = 10000 * v1s[0] + 100 * v1s[1] + parseInt(v1s[2])
7 | let newV = 10000 * v2s[0] + 100 * v2s[1] + parseInt(v2s[2])
8 | return newV > oldV
9 | }
10 | let hasNewVersion = versionCompare(message.data.version, versionObj.version)
11 | if (!hasNewVersion) return
12 | let data = {
13 | action: message.action,
14 | data: versionObj
15 | }
16 | if (cb) cb(data)
17 | }
18 | module.exports = {
19 | checkVersion
20 | }
--------------------------------------------------------------------------------
/extensions/xcoin/panacea/api/status.js:
--------------------------------------------------------------------------------
1 | var config = require("../../../../config/config-structure.json")
2 | /**
3 | * get real-time symbols data
4 | * @param {*} s
5 | * @returns
6 | */
7 | const getRefreshData = (s) => {
8 | let symbols = getSymbols(s, false)
9 | let output = {
10 | symbols,
11 | status: s.status
12 | }
13 | return output
14 | }
15 | /**
16 | * get bot init status with full symbols data and other data
17 | * @param {*} s
18 | * @returns
19 | */
20 | const getInitData = (s) => {
21 | let symbols = getSymbols(s, true)
22 | let output = {
23 | strategies: s.strategies, // all strategies list
24 | exchange: s.exchange, // bot exchange info
25 | symbols, // symbols status data
26 | options: s.options, // bot config params
27 | status: s.status, // bot status,
28 | config: config
29 | }
30 | return output
31 | }
32 | /**
33 | * get data to save to database
34 | */
35 | const getBacktestData = (s) => {
36 | let symbols = getSymbols(s, true)
37 | let output = {
38 | symbols,
39 | options: s.options,
40 | status: s.status
41 | }
42 | return output
43 | }
44 | /**
45 | * get all symbols status
46 | * @param {} s
47 | * @param {*} init //if in init mode
48 | * @returns
49 | */
50 | const getSymbols = (s, init = false) => {
51 | return Object.keys(s.symbols).map(key => {
52 | const symbol = s.symbols[key]
53 | let output = {
54 | product_id: symbol.product_id,
55 | price: (symbol.period && symbol.period.close) || '',
56 | normalized: symbol.normalized,
57 | min_size: symbol.min_size,
58 | asset: symbol.asset,
59 | currency: symbol.currency,
60 | assetCaptial: symbol.asset_amount,
61 | leverage: symbol.leverage,
62 | isolated: symbol.isolated,
63 | usdtProfit: symbol.usdtProfit,
64 | dynamicProfit: symbol.dynamicProfit,
65 | dynamicUsdtProfit: symbol.dynamicUsdtProfit,
66 | profit: symbol.profit,
67 | signal: symbol.signal,
68 | win: symbol.win,
69 | lost: symbol.lost,
70 | winLostRate: symbol.winLostRate,
71 | action: symbol.buy_order ? 'buying' : (symbol.sell_order ? 'selling' : symbol.action),
72 | inSignal: symbol.inSignal,
73 | trades: symbol.my_trades,
74 | lastTradeTime: symbol.last_trade_time
75 | }
76 | if (init) {
77 | output.klines = symbol.lookback.map(p => {
78 | return p
79 | }).reverse()
80 | }
81 | else {
82 | output.kline = symbol.period
83 | // console.log(symbol.product_id, symbol.period.close, symbol.period.strategy)
84 | }
85 | /// console.log('output', output)
86 | // console.timeEnd('getSymbolData')
87 | return output
88 | })
89 | }
90 | module.exports = {
91 | getRefreshData,
92 | getInitData,
93 | getBacktestData
94 | }
--------------------------------------------------------------------------------
/extensions/xcoin/panacea/api/strategy.js:
--------------------------------------------------------------------------------
1 | module.exports = {}
--------------------------------------------------------------------------------
/extensions/xcoin/panacea/index.js:
--------------------------------------------------------------------------------
1 | const webSocket = require('ws')
2 | , random_port = require('random-port')
3 | , helpers = require('../../../lib/helpers')
4 | , debug = require('../../../lib/debug')
5 | , apiFactory = require('./api/api')
6 | module.exports = function panacea(s, conf, engine, keyboard) {
7 | let aliveCount = 0
8 | let api = apiFactory()
9 | var wsServer = {
10 | wss: null,
11 | run: function () {
12 | if (!s.options.output.panacea.port || s.options.output.panacea.port === 0) {
13 | random_port({ from: 17000, range: 1000 }, function (port) {
14 | this.startServer(s.options.output.panacea.ip, port)
15 | })
16 | } else {
17 | this.startServer(s.options.output.panacea.ip, s.options.output.panacea.port)
18 | }
19 | },
20 | reply: function (ws, data) {
21 | debug.msg('reply ' + data.action + " " + JSON.stringify(data).length)
22 | ws.send(JSON.stringify(data))
23 | },
24 | startServer: function (ip, port) {
25 | var self = this
26 | this.wss = new webSocket.Server({ host: ip, port: port })
27 | const interval = setInterval(() => {
28 | this.wss.clients.forEach(function each(ws) {
29 | if (ws.isAlive === false) {
30 | aliveCount--
31 | return ws.terminate();
32 | }
33 | ws.isAlive = false;
34 | ws.ping();
35 | });
36 | }, 60000);
37 | this.wss.on('close', function close() {
38 | clearInterval(interval);
39 | });
40 | console.log('WebSocket running on ws://%s:%s'.green, ip, port)
41 | this.wss.on('connection', (ws) => {
42 | aliveCount++
43 | ws.isAlive = true;
44 | debug.msg('Websocket new client join '.cyan + aliveCount.toString().cyan)
45 | this.init(ws)
46 | ws.on('pong', () => {
47 | ws.isAlive = true
48 | });
49 | ws.on('message', (data) => {
50 | try {
51 | let message = JSON.parse(data)
52 | debug.msg('receive message ' + message.action)
53 | /** client user auth */
54 | if (message.action !== 'getTickers' && message.action !== 'checkVersion' && message.action !== 'getProducts' && message.action !== 'getPickerNormal') {
55 | if (!message.apiKey || message.apiKey !== conf.secret.keys.apiKey) {
56 | self.reply(ws, {
57 | action: 'none',
58 | toast: 'bot.apiKeyError'
59 | })
60 | return
61 | }
62 | }
63 | switch (message.action) {
64 | case 'init':
65 | self.init()
66 | break;
67 | case "refresh":
68 | self.refresh()
69 | break;
70 | default:
71 | api[message.action](message, (data) => {
72 | self.reply(ws, data)
73 | }, s, conf, engine, keyboard)
74 | break
75 | }
76 | } catch (e) {
77 | self.reply(ws, {
78 | action: 'error',
79 | data: e.toString()
80 | })
81 | console.log('error', e)
82 | }
83 | })
84 |
85 | })
86 | },
87 | /**
88 | * init all bot status
89 | * @param {} ws
90 | */
91 | async init(ws) {
92 | if (s.status.status === 'created') {
93 | let data = {
94 | action: 'ready'
95 | }
96 | this.reply(ws, data)
97 | while (s.status.status !== 'ready') {
98 | await helpers.sleep(3000)
99 | }
100 | }
101 | data = {
102 | action: 'init',
103 | data: api.getInitData(s)
104 | }
105 | this.reply(ws, data)
106 | s.status.status = 'work'
107 | },
108 | /**
109 | * broadcast all symbols real-time data to all client
110 | * @returns
111 | */
112 | refresh: function () {
113 | if (!this.wss) return
114 | if (s.status.status !== 'work') return
115 | this.wss.clients.forEach(client => {
116 | if (client.readyState === 1) {
117 | let data = {
118 | action: 'refresh',
119 | data: api.getRefreshData(s)
120 | }
121 | this.reply(client, data)
122 | }
123 | })
124 | }
125 | }
126 | return wsServer
127 | }
128 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "panacea-api",
3 | "version": "1.2.7",
4 | "description": "Api for Panacea",
5 | "bugs": "https://github.com/markmind/panacea-api/issues",
6 | "license": "MIT",
7 | "repository": {
8 | "type": "git",
9 | "url": "https://github.com/markmind/panacea-api.git"
10 | },
11 | "scripts": {
12 | "docs:dev": "vitepress dev docs",
13 | "docs:build": "vitepress build docs",
14 | "docs:serve": "vitepress serve docs"
15 | },
16 | "devDependencies": {
17 | "vitepress": "^1.0.0-alpha.65",
18 | "yargs": "^16.1.1"
19 | },
20 | "engines": {
21 | "node": ">=16.0.0"
22 | },
23 | "snyk": true
24 | }
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | "@algolia/autocomplete-core@1.7.4":
6 | version "1.7.4"
7 | resolved "https://registry.npmmirror.com/@algolia/autocomplete-core/-/autocomplete-core-1.7.4.tgz#85ff36b2673654a393c8c505345eaedd6eaa4f70"
8 | integrity sha512-daoLpQ3ps/VTMRZDEBfU8ixXd+amZcNJ4QSP3IERGyzqnL5Ch8uSRFt/4G8pUvW9c3o6GA4vtVv4I4lmnkdXyg==
9 | dependencies:
10 | "@algolia/autocomplete-shared" "1.7.4"
11 |
12 | "@algolia/autocomplete-preset-algolia@1.7.4":
13 | version "1.7.4"
14 | resolved "https://registry.npmmirror.com/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.7.4.tgz#610ee1d887962f230b987cba2fd6556478000bc3"
15 | integrity sha512-s37hrvLEIfcmKY8VU9LsAXgm2yfmkdHT3DnA3SgHaY93yjZ2qL57wzb5QweVkYuEBZkT2PIREvRoLXC2sxTbpQ==
16 | dependencies:
17 | "@algolia/autocomplete-shared" "1.7.4"
18 |
19 | "@algolia/autocomplete-shared@1.7.4":
20 | version "1.7.4"
21 | resolved "https://registry.npmmirror.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.7.4.tgz#78aea1140a50c4d193e1f06a13b7f12c5e2cbeea"
22 | integrity sha512-2VGCk7I9tA9Ge73Km99+Qg87w0wzW4tgUruvWAn/gfey1ZXgmxZtyIRBebk35R1O8TbK77wujVtCnpsGpRy1kg==
23 |
24 | "@algolia/cache-browser-local-storage@4.17.0":
25 | version "4.17.0"
26 | resolved "https://registry.npmmirror.com/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.17.0.tgz#4c54a9b1795dcc1cd9f9533144f7df3057984d39"
27 | integrity sha512-myRSRZDIMYB8uCkO+lb40YKiYHi0fjpWRtJpR/dgkaiBlSD0plRyB6lLOh1XIfmMcSeBOqDE7y9m8xZMrXYfyQ==
28 | dependencies:
29 | "@algolia/cache-common" "4.17.0"
30 |
31 | "@algolia/cache-common@4.17.0":
32 | version "4.17.0"
33 | resolved "https://registry.npmmirror.com/@algolia/cache-common/-/cache-common-4.17.0.tgz#bc3da15548df585b44d76c55e66b0056a2b3f917"
34 | integrity sha512-g8mXzkrcUBIPZaulAuqE7xyHhLAYAcF2xSch7d9dABheybaU3U91LjBX6eJTEB7XVhEsgK4Smi27vWtAJRhIKQ==
35 |
36 | "@algolia/cache-in-memory@4.17.0":
37 | version "4.17.0"
38 | resolved "https://registry.npmmirror.com/@algolia/cache-in-memory/-/cache-in-memory-4.17.0.tgz#eb55a92cb8eb8641903a2b23fd6d05ebdaca2010"
39 | integrity sha512-PT32ciC/xI8z919d0oknWVu3kMfTlhQn3MKxDln3pkn+yA7F7xrxSALysxquv+MhFfNAcrtQ/oVvQVBAQSHtdw==
40 | dependencies:
41 | "@algolia/cache-common" "4.17.0"
42 |
43 | "@algolia/client-account@4.17.0":
44 | version "4.17.0"
45 | resolved "https://registry.npmmirror.com/@algolia/client-account/-/client-account-4.17.0.tgz#4b13e5a8e50a06be1f3289d9db337096ebc66b73"
46 | integrity sha512-sSEHx9GA6m7wrlsSMNBGfyzlIfDT2fkz2u7jqfCCd6JEEwmxt8emGmxAU/0qBfbhRSuGvzojoLJlr83BSZAKjA==
47 | dependencies:
48 | "@algolia/client-common" "4.17.0"
49 | "@algolia/client-search" "4.17.0"
50 | "@algolia/transporter" "4.17.0"
51 |
52 | "@algolia/client-analytics@4.17.0":
53 | version "4.17.0"
54 | resolved "https://registry.npmmirror.com/@algolia/client-analytics/-/client-analytics-4.17.0.tgz#1b36ffbe913b7b4d8900bc15982ca431f47a473c"
55 | integrity sha512-84ooP8QA3mQ958hQ9wozk7hFUbAO+81CX1CjAuerxBqjKIInh1fOhXKTaku05O/GHBvcfExpPLIQuSuLYziBXQ==
56 | dependencies:
57 | "@algolia/client-common" "4.17.0"
58 | "@algolia/client-search" "4.17.0"
59 | "@algolia/requester-common" "4.17.0"
60 | "@algolia/transporter" "4.17.0"
61 |
62 | "@algolia/client-common@4.17.0":
63 | version "4.17.0"
64 | resolved "https://registry.npmmirror.com/@algolia/client-common/-/client-common-4.17.0.tgz#67fd898006e3ac359ea3e3ed61abfc26147ffa53"
65 | integrity sha512-jHMks0ZFicf8nRDn6ma8DNNsdwGgP/NKiAAL9z6rS7CymJ7L0+QqTJl3rYxRW7TmBhsUH40wqzmrG6aMIN/DrQ==
66 | dependencies:
67 | "@algolia/requester-common" "4.17.0"
68 | "@algolia/transporter" "4.17.0"
69 |
70 | "@algolia/client-personalization@4.17.0":
71 | version "4.17.0"
72 | resolved "https://registry.npmmirror.com/@algolia/client-personalization/-/client-personalization-4.17.0.tgz#428d9f4762c22856b6062bb54351eb31834db6c1"
73 | integrity sha512-RMzN4dZLIta1YuwT7QC9o+OeGz2cU6eTOlGNE/6RcUBLOU3l9tkCOdln5dPE2jp8GZXPl2yk54b2nSs1+pAjqw==
74 | dependencies:
75 | "@algolia/client-common" "4.17.0"
76 | "@algolia/requester-common" "4.17.0"
77 | "@algolia/transporter" "4.17.0"
78 |
79 | "@algolia/client-search@4.17.0":
80 | version "4.17.0"
81 | resolved "https://registry.npmmirror.com/@algolia/client-search/-/client-search-4.17.0.tgz#0053c682f5f588e006c20791c27e8bcb0aa5b53c"
82 | integrity sha512-x4P2wKrrRIXszT8gb7eWsMHNNHAJs0wE7/uqbufm4tZenAp+hwU/hq5KVsY50v+PfwM0LcDwwn/1DroujsTFoA==
83 | dependencies:
84 | "@algolia/client-common" "4.17.0"
85 | "@algolia/requester-common" "4.17.0"
86 | "@algolia/transporter" "4.17.0"
87 |
88 | "@algolia/logger-common@4.17.0":
89 | version "4.17.0"
90 | resolved "https://registry.npmmirror.com/@algolia/logger-common/-/logger-common-4.17.0.tgz#0fcea39c9485554edb4cdbfd965c5748b0b837ac"
91 | integrity sha512-DGuoZqpTmIKJFDeyAJ7M8E/LOenIjWiOsg1XJ1OqAU/eofp49JfqXxbfgctlVZVmDABIyOz8LqEoJ6ZP4DTyvw==
92 |
93 | "@algolia/logger-console@4.17.0":
94 | version "4.17.0"
95 | resolved "https://registry.npmmirror.com/@algolia/logger-console/-/logger-console-4.17.0.tgz#8ac56ef4259c4fa3eb9eb6586c7b4b4ed942e8da"
96 | integrity sha512-zMPvugQV/gbXUvWBCzihw6m7oxIKp48w37QBIUu/XqQQfxhjoOE9xyfJr1KldUt5FrYOKZJVsJaEjTsu+bIgQg==
97 | dependencies:
98 | "@algolia/logger-common" "4.17.0"
99 |
100 | "@algolia/requester-browser-xhr@4.17.0":
101 | version "4.17.0"
102 | resolved "https://registry.npmmirror.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.17.0.tgz#f52fdeeac2f3c531f00838920af33a73066a159b"
103 | integrity sha512-aSOX/smauyTkP21Pf52pJ1O2LmNFJ5iHRIzEeTh0mwBeADO4GdG94cAWDILFA9rNblq/nK3EDh3+UyHHjplZ1A==
104 | dependencies:
105 | "@algolia/requester-common" "4.17.0"
106 |
107 | "@algolia/requester-common@4.17.0":
108 | version "4.17.0"
109 | resolved "https://registry.npmmirror.com/@algolia/requester-common/-/requester-common-4.17.0.tgz#746020d2cbc829213e7cede8eef2182c7a71e32b"
110 | integrity sha512-XJjmWFEUlHu0ijvcHBoixuXfEoiRUdyzQM6YwTuB8usJNIgShua8ouFlRWF8iCeag0vZZiUm4S2WCVBPkdxFgg==
111 |
112 | "@algolia/requester-node-http@4.17.0":
113 | version "4.17.0"
114 | resolved "https://registry.npmmirror.com/@algolia/requester-node-http/-/requester-node-http-4.17.0.tgz#262276d94c25a4ec2128b1bdfb9471529528d8b9"
115 | integrity sha512-bpb/wDA1aC6WxxM8v7TsFspB7yBN3nqCGs2H1OADolQR/hiAIjAxusbuMxVbRFOdaUvAIqioIIkWvZdpYNIn8w==
116 | dependencies:
117 | "@algolia/requester-common" "4.17.0"
118 |
119 | "@algolia/transporter@4.17.0":
120 | version "4.17.0"
121 | resolved "https://registry.npmmirror.com/@algolia/transporter/-/transporter-4.17.0.tgz#6aabdbc20c475d72d83c8e6519f1191f1a51fb37"
122 | integrity sha512-6xL6H6fe+Fi0AEP3ziSgC+G04RK37iRb4uUUqVAH9WPYFI8g+LYFq6iv5HS8Cbuc5TTut+Bwj6G+dh/asdb9uA==
123 | dependencies:
124 | "@algolia/cache-common" "4.17.0"
125 | "@algolia/logger-common" "4.17.0"
126 | "@algolia/requester-common" "4.17.0"
127 |
128 | "@babel/parser@^7.16.4":
129 | version "7.21.4"
130 | resolved "https://registry.npmmirror.com/@babel/parser/-/parser-7.21.4.tgz#94003fdfc520bbe2875d4ae557b43ddb6d880f17"
131 | integrity sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==
132 |
133 | "@docsearch/css@3.3.3", "@docsearch/css@^3.3.3":
134 | version "3.3.3"
135 | resolved "https://registry.npmmirror.com/@docsearch/css/-/css-3.3.3.tgz#f9346c9e24602218341f51b8ba91eb9109add434"
136 | integrity sha512-6SCwI7P8ao+se1TUsdZ7B4XzL+gqeQZnBc+2EONZlcVa0dVrk0NjETxozFKgMv0eEGH8QzP1fkN+A1rH61l4eg==
137 |
138 | "@docsearch/js@^3.3.3":
139 | version "3.3.3"
140 | resolved "https://registry.npmmirror.com/@docsearch/js/-/js-3.3.3.tgz#70725a7a8fe92d221fcf0593263b936389d3728f"
141 | integrity sha512-2xAv2GFuHzzmG0SSZgf8wHX0qZX8n9Y1ZirKUk5Wrdc+vH9CL837x2hZIUdwcPZI9caBA+/CzxsS68O4waYjUQ==
142 | dependencies:
143 | "@docsearch/react" "3.3.3"
144 | preact "^10.0.0"
145 |
146 | "@docsearch/react@3.3.3":
147 | version "3.3.3"
148 | resolved "https://registry.npmmirror.com/@docsearch/react/-/react-3.3.3.tgz#907b6936a565f880b4c0892624b4f7a9f132d298"
149 | integrity sha512-pLa0cxnl+G0FuIDuYlW+EBK6Rw2jwLw9B1RHIeS4N4s2VhsfJ/wzeCi3CWcs5yVfxLd5ZK50t//TMA5e79YT7Q==
150 | dependencies:
151 | "@algolia/autocomplete-core" "1.7.4"
152 | "@algolia/autocomplete-preset-algolia" "1.7.4"
153 | "@docsearch/css" "3.3.3"
154 | algoliasearch "^4.0.0"
155 |
156 | "@esbuild/android-arm64@0.17.15":
157 | version "0.17.15"
158 | resolved "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.17.15.tgz#893ad71f3920ccb919e1757c387756a9bca2ef42"
159 | integrity sha512-0kOB6Y7Br3KDVgHeg8PRcvfLkq+AccreK///B4Z6fNZGr/tNHX0z2VywCc7PTeWp+bPvjA5WMvNXltHw5QjAIA==
160 |
161 | "@esbuild/android-arm@0.17.15":
162 | version "0.17.15"
163 | resolved "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.17.15.tgz#143e0d4e4c08c786ea410b9a7739779a9a1315d8"
164 | integrity sha512-sRSOVlLawAktpMvDyJIkdLI/c/kdRTOqo8t6ImVxg8yT7LQDUYV5Rp2FKeEosLr6ZCja9UjYAzyRSxGteSJPYg==
165 |
166 | "@esbuild/android-x64@0.17.15":
167 | version "0.17.15"
168 | resolved "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.17.15.tgz#d2d12a7676b2589864281b2274355200916540bc"
169 | integrity sha512-MzDqnNajQZ63YkaUWVl9uuhcWyEyh69HGpMIrf+acR4otMkfLJ4sUCxqwbCyPGicE9dVlrysI3lMcDBjGiBBcQ==
170 |
171 | "@esbuild/darwin-arm64@0.17.15":
172 | version "0.17.15"
173 | resolved "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.17.15.tgz#2e88e79f1d327a2a7d9d06397e5232eb0a473d61"
174 | integrity sha512-7siLjBc88Z4+6qkMDxPT2juf2e8SJxmsbNVKFY2ifWCDT72v5YJz9arlvBw5oB4W/e61H1+HDB/jnu8nNg0rLA==
175 |
176 | "@esbuild/darwin-x64@0.17.15":
177 | version "0.17.15"
178 | resolved "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.17.15.tgz#9384e64c0be91388c57be6d3a5eaf1c32a99c91d"
179 | integrity sha512-NbImBas2rXwYI52BOKTW342Tm3LTeVlaOQ4QPZ7XuWNKiO226DisFk/RyPk3T0CKZkKMuU69yOvlapJEmax7cg==
180 |
181 | "@esbuild/freebsd-arm64@0.17.15":
182 | version "0.17.15"
183 | resolved "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.15.tgz#2ad5a35bc52ebd9ca6b845dbc59ba39647a93c1a"
184 | integrity sha512-Xk9xMDjBVG6CfgoqlVczHAdJnCs0/oeFOspFap5NkYAmRCT2qTn1vJWA2f419iMtsHSLm+O8B6SLV/HlY5cYKg==
185 |
186 | "@esbuild/freebsd-x64@0.17.15":
187 | version "0.17.15"
188 | resolved "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.17.15.tgz#b513a48446f96c75fda5bef470e64d342d4379cd"
189 | integrity sha512-3TWAnnEOdclvb2pnfsTWtdwthPfOz7qAfcwDLcfZyGJwm1SRZIMOeB5FODVhnM93mFSPsHB9b/PmxNNbSnd0RQ==
190 |
191 | "@esbuild/linux-arm64@0.17.15":
192 | version "0.17.15"
193 | resolved "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.17.15.tgz#9697b168175bfd41fa9cc4a72dd0d48f24715f31"
194 | integrity sha512-T0MVnYw9KT6b83/SqyznTs/3Jg2ODWrZfNccg11XjDehIved2oQfrX/wVuev9N936BpMRaTR9I1J0tdGgUgpJA==
195 |
196 | "@esbuild/linux-arm@0.17.15":
197 | version "0.17.15"
198 | resolved "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.17.15.tgz#5b22062c54f48cd92fab9ffd993732a52db70cd3"
199 | integrity sha512-MLTgiXWEMAMr8nmS9Gigx43zPRmEfeBfGCwxFQEMgJ5MC53QKajaclW6XDPjwJvhbebv+RzK05TQjvH3/aM4Xw==
200 |
201 | "@esbuild/linux-ia32@0.17.15":
202 | version "0.17.15"
203 | resolved "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.17.15.tgz#eb28a13f9b60b5189fcc9e98e1024f6b657ba54c"
204 | integrity sha512-wp02sHs015T23zsQtU4Cj57WiteiuASHlD7rXjKUyAGYzlOKDAjqK6bk5dMi2QEl/KVOcsjwL36kD+WW7vJt8Q==
205 |
206 | "@esbuild/linux-loong64@0.17.15":
207 | version "0.17.15"
208 | resolved "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.17.15.tgz#32454bdfe144cf74b77895a8ad21a15cb81cfbe5"
209 | integrity sha512-k7FsUJjGGSxwnBmMh8d7IbObWu+sF/qbwc+xKZkBe/lTAF16RqxRCnNHA7QTd3oS2AfGBAnHlXL67shV5bBThQ==
210 |
211 | "@esbuild/linux-mips64el@0.17.15":
212 | version "0.17.15"
213 | resolved "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.17.15.tgz#af12bde0d775a318fad90eb13a0455229a63987c"
214 | integrity sha512-ZLWk6czDdog+Q9kE/Jfbilu24vEe/iW/Sj2d8EVsmiixQ1rM2RKH2n36qfxK4e8tVcaXkvuV3mU5zTZviE+NVQ==
215 |
216 | "@esbuild/linux-ppc64@0.17.15":
217 | version "0.17.15"
218 | resolved "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.17.15.tgz#34c5ed145b2dfc493d3e652abac8bd3baa3865a5"
219 | integrity sha512-mY6dPkIRAiFHRsGfOYZC8Q9rmr8vOBZBme0/j15zFUKM99d4ILY4WpOC7i/LqoY+RE7KaMaSfvY8CqjJtuO4xg==
220 |
221 | "@esbuild/linux-riscv64@0.17.15":
222 | version "0.17.15"
223 | resolved "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.17.15.tgz#87bd515e837f2eb004b45f9e6a94dc5b93f22b92"
224 | integrity sha512-EcyUtxffdDtWjjwIH8sKzpDRLcVtqANooMNASO59y+xmqqRYBBM7xVLQhqF7nksIbm2yHABptoioS9RAbVMWVA==
225 |
226 | "@esbuild/linux-s390x@0.17.15":
227 | version "0.17.15"
228 | resolved "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.17.15.tgz#20bf7947197f199ddac2ec412029a414ceae3aa3"
229 | integrity sha512-BuS6Jx/ezxFuHxgsfvz7T4g4YlVrmCmg7UAwboeyNNg0OzNzKsIZXpr3Sb/ZREDXWgt48RO4UQRDBxJN3B9Rbg==
230 |
231 | "@esbuild/linux-x64@0.17.15":
232 | version "0.17.15"
233 | resolved "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.17.15.tgz#31b93f9c94c195e852c20cd3d1914a68aa619124"
234 | integrity sha512-JsdS0EgEViwuKsw5tiJQo9UdQdUJYuB+Mf6HxtJSPN35vez1hlrNb1KajvKWF5Sa35j17+rW1ECEO9iNrIXbNg==
235 |
236 | "@esbuild/netbsd-x64@0.17.15":
237 | version "0.17.15"
238 | resolved "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.17.15.tgz#8da299b3ac6875836ca8cdc1925826498069ac65"
239 | integrity sha512-R6fKjtUysYGym6uXf6qyNephVUQAGtf3n2RCsOST/neIwPqRWcnc3ogcielOd6pT+J0RDR1RGcy0ZY7d3uHVLA==
240 |
241 | "@esbuild/openbsd-x64@0.17.15":
242 | version "0.17.15"
243 | resolved "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.17.15.tgz#04a1ec3d4e919714dba68dcf09eeb1228ad0d20c"
244 | integrity sha512-mVD4PGc26b8PI60QaPUltYKeSX0wxuy0AltC+WCTFwvKCq2+OgLP4+fFd+hZXzO2xW1HPKcytZBdjqL6FQFa7w==
245 |
246 | "@esbuild/sunos-x64@0.17.15":
247 | version "0.17.15"
248 | resolved "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.17.15.tgz#6694ebe4e16e5cd7dab6505ff7c28f9c1c695ce5"
249 | integrity sha512-U6tYPovOkw3459t2CBwGcFYfFRjivcJJc1WC8Q3funIwX8x4fP+R6xL/QuTPNGOblbq/EUDxj9GU+dWKX0oWlQ==
250 |
251 | "@esbuild/win32-arm64@0.17.15":
252 | version "0.17.15"
253 | resolved "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.17.15.tgz#1f95b2564193c8d1fee8f8129a0609728171d500"
254 | integrity sha512-W+Z5F++wgKAleDABemiyXVnzXgvRFs+GVKThSI+mGgleLWluv0D7Diz4oQpgdpNzh4i2nNDzQtWbjJiqutRp6Q==
255 |
256 | "@esbuild/win32-ia32@0.17.15":
257 | version "0.17.15"
258 | resolved "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.17.15.tgz#c362b88b3df21916ed7bcf75c6d09c6bf3ae354a"
259 | integrity sha512-Muz/+uGgheShKGqSVS1KsHtCyEzcdOn/W/Xbh6H91Etm+wiIfwZaBn1W58MeGtfI8WA961YMHFYTthBdQs4t+w==
260 |
261 | "@esbuild/win32-x64@0.17.15":
262 | version "0.17.15"
263 | resolved "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.17.15.tgz#c2e737f3a201ebff8e2ac2b8e9f246b397ad19b8"
264 | integrity sha512-DjDa9ywLUUmjhV2Y9wUTIF+1XsmuFGvZoCmOWkli1XcNAh5t25cc7fgsCx4Zi/Uurep3TTLyDiKATgGEg61pkA==
265 |
266 | "@types/web-bluetooth@^0.0.16":
267 | version "0.0.16"
268 | resolved "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz#1d12873a8e49567371f2a75fe3e7f7edca6662d8"
269 | integrity sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==
270 |
271 | "@vitejs/plugin-vue@^4.1.0":
272 | version "4.1.0"
273 | resolved "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-4.1.0.tgz#b6a9d83cd91575f7ee15593f6444397f68751073"
274 | integrity sha512-++9JOAFdcXI3lyer9UKUV4rfoQ3T1RN8yDqoCLar86s0xQct5yblxAE+yWgRnU5/0FOlVCpTZpYSBV/bGWrSrQ==
275 |
276 | "@vue/compiler-core@3.2.47":
277 | version "3.2.47"
278 | resolved "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.2.47.tgz#3e07c684d74897ac9aa5922c520741f3029267f8"
279 | integrity sha512-p4D7FDnQb7+YJmO2iPEv0SQNeNzcbHdGByJDsT4lynf63AFkOTFN07HsiRSvjGo0QrxR/o3d0hUyNCUnBU2Tig==
280 | dependencies:
281 | "@babel/parser" "^7.16.4"
282 | "@vue/shared" "3.2.47"
283 | estree-walker "^2.0.2"
284 | source-map "^0.6.1"
285 |
286 | "@vue/compiler-dom@3.2.47":
287 | version "3.2.47"
288 | resolved "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.2.47.tgz#a0b06caf7ef7056939e563dcaa9cbde30794f305"
289 | integrity sha512-dBBnEHEPoftUiS03a4ggEig74J2YBZ2UIeyfpcRM2tavgMWo4bsEfgCGsu+uJIL/vax9S+JztH8NmQerUo7shQ==
290 | dependencies:
291 | "@vue/compiler-core" "3.2.47"
292 | "@vue/shared" "3.2.47"
293 |
294 | "@vue/compiler-sfc@3.2.47":
295 | version "3.2.47"
296 | resolved "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.2.47.tgz#1bdc36f6cdc1643f72e2c397eb1a398f5004ad3d"
297 | integrity sha512-rog05W+2IFfxjMcFw10tM9+f7i/+FFpZJJ5XHX72NP9eC2uRD+42M3pYcQqDXVYoj74kHMSEdQ/WmCjt8JFksQ==
298 | dependencies:
299 | "@babel/parser" "^7.16.4"
300 | "@vue/compiler-core" "3.2.47"
301 | "@vue/compiler-dom" "3.2.47"
302 | "@vue/compiler-ssr" "3.2.47"
303 | "@vue/reactivity-transform" "3.2.47"
304 | "@vue/shared" "3.2.47"
305 | estree-walker "^2.0.2"
306 | magic-string "^0.25.7"
307 | postcss "^8.1.10"
308 | source-map "^0.6.1"
309 |
310 | "@vue/compiler-ssr@3.2.47":
311 | version "3.2.47"
312 | resolved "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.2.47.tgz#35872c01a273aac4d6070ab9d8da918ab13057ee"
313 | integrity sha512-wVXC+gszhulcMD8wpxMsqSOpvDZ6xKXSVWkf50Guf/S+28hTAXPDYRTbLQ3EDkOP5Xz/+SY37YiwDquKbJOgZw==
314 | dependencies:
315 | "@vue/compiler-dom" "3.2.47"
316 | "@vue/shared" "3.2.47"
317 |
318 | "@vue/devtools-api@^6.5.0":
319 | version "6.5.0"
320 | resolved "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.5.0.tgz#98b99425edee70b4c992692628fa1ea2c1e57d07"
321 | integrity sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q==
322 |
323 | "@vue/reactivity-transform@3.2.47":
324 | version "3.2.47"
325 | resolved "https://registry.npmmirror.com/@vue/reactivity-transform/-/reactivity-transform-3.2.47.tgz#e45df4d06370f8abf29081a16afd25cffba6d84e"
326 | integrity sha512-m8lGXw8rdnPVVIdIFhf0LeQ/ixyHkH5plYuS83yop5n7ggVJU+z5v0zecwEnX7fa7HNLBhh2qngJJkxpwEEmYA==
327 | dependencies:
328 | "@babel/parser" "^7.16.4"
329 | "@vue/compiler-core" "3.2.47"
330 | "@vue/shared" "3.2.47"
331 | estree-walker "^2.0.2"
332 | magic-string "^0.25.7"
333 |
334 | "@vue/reactivity@3.2.47":
335 | version "3.2.47"
336 | resolved "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.2.47.tgz#1d6399074eadfc3ed35c727e2fd707d6881140b6"
337 | integrity sha512-7khqQ/75oyyg+N/e+iwV6lpy1f5wq759NdlS1fpAhFXa8VeAIKGgk2E/C4VF59lx5b+Ezs5fpp/5WsRYXQiKxQ==
338 | dependencies:
339 | "@vue/shared" "3.2.47"
340 |
341 | "@vue/runtime-core@3.2.47":
342 | version "3.2.47"
343 | resolved "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.2.47.tgz#406ebade3d5551c00fc6409bbc1eeb10f32e121d"
344 | integrity sha512-RZxbLQIRB/K0ev0K9FXhNbBzT32H9iRtYbaXb0ZIz2usLms/D55dJR2t6cIEUn6vyhS3ALNvNthI+Q95C+NOpA==
345 | dependencies:
346 | "@vue/reactivity" "3.2.47"
347 | "@vue/shared" "3.2.47"
348 |
349 | "@vue/runtime-dom@3.2.47":
350 | version "3.2.47"
351 | resolved "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.2.47.tgz#93e760eeaeab84dedfb7c3eaf3ed58d776299382"
352 | integrity sha512-ArXrFTjS6TsDei4qwNvgrdmHtD930KgSKGhS5M+j8QxXrDJYLqYw4RRcDy1bz1m1wMmb6j+zGLifdVHtkXA7gA==
353 | dependencies:
354 | "@vue/runtime-core" "3.2.47"
355 | "@vue/shared" "3.2.47"
356 | csstype "^2.6.8"
357 |
358 | "@vue/server-renderer@3.2.47":
359 | version "3.2.47"
360 | resolved "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.2.47.tgz#8aa1d1871fc4eb5a7851aa7f741f8f700e6de3c0"
361 | integrity sha512-dN9gc1i8EvmP9RCzvneONXsKfBRgqFeFZLurmHOveL7oH6HiFXJw5OGu294n1nHc/HMgTy6LulU/tv5/A7f/LA==
362 | dependencies:
363 | "@vue/compiler-ssr" "3.2.47"
364 | "@vue/shared" "3.2.47"
365 |
366 | "@vue/shared@3.2.47":
367 | version "3.2.47"
368 | resolved "https://registry.npmmirror.com/@vue/shared/-/shared-3.2.47.tgz#e597ef75086c6e896ff5478a6bfc0a7aa4bbd14c"
369 | integrity sha512-BHGyyGN3Q97EZx0taMQ+OLNuZcW3d37ZEVmEAyeoA9ERdGvm9Irc/0Fua8SNyOtV1w6BS4q25wbMzJujO9HIfQ==
370 |
371 | "@vueuse/core@^9.13.0":
372 | version "9.13.0"
373 | resolved "https://registry.npmmirror.com/@vueuse/core/-/core-9.13.0.tgz#2f69e66d1905c1e4eebc249a01759cf88ea00cf4"
374 | integrity sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==
375 | dependencies:
376 | "@types/web-bluetooth" "^0.0.16"
377 | "@vueuse/metadata" "9.13.0"
378 | "@vueuse/shared" "9.13.0"
379 | vue-demi "*"
380 |
381 | "@vueuse/metadata@9.13.0":
382 | version "9.13.0"
383 | resolved "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-9.13.0.tgz#bc25a6cdad1b1a93c36ce30191124da6520539ff"
384 | integrity sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==
385 |
386 | "@vueuse/shared@9.13.0":
387 | version "9.13.0"
388 | resolved "https://registry.npmmirror.com/@vueuse/shared/-/shared-9.13.0.tgz#089ff4cc4e2e7a4015e57a8f32e4b39d096353b9"
389 | integrity sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==
390 | dependencies:
391 | vue-demi "*"
392 |
393 | algoliasearch@^4.0.0:
394 | version "4.17.0"
395 | resolved "https://registry.npmmirror.com/algoliasearch/-/algoliasearch-4.17.0.tgz#46ed58b2b99509d041f11cd1ea83623edf84355f"
396 | integrity sha512-JMRh2Mw6sEnVMiz6+APsi7lx9a2jiDFF+WUtANaUVCv6uSU9UOLdo5h9K3pdP6frRRybaM2fX8b1u0nqICS9aA==
397 | dependencies:
398 | "@algolia/cache-browser-local-storage" "4.17.0"
399 | "@algolia/cache-common" "4.17.0"
400 | "@algolia/cache-in-memory" "4.17.0"
401 | "@algolia/client-account" "4.17.0"
402 | "@algolia/client-analytics" "4.17.0"
403 | "@algolia/client-common" "4.17.0"
404 | "@algolia/client-personalization" "4.17.0"
405 | "@algolia/client-search" "4.17.0"
406 | "@algolia/logger-common" "4.17.0"
407 | "@algolia/logger-console" "4.17.0"
408 | "@algolia/requester-browser-xhr" "4.17.0"
409 | "@algolia/requester-common" "4.17.0"
410 | "@algolia/requester-node-http" "4.17.0"
411 | "@algolia/transporter" "4.17.0"
412 |
413 | ansi-regex@^5.0.1:
414 | version "5.0.1"
415 | resolved "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
416 | integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
417 |
418 | ansi-sequence-parser@^1.1.0:
419 | version "1.1.0"
420 | resolved "https://registry.npmmirror.com/ansi-sequence-parser/-/ansi-sequence-parser-1.1.0.tgz#4d790f31236ac20366b23b3916b789e1bde39aed"
421 | integrity sha512-lEm8mt52to2fT8GhciPCGeCXACSz2UwIN4X2e2LJSnZ5uAbn2/dsYdOmUXq0AtWS5cpAupysIneExOgH0Vd2TQ==
422 |
423 | ansi-styles@^4.0.0:
424 | version "4.3.0"
425 | resolved "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
426 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
427 | dependencies:
428 | color-convert "^2.0.1"
429 |
430 | body-scroll-lock@4.0.0-beta.0:
431 | version "4.0.0-beta.0"
432 | resolved "https://registry.npmmirror.com/body-scroll-lock/-/body-scroll-lock-4.0.0-beta.0.tgz#4f78789d10e6388115c0460cd6d7d4dd2bbc4f7e"
433 | integrity sha512-a7tP5+0Mw3YlUJcGAKUqIBkYYGlYxk2fnCasq/FUph1hadxlTRjF+gAcZksxANnaMnALjxEddmSi/H3OR8ugcQ==
434 |
435 | cliui@^7.0.2:
436 | version "7.0.4"
437 | resolved "https://registry.npmmirror.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
438 | integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==
439 | dependencies:
440 | string-width "^4.2.0"
441 | strip-ansi "^6.0.0"
442 | wrap-ansi "^7.0.0"
443 |
444 | color-convert@^2.0.1:
445 | version "2.0.1"
446 | resolved "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
447 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
448 | dependencies:
449 | color-name "~1.1.4"
450 |
451 | color-name@~1.1.4:
452 | version "1.1.4"
453 | resolved "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
454 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
455 |
456 | csstype@^2.6.8:
457 | version "2.6.21"
458 | resolved "https://registry.npmmirror.com/csstype/-/csstype-2.6.21.tgz#2efb85b7cc55c80017c66a5ad7cbd931fda3a90e"
459 | integrity sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==
460 |
461 | emoji-regex@^8.0.0:
462 | version "8.0.0"
463 | resolved "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
464 | integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
465 |
466 | esbuild@^0.17.5:
467 | version "0.17.15"
468 | resolved "https://registry.npmmirror.com/esbuild/-/esbuild-0.17.15.tgz#209ebc87cb671ffb79574db93494b10ffaf43cbc"
469 | integrity sha512-LBUV2VsUIc/iD9ME75qhT4aJj0r75abCVS0jakhFzOtR7TQsqQA5w0tZ+KTKnwl3kXE0MhskNdHDh/I5aCR1Zw==
470 | optionalDependencies:
471 | "@esbuild/android-arm" "0.17.15"
472 | "@esbuild/android-arm64" "0.17.15"
473 | "@esbuild/android-x64" "0.17.15"
474 | "@esbuild/darwin-arm64" "0.17.15"
475 | "@esbuild/darwin-x64" "0.17.15"
476 | "@esbuild/freebsd-arm64" "0.17.15"
477 | "@esbuild/freebsd-x64" "0.17.15"
478 | "@esbuild/linux-arm" "0.17.15"
479 | "@esbuild/linux-arm64" "0.17.15"
480 | "@esbuild/linux-ia32" "0.17.15"
481 | "@esbuild/linux-loong64" "0.17.15"
482 | "@esbuild/linux-mips64el" "0.17.15"
483 | "@esbuild/linux-ppc64" "0.17.15"
484 | "@esbuild/linux-riscv64" "0.17.15"
485 | "@esbuild/linux-s390x" "0.17.15"
486 | "@esbuild/linux-x64" "0.17.15"
487 | "@esbuild/netbsd-x64" "0.17.15"
488 | "@esbuild/openbsd-x64" "0.17.15"
489 | "@esbuild/sunos-x64" "0.17.15"
490 | "@esbuild/win32-arm64" "0.17.15"
491 | "@esbuild/win32-ia32" "0.17.15"
492 | "@esbuild/win32-x64" "0.17.15"
493 |
494 | escalade@^3.1.1:
495 | version "3.1.1"
496 | resolved "https://registry.npmmirror.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
497 | integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
498 |
499 | estree-walker@^2.0.2:
500 | version "2.0.2"
501 | resolved "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac"
502 | integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==
503 |
504 | fsevents@~2.3.2:
505 | version "2.3.2"
506 | resolved "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
507 | integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
508 |
509 | function-bind@^1.1.1:
510 | version "1.1.1"
511 | resolved "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
512 | integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
513 |
514 | get-caller-file@^2.0.5:
515 | version "2.0.5"
516 | resolved "https://registry.npmmirror.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
517 | integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
518 |
519 | has@^1.0.3:
520 | version "1.0.3"
521 | resolved "https://registry.npmmirror.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
522 | integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
523 | dependencies:
524 | function-bind "^1.1.1"
525 |
526 | is-core-module@^2.11.0:
527 | version "2.11.0"
528 | resolved "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144"
529 | integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==
530 | dependencies:
531 | has "^1.0.3"
532 |
533 | is-fullwidth-code-point@^3.0.0:
534 | version "3.0.0"
535 | resolved "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
536 | integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
537 |
538 | jsonc-parser@^3.2.0:
539 | version "3.2.0"
540 | resolved "https://registry.npmmirror.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76"
541 | integrity sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==
542 |
543 | magic-string@^0.25.7:
544 | version "0.25.9"
545 | resolved "https://registry.npmmirror.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c"
546 | integrity sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==
547 | dependencies:
548 | sourcemap-codec "^1.4.8"
549 |
550 | nanoid@^3.3.4:
551 | version "3.3.6"
552 | resolved "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c"
553 | integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==
554 |
555 | path-parse@^1.0.7:
556 | version "1.0.7"
557 | resolved "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
558 | integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
559 |
560 | picocolors@^1.0.0:
561 | version "1.0.0"
562 | resolved "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
563 | integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
564 |
565 | postcss@^8.1.10, postcss@^8.4.21:
566 | version "8.4.21"
567 | resolved "https://registry.npmmirror.com/postcss/-/postcss-8.4.21.tgz#c639b719a57efc3187b13a1d765675485f4134f4"
568 | integrity sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==
569 | dependencies:
570 | nanoid "^3.3.4"
571 | picocolors "^1.0.0"
572 | source-map-js "^1.0.2"
573 |
574 | preact@^10.0.0:
575 | version "10.13.2"
576 | resolved "https://registry.npmmirror.com/preact/-/preact-10.13.2.tgz#2c40c73d57248b57234c4ae6cd9ab9d8186ebc0a"
577 | integrity sha512-q44QFLhOhty2Bd0Y46fnYW0gD/cbVM9dUVtNTDKPcdXSMA7jfY+Jpd6rk3GB0lcQss0z5s/6CmVP0Z/hV+g6pw==
578 |
579 | require-directory@^2.1.1:
580 | version "2.1.1"
581 | resolved "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
582 | integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==
583 |
584 | resolve@^1.22.1:
585 | version "1.22.2"
586 | resolved "https://registry.npmmirror.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f"
587 | integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==
588 | dependencies:
589 | is-core-module "^2.11.0"
590 | path-parse "^1.0.7"
591 | supports-preserve-symlinks-flag "^1.0.0"
592 |
593 | rollup@^3.18.0:
594 | version "3.20.2"
595 | resolved "https://registry.npmmirror.com/rollup/-/rollup-3.20.2.tgz#f798c600317f216de2e4ad9f4d9ab30a89b690ff"
596 | integrity sha512-3zwkBQl7Ai7MFYQE0y1MeQ15+9jsi7XxfrqwTb/9EK8D9C9+//EBR4M+CuA1KODRaNbFez/lWxA5vhEGZp4MUg==
597 | optionalDependencies:
598 | fsevents "~2.3.2"
599 |
600 | shiki@^0.14.1:
601 | version "0.14.1"
602 | resolved "https://registry.npmmirror.com/shiki/-/shiki-0.14.1.tgz#9fbe082d0a8aa2ad63df4fbf2ee11ec924aa7ee1"
603 | integrity sha512-+Jz4nBkCBe0mEDqo1eKRcCdjRtrCjozmcbTUjbPTX7OOJfEbTZzlUWlZtGe3Gb5oV1/jnojhG//YZc3rs9zSEw==
604 | dependencies:
605 | ansi-sequence-parser "^1.1.0"
606 | jsonc-parser "^3.2.0"
607 | vscode-oniguruma "^1.7.0"
608 | vscode-textmate "^8.0.0"
609 |
610 | source-map-js@^1.0.2:
611 | version "1.0.2"
612 | resolved "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
613 | integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
614 |
615 | source-map@^0.6.1:
616 | version "0.6.1"
617 | resolved "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
618 | integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
619 |
620 | sourcemap-codec@^1.4.8:
621 | version "1.4.8"
622 | resolved "https://registry.npmmirror.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
623 | integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==
624 |
625 | string-width@^4.1.0, string-width@^4.2.0:
626 | version "4.2.3"
627 | resolved "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
628 | integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
629 | dependencies:
630 | emoji-regex "^8.0.0"
631 | is-fullwidth-code-point "^3.0.0"
632 | strip-ansi "^6.0.1"
633 |
634 | strip-ansi@^6.0.0, strip-ansi@^6.0.1:
635 | version "6.0.1"
636 | resolved "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
637 | integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
638 | dependencies:
639 | ansi-regex "^5.0.1"
640 |
641 | supports-preserve-symlinks-flag@^1.0.0:
642 | version "1.0.0"
643 | resolved "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
644 | integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
645 |
646 | vite@^4.2.1:
647 | version "4.2.1"
648 | resolved "https://registry.npmmirror.com/vite/-/vite-4.2.1.tgz#6c2eb337b0dfd80a9ded5922163b94949d7fc254"
649 | integrity sha512-7MKhqdy0ISo4wnvwtqZkjke6XN4taqQ2TBaTccLIpOKv7Vp2h4Y+NpmWCnGDeSvvn45KxvWgGyb0MkHvY1vgbg==
650 | dependencies:
651 | esbuild "^0.17.5"
652 | postcss "^8.4.21"
653 | resolve "^1.22.1"
654 | rollup "^3.18.0"
655 | optionalDependencies:
656 | fsevents "~2.3.2"
657 |
658 | vitepress@^1.0.0-alpha.65:
659 | version "1.0.0-alpha.65"
660 | resolved "https://registry.npmmirror.com/vitepress/-/vitepress-1.0.0-alpha.65.tgz#785268010d3bd1cabeb18011e68d512c9f1d4e0e"
661 | integrity sha512-iGWC0AQC6WrfRZTJf5+TiGG4o8PLhqIJNyai8NVxZCY9YpmMJhddvQeqqjJdQniF/LQK/hQ5nQZ9HgSZDGRPGQ==
662 | dependencies:
663 | "@docsearch/css" "^3.3.3"
664 | "@docsearch/js" "^3.3.3"
665 | "@vitejs/plugin-vue" "^4.1.0"
666 | "@vue/devtools-api" "^6.5.0"
667 | "@vueuse/core" "^9.13.0"
668 | body-scroll-lock "4.0.0-beta.0"
669 | shiki "^0.14.1"
670 | vite "^4.2.1"
671 | vue "^3.2.47"
672 |
673 | vscode-oniguruma@^1.7.0:
674 | version "1.7.0"
675 | resolved "https://registry.npmmirror.com/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz#439bfad8fe71abd7798338d1cd3dc53a8beea94b"
676 | integrity sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==
677 |
678 | vscode-textmate@^8.0.0:
679 | version "8.0.0"
680 | resolved "https://registry.npmmirror.com/vscode-textmate/-/vscode-textmate-8.0.0.tgz#2c7a3b1163ef0441097e0b5d6389cd5504b59e5d"
681 | integrity sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==
682 |
683 | vue-demi@*:
684 | version "0.13.11"
685 | resolved "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.13.11.tgz#7d90369bdae8974d87b1973564ad390182410d99"
686 | integrity sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==
687 |
688 | vue@^3.2.47:
689 | version "3.2.47"
690 | resolved "https://registry.npmmirror.com/vue/-/vue-3.2.47.tgz#3eb736cbc606fc87038dbba6a154707c8a34cff0"
691 | integrity sha512-60188y/9Dc9WVrAZeUVSDxRQOZ+z+y5nO2ts9jWXSTkMvayiWxCWOWtBQoYjLeccfXkiiPZWAHcV+WTPhkqJHQ==
692 | dependencies:
693 | "@vue/compiler-dom" "3.2.47"
694 | "@vue/compiler-sfc" "3.2.47"
695 | "@vue/runtime-dom" "3.2.47"
696 | "@vue/server-renderer" "3.2.47"
697 | "@vue/shared" "3.2.47"
698 |
699 | wrap-ansi@^7.0.0:
700 | version "7.0.0"
701 | resolved "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
702 | integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
703 | dependencies:
704 | ansi-styles "^4.0.0"
705 | string-width "^4.1.0"
706 | strip-ansi "^6.0.0"
707 |
708 | y18n@^5.0.5:
709 | version "5.0.8"
710 | resolved "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
711 | integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
712 |
713 | yargs-parser@^20.2.2:
714 | version "20.2.9"
715 | resolved "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
716 | integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==
717 |
718 | yargs@^16.1.1:
719 | version "16.2.0"
720 | resolved "https://registry.npmmirror.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66"
721 | integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==
722 | dependencies:
723 | cliui "^7.0.2"
724 | escalade "^3.1.1"
725 | get-caller-file "^2.0.5"
726 | require-directory "^2.1.1"
727 | string-width "^4.2.0"
728 | y18n "^5.0.5"
729 | yargs-parser "^20.2.2"
730 |
--------------------------------------------------------------------------------