Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
04848d6
feat(dev): task #11
endless-bot May 8, 2026
4609f73
feat(final): task #11
endless-bot May 8, 2026
d8c737e
Merge branch 'main' into endless/task-11
hogan-yuan May 8, 2026
a7c6d08
feat(sdk-docs): sync docs with openapi commit d7c2f6e
hogan-yuan May 9, 2026
75a0bc5
fix(build): resolve OOM and mark.js ESM issues
hogan-yuan May 9, 2026
5832d8e
fix(autocorrect): add spaces around dash in trading_stats
hogan-yuan May 10, 2026
86e0ed1
fix(config): remove local-only superpowers exclude from srcExclude
hogan-yuan May 10, 2026
a92b386
chore: remove .temp from tracking and add to gitignore
hogan-yuan May 10, 2026
5a0fd53
chore(build): increase Node.js heap limit to 10GB
hogan-yuan May 10, 2026
b1d2248
fix(ssr): guard document access in PlatformStats with onMounted
hogan-yuan May 10, 2026
29f226c
docs(sdk): validate and fix response schemas from live API calls
hogan-yuan May 11, 2026
4acc86a
fix(autocorrect): add space in 标普 500 ETF in list_dca example
hogan-yuan May 11, 2026
6c12189
docs(sdk): fix schemas based on live Python SDK calls
hogan-yuan May 11, 2026
3318ede
docs(sdk): fix financial_report and profit_analysis_detail schemas
hogan-yuan May 11, 2026
c38c370
docs(sdk): fill empty-list schemas from .pyi type annotations
hogan-yuan May 11, 2026
f0fcf79
docs(sdk): fix schemas from additional SDK calls
hogan-yuan May 11, 2026
925e690
fix(docs): correct start/end type to integer in profit_analysis_detai…
hogan-yuan May 11, 2026
6e8c5d2
docs(sdk): complete write-op and empty-list schemas from demo account
hogan-yuan May 11, 2026
b9fa284
fix(docs): resolve disable/enable alert errors; add sequence to sdk r…
hogan-yuan May 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,5 @@ jobs:
- name: Build for canary
run: |
bun run build:canary
env:
NODE_OPTIONS: --max-old-space-size=10240 --expose-gc
1 change: 1 addition & 0 deletions .github/workflows/canary.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ jobs:
run: bun run build:canary
env:
VITE_PORTAL_GATEWAY_BASE_URL: 'https://m.longbridge.xyz'
NODE_OPTIONS: --max-old-space-size=10240 --expose-gc

- name: Upload to Aliyun OSS
run: |
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,4 @@ docs/superpowers

# generated at build time by fetch-mcp-tools plugin
docs/.vitepress/data/mcp-tools.json
docs/.vitepress/.temp/
24 changes: 23 additions & 1 deletion docs/.vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export default defineConfig(
metaChunk: true,
ignoreDeadLinks: true,
base: '/',
buildConcurrency: 10,

srcExclude: ['README.md', ...regionSrcExclude],
rewrites: rewriteMarkdownPath,
Expand Down Expand Up @@ -180,7 +181,7 @@ export default defineConfig(

vite: {
ssr: {
noExternal: ['vue-i18n'],
noExternal: ['vue-i18n', 'mark.js'],
},
server: {
port: 8000,
Expand All @@ -203,6 +204,18 @@ export default defineConfig(
},
build: {
chunkSizeWarningLimit: 1000,
rollupOptions: {
output: {
manualChunks(id) {
if (id.includes('node_modules')) {
if (id.includes('shiki') || id.includes('shikiji')) return 'shiki'
if (id.includes('@vue') || id.includes('vue-demi')) return 'vue-vendor'
if (id.includes('unocss') || id.includes('@unocss')) return 'unocss'
return 'vendor'
}
},
},
},
},
resolve: {
alias: [
Expand All @@ -217,6 +230,15 @@ export default defineConfig(
],
},
plugins: [
{
name: 'gc-between-bundles',
buildEnd() {
if (typeof global.gc === 'function') {
global.gc()
console.log('✓ GC triggered after bundle')
}
},
},
{
name: 'yaml-transform',
transform(src: string, id: string) {
Expand Down
24 changes: 14 additions & 10 deletions docs/.vitepress/theme/components/NewHomePage/PlatformStats.vue
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
<script setup lang="ts">
import { computed } from 'vue'
import { computed, ref, onMounted } from 'vue'
import { useI18n } from 'vue-i18n'
import NumberTicker from '../inspira/NumberTicker.vue'

const { t } = useI18n()

// Logo-inspired stat colors: teal, yellow/gold, orange, dark
let statColors = ['#00b8b8', '#d4a800', '#c34607', '#505050']
if (document.querySelector('html')?.classList.contains('dark')) {
statColors = ['#00dbb6', '#ffe000', '#fc5200', '#AAAAAA']
}
const lightColors = ['#00b8b8', '#d4a800', '#c34607', '#505050']
const darkColors = ['#00dbb6', '#ffe000', '#fc5200', '#AAAAAA']
const statColors = ref(lightColors)

onMounted(() => {
if (document.querySelector('html')?.classList.contains('dark')) {
statColors.value = darkColors
}
})

const stats = computed(() => [
{
value: 4,
label: t('stats.ainative'),
suffix: '+',
link: '/docs/mcp',
color: statColors[0],
color: statColors.value[0],
card: {
title: t('stats.ainative'),
items: [
Expand Down Expand Up @@ -53,7 +57,7 @@ const stats = computed(() => [
label: t('stats.markets'),
suffix: '+',
link: '/docs/',
color: statColors[1],
color: statColors.value[1],
card: {
title: t('stats.markets'),
items: [
Expand Down Expand Up @@ -85,7 +89,7 @@ const stats = computed(() => [
label: t('stats.sdks'),
suffix: '+',
link: '/sdk',
color: statColors[2],
color: statColors.value[2],
card: {
title: t('stats.sdks'),
items: [
Expand Down Expand Up @@ -127,7 +131,7 @@ const stats = computed(() => [
label: t('stats.endpoints'),
suffix: '+',
link: '/docs/api',
color: statColors[3],
color: statColors.value[3],
card: {
title: t('stats.endpoints'),
items: [
Expand Down
8 changes: 8 additions & 0 deletions docs/en/docs/account/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"position": 6,
"label": "Account",
"collapsible": true,
"collapsed": true,
"link": null,
"icon": "briefcase"
}
7 changes: 7 additions & 0 deletions docs/en/docs/account/alert/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"position": 2,
"label": "Alerts",
"collapsible": true,
"collapsed": true,
"link": null
}
232 changes: 232 additions & 0 deletions docs/en/docs/account/alert/create_alert.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
---
slug: create-alert
title: Create Alert
sidebar_position: 2
language_tabs: false
toc_footers: []
includes: []
search: true
highlight_theme: ''
headingLevel: 2
---

Create a new price alert for a security when it rises above or falls below a target price.

<CliCommand>
longbridge alert add TSLA.US --price 300 --direction rise
longbridge alert add AAPL.US --price 150 --direction fall
</CliCommand>

<SDKLinks module="alert" klass="AlertContext" method="create_alert" />

## Request

<table className="http-basic">
<tbody>
<tr><td className="http-basic-key">HTTP Method</td><td>POST</td></tr>
<tr><td className="http-basic-key">HTTP URL</td><td>/v1/account/alerts</td></tr>
</tbody>
</table>

### Parameters

> Content-Type: application/json; charset=utf-8

| Name | Type | Required | Description |
| ---- | ---- | -------- | ----------- |
| symbol | string | YES | Security symbol, e.g. `TSLA.US` |
| price | string | YES | Target price |
| direction | string | YES | Alert direction: `rise` or `fall` |
| frequency | string | NO | Trigger frequency: `once` (default) or `every` |

### Request Example

<Tabs groupId="request-example">
<TabItem value="python" label="Python">

```python
from longbridge.openapi import AlertContext, Config, OAuthBuilder

oauth = OAuthBuilder("your-client-id").build(lambda url: print("Visit:", url))
config = Config.from_oauth(oauth)
ctx = AlertContext(config)

resp = ctx.create_alert()
print(resp)
```

</TabItem>
<TabItem value="python-async" label="Python (async)">

```python
import asyncio
from longbridge.openapi import AsyncAlertContext, Config, OAuthBuilder

async def main() -> None:
oauth = await OAuthBuilder("your-client-id").build_async(lambda url: print("Visit:", url))
config = Config.from_oauth(oauth)
ctx = AsyncAlertContext.create(config)

resp = await ctx.create_alert()
print(resp)

if __name__ == "__main__":
asyncio.run(main())
```

</TabItem>
<TabItem value="nodejs" label="Node.js">

```javascript
const { Config, AlertContext, OAuth } = require('longbridge')

async function main() {
const oauth = await OAuth.build('your-client-id', (_, url) => {
console.log('Open this URL to authorize: ' + url)
})
const config = Config.fromOAuth(oauth)
const ctx = AlertContext.new(config)
const resp = await ctx.create_alert()
console.log(resp)
}
main().catch(console.error)
```

</TabItem>
<TabItem value="java" label="Java">

```java
import com.longbridge.*;
import com.longbridge.alert.*;

class Main {
public static void main(String[] args) throws Exception {
try (OAuth oauth = new OAuthBuilder("your-client-id").build(url -> System.out.println("Open to authorize: " + url)).get();
Config config = Config.fromOAuth(oauth);
AlertContext ctx = AlertContext.create(config)) {
var resp = ctx.getCreateAlert().get();
System.out.println(resp);
}
}
}
```

</TabItem>
<TabItem value="rust" label="Rust">

```rust
use std::sync::Arc;
use longbridge::{oauth::OAuthBuilder, alert::AlertContext, Config};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let oauth = OAuthBuilder::new("your-client-id").build(|url| println!("Open: {url}")).await?;
let config = Arc::new(Config::from_oauth(oauth));
let ctx = AlertContext::new(config);
let resp = ctx.create_alert().await?;
println!("{:?}", resp);
Ok(())
}
```

</TabItem>
<TabItem value="cpp" label="C++">

```cpp
#include <iostream>
#include <longbridge.hpp>

using namespace longbridge;
using namespace longbridge::alert;

int main() {
OAuthBuilder("your-client-id").build(
[](const std::string& url) { std::cout << "Open: " << url << std::endl; },
[](auto res) {
if (!res) return;
Config config = Config::from_oauth(*res);
AlertContext ctx = AlertContext::create(config);
ctx.create_alert([](auto resp) {
if (resp) std::cout << "OK" << std::endl;
});
});
std::cin.get();
}
```

</TabItem>
<TabItem value="go" label="Go">

```go
package main

import (
"context"
"fmt"
"log"

"github.com/longbridge/openapi-go/config"
"github.com/longbridge/openapi-go/oauth"
"github.com/longbridge/openapi-go/alert"
)

func main() {
o := oauth.New("your-client-id").
OnOpenURL(func(url string) { fmt.Println("Open this URL to authorize:", url) })
if err := o.Build(context.Background()); err != nil {
log.Fatal(err)
}
conf, err := config.New(config.WithOAuthClient(o))
if err != nil {
log.Fatal(err)
}
c, err := alert.NewFromCfg(conf)
if err != nil {
log.Fatal(err)
}
defer c.Close()
resp, err := c.CreateAlert(context.Background())
if err != nil {
log.Fatal(err)
}
fmt.Printf("%+v\n", resp)
}
```

</TabItem>
</Tabs>

## Response

### Response Headers

- Content-Type: application/json

### Response Example

```json
{
"code": 0,
"message": "success",
"data": {
"id": 486469
}
}
```

### Response Status

| Status | Description | Schema |
| ------ | ----------- | ------ |
| 200 | Success | [CreateAlertResponse](#CreateAlertResponse) |
| 400 | Bad request | None |

## Schemas

### CreateAlertResponse

<a id="CreateAlertResponse"></a>

| Name | Type | Required | Description |
| ---- | ---- | -------- | ----------- |
| id | int64 | true | ID of the newly created alert |
Loading
Loading