OS
优宽量化交易平台支持文件读写操作,os库提供了完整的文件系统操作接口,帮助用户在策略开发中进行数据持久化、配置管理和日志记录等操作。
需要注意的是,该功能仅支持JavaScript语言策略。
os库支持:文件对象、文件列表对象、文件信息对象。
| 对象 | 说明 | 备注 |
|---|---|---|
| 文件对象:File | 提供文件读写、定位等操作。 | 通过os.open()获取,使用完毕需调用close()释放资源。 |
| 文件列表对象:ListFilesResult | 用于记录目录列表信息。 | 支持通配符匹配模式,由os.listFiles()函数返回。 |
| 文件信息对象:FileStat | 文件统计信息。 | 由os.stat()函数返回。 |
支持实盘、回测系统。
- 实盘环境:
实盘默认目录为托管者目录下实盘数据库文件同级目录的files文件夹中,即:/logs/storage/xxx/files,其中xxx为实盘Id,托管者程序(robot)与logs在同一级目录。 - 回测系统环境:
回测系统是一个沙盒环境,系统模拟一个文件目录,默认目录为:/logs/storage/1/files。
当回测结束时,创建的文件内容将被清除。
os
os库为优宽量化交易平台提供完整的文件系统操作接口。
open
以指定模式打开文件。
open(filename)
open(filename, mode)示例
创建文件,写入数据后再读取。
javascript
function main() {
let fileHandle = os.open("output.txt", "w+")
if (!fileHandle) {
Log("Failed to open file")
return
}
let bytesWritten = fileHandle.write("Hello YouQuant!")
Log("Bytes written:", bytesWritten) // Bytes written: 15
fileHandle.seek(0, 0)
let fileContent = fileHandle.read()
Log("File content read:", fileContent) // File content read: Hello YouQuant!
fileHandle.close()
}返回值
| 类型 | 描述 |
|
|
参数
| 名称 | 类型 | 必填 | 描述 |
filename | string | 是 | 文件名称。参数 |
mode | string | 否 | 指定文件的打开模式。 |
参考
File ListFilesResult FileStat open fgets fputs mmap getRootDir listFiles exists remove mkdir rmdir rename stat exit
备注
文件打开模式:
-
r: read(只读,文件必须存在) -
w: write(只写,文件不存在则创建,存在则清空内容) -
a: append(追加写入,文件不存在则创建,存在则写入到末尾) -
+: 在 r/w/a 后加 + 表示既可以读也可以写(例如 "r+", "w+", "a+") -
b: binary(二进制模式,常用于 Windows 区分文本/二进制文件,例如 "rb", "wb")
文件的打开/创建位于实盘数据库文件目录(xxx.db3,其中xxx为实盘Id)下的files文件夹中。
fgets
一次性读取整个文件的内容。
fgets(filename)示例
读取配置文件的内容。
javascript
function main() {
// 先创建、写入文件
// let fileHandle = os.open("config.json", "w+")
// if (!fileHandle) {
// Log("Failed to open file")
// return
// }
// let objJson = {"name": "tom", "age": 18}
// fileHandle.write(JSON.stringify(objJson))
// fileHandle.close()
let content = os.fgets("config.json")
Log("Config content:", content) // Config content: {"name":"tom","age":18}
}返回值
| 类型 | 描述 |
string | 返回文件的完整内容。 |
参数
| 名称 | 类型 | 必填 | 描述 |
filename | string | 是 | 文件路径,包含要读取的文件名。 |
参考
File ListFilesResult FileStat open fgets fputs mmap getRootDir listFiles exists remove mkdir rmdir rename stat exit
备注
适用于小文件的快速读取,将整个文件内容一次性加载到内存中。
如果文件不存在,fgets()函数会抛出错误:InternalError: failed to open file: openat config.json: no such file or directory at main。
fputs
向文件写入内容。
fputs(filename, content)
fputs(filename, content, append)示例
保存策略配置到文件。
javascript
function main() {
let config = '{"strategy": "MA", "period": 20}'
let bytesWritten = os.fputs("strategy_config.json", config)
Log("Bytes written:", bytesWritten) // Bytes written: 32
Log(`os.fgets("strategy_config.json"):`, os.fgets("strategy_config.json")) // os.fgets("strategy_config.json"): {"strategy": "MA", "period": 20}
// 追加日志信息
let logInfo = "\n[" + new Date().toISOString() + "] Config saved"
os.fputs("strategy_config.json", logInfo, true)
Log(`os.fgets("strategy_config.json"):`, os.fgets("strategy_config.json")) // os.fgets("strategy_config.json"): {"strategy": "MA", "period": 20} [2025-09-08T07:20:30.563Z] Config saved
}返回值
| 类型 | 描述 |
number | 返回实际写入的字节数。 |
参数
| 名称 | 类型 | 必填 | 描述 |
filename | string | 是 | 文件路径。 |
content | string | 是 | 要写入的内容。 |
append | bool | 否 | 是否以追加模式写入,默认为 false(覆盖模式)。 |
参考
File ListFilesResult FileStat open fgets fputs mmap getRootDir listFiles exists remove mkdir rmdir rename stat exit
备注
便捷的文件写入方法,默认覆盖文件内容。设置 append 为 true 可追加到文件末尾。
mmap
内存映射文件,返回文件的二进制数据。
mmap(filename)示例
映射文件的二进制数据。
javascript
function ab2str(buf) {
let arr = new Uint8Array(buf)
return String.fromCharCode.apply(null, arr)
}
function main() {
let buffer = os.mmap("strategyConfig/testData.txt")
Log("File size in bytes:", buffer.byteLength)
let arr = Array.from(new Uint8Array(buffer))
Log("arr:", arr)
Log("ab2str(buffer):", ab2str(buffer)) // ab2str(buffer): Hello YouQuant!
}返回值
| 类型 | 描述 |
ArrayBuffer | 返回文件内容的二进制数据。 |
参数
| 名称 | 类型 | 必填 | 描述 |
filename | string | 是 | 文件路径。 |
参考
File ListFilesResult FileStat open fgets fputs mmap getRootDir listFiles exists remove mkdir rmdir rename stat exit
备注
适用于大文件的高效读取和处理,将文件映射到内存中并以ArrayBuffer形式返回。
getRootDir
获取文件操作的根目录路径。
getRootDir()示例
获取并显示根目录路径。
javascript
function main() {
let rootDir = os.getRootDir()
Log("Root directory:", rootDir)
}返回值
| 类型 | 描述 |
string | 返回根目录的路径。 |
参考
listFiles
列出指定目录中的文件和子目录。
listFiles()
listFiles(pattern)示例
列出匹配的文件和目录。
javascript
function main() {
// 列出所有json文件
let result = os.listFiles("*.json")
Log("result:", result)
// 列出所有内容
let allFiles = os.listFiles()
Log("allFiles:", allFiles)
}返回值
| 类型 | 描述 |
ListFilesResult 对象 | 返回包含 - files:匹配到的文件名数组。 - dirs:当前目录下的子目录名数组。 |
参数
| 名称 | 类型 | 必填 | 描述 |
pattern | string | 否 | 可选的匹配模式,支持通配符(如 .txt、data_.json),可以指定目录路径。 |
参考
File ListFilesResult FileStat open fgets fputs mmap getRootDir listFiles exists remove mkdir rmdir rename stat exit
备注
不指定 pattern 参数时,列出当前目录(../files)下的所有文件和子目录。
exists
检查文件或目录是否存在。
exists(filename)示例
检查文件或路径是否存在。
javascript
function main() {
Log(`os.exists("./strategyConfig"):`, os.exists("./strategyConfig")) // os.exists("./strategyConfig"): true
Log(`os.exists("./strategyConfig/testData.txt"):`, os.exists("./strategyConfig/testData.txt")) // os.exists("./strategyConfig/testData.txt"): true
// Log(`os.exists("/strategyConfig"):`, os.exists("/strategyConfig")) // InternalError: invalid filename: path traversal or absolute path not allowed at main
Log(`os.exists("test_1.txt"):`, os.exists("test_1.txt")) // os.exists("test_1.txt"): true
Log(`os.exists("test_2.txt"):`, os.exists("test_2.txt")) // os.exists("test_2.txt"): false
}返回值
| 类型 | 描述 |
bool | 如果存在则返回true,否则返回false。 |
参数
| 名称 | 类型 | 必填 | 描述 |
filename | string | 是 | 文件或目录的路径。 |
参考
remove
删除指定文件。
remove(filename)示例
删除文件示例。
javascript
function main() {
let tempFile = "test_1.txt"
if (os.exists(tempFile)) {
let success = os.remove(tempFile)
Log("Temp file deleted:", success)
}
}返回值
| 类型 | 描述 |
bool | 删除成功返回true,失败返回false。 |
参数
| 名称 | 类型 | 必填 | 描述 |
filename | string | 是 | 要删除的文件路径。 |
参考
File ListFilesResult FileStat open fgets fputs mmap getRootDir listFiles exists remove mkdir rmdir rename stat exit
备注
此函数仅支持删除文件,不支持删除目录。如需删除目录,请使用rmdir()函数。
mkdir
创建目录。
mkdir(dirname)示例
创建数据存储目录,创建文件并写入数据。
javascript
function main() {
let success = os.mkdir("data/backtest/results")
Log("Directory created:", success)
if (success) {
os.fputs("data/backtest/results/summary.txt", "Backtest completed")
}
}返回值
| 类型 | 描述 |
bool | 创建成功返回true,失败返回false。 |
参数
| 名称 | 类型 | 必填 | 描述 |
dirname | string | 是 | 要创建的目录路径。 |
参考
File ListFilesResult FileStat open fgets fputs mmap getRootDir listFiles exists remove mkdir rmdir rename stat exit
备注
支持递归创建多级目录。如果父目录不存在,会自动创建。
rmdir
删除指定目录及其包含的所有内容。
rmdir(dirname)示例
删除指定目录及其所有内容。
javascript
function main() {
let tempDir = "data"
if (os.exists(tempDir)) {
let success = os.rmdir(tempDir)
Log("directory removed:", success)
}
}返回值
| 类型 | 描述 |
bool | 删除成功返回 true,失败返回 false。 |
参数
| 名称 | 类型 | 必填 | 描述 |
dirname | string | 是 | 需要删除的目录路径。 |
参考
File ListFilesResult FileStat open fgets fputs mmap getRootDir listFiles exists remove mkdir rmdir rename stat exit
备注
此操作将永久删除目录及其所有内容,请谨慎使用。
rename
重命名文件或将文件移动到新位置。
rename(oldName, newName)示例
重命名文件并将其移动到其他目录。
javascript
function main() {
let oldFileName = "output.txt"
let newFileName = "outputFiles/" + new Date().getTime() + "output.txt"
// let retRename = os.rename(oldFileName, newFileName)
// Log("retRename:", retRename) // InternalError: failed to rename file: renameat output.txt outputFiles/1757322073139output.txt: no such file or directory at main
os.mkdir("outputFiles")
retRename = os.rename(oldFileName, newFileName)
Log("retRename:", retRename) // retRename: true
}返回值
| 类型 | 描述 |
bool | 操作成功时返回 true,失败时返回 false。 |
参数
| 名称 | 类型 | 必填 | 描述 |
oldName | string | 是 | 原始文件名或文件路径。 |
newName | string | 是 | 目标文件名或文件路径。 |
参考
File ListFilesResult FileStat open fgets fputs mmap getRootDir listFiles exists remove mkdir rmdir rename stat exit
备注
此函数可用于重命名文件或将文件移动到不同的目录。如果目标路径中的目录不存在,操作将失败。
stat
获取文件的详细统计信息。
stat(filename)示例
获取文件信息并检查文件大小。
javascript
function main() {
if (os.exists("strategyConfig/testData.txt")) {
let stat = os.stat("strategyConfig/testData.txt") // stat: {"size":10,"mode":420,"mtime":1757312981796,"atime":1757312981796,"ctime":1757312981796}
Log("stat:", stat)
}
}返回值
| 类型 | 描述 |
FileStat 对象 | 返回包含文件统计信息的对象。 |
参数
| 名称 | 类型 | 必填 | 描述 |
filename | string | 是 | 文件路径。 |
参考
File ListFilesResult FileStat open fgets fputs mmap getRootDir listFiles exists remove mkdir rmdir rename stat exit
备注
返回的FileStat对象包含以下字段:
-
size: 文件大小(字节)。
-
mode: 文件权限模式。
-
mtime: 最后修改时间(时间戳)。
-
atime: 最后访问时间(时间戳)。
-
ctime: 创建时间(时间戳)。
exit
退出程序。
exit()
exit(status)示例
检查条件后退出程序。
javascript
function main() {
if (!os.exists("required_config.json")) {
Log("Required configuration file not found!")
os.exit(1) // 异常退出
}
Log("Configuration found, continuing...")
// 正常的策略逻辑...
}返回值
| 类型 | 描述 |
never | 此函数不会返回值,程序将直接终止执行。 |
参数
| 名称 | 类型 | 必填 | 描述 |
status | number | 否 | 可选的退出状态码,默认值为0。 |
参考
File ListFilesResult FileStat open fgets fputs mmap getRootDir listFiles exists remove mkdir rmdir rename stat exit
备注
立即终止程序执行。状态码0表示正常退出,非零值表示异常退出(实盘中将显示为错误)。
File
文件对象,提供文件读写、定位等操作。
close
关闭文件并释放相关资源。
close()示例
标准的文件操作流程示例。
javascript
function main() {
let file = os.open("data.txt", "w")
file.write("Hello YouQuant!")
file.close() // 必须关闭文件
}参考
备注
使用完文件对象后必须调用此方法以释放系统资源。
puts
向文件写入一个或多个字符串。
puts(data1, data2, ...dataN)示例
向文件写入多个字符串。
javascript
function main() {
let file = os.open("output.txt", "w+")
let bytes = file.puts("Hello", " ", "World", "!")
Log("Bytes written:", bytes) // Bytes written: 12
file.seek(0, 0)
let data = file.read()
Log("data:", data) // If using os.open("output.txt", "w") may result in data being undefined
// data: Hello World!
// file.puts() // error: puts requires at least 1 argument at main
file.puts(", Hello YouQuant!")
file.seek(0, 0)
data = file.read()
Log("data:", data) // data: Hello World!, Hello YouQuant!
file.close()
}返回值
| 类型 | 描述 |
number | 返回实际写入的字节数。 |
参数
| 名称 | 类型 | 必填 | 描述 |
data | string | 是 | 要写入的字符串数据,可传入多个参数。 |
参考
备注
可一次写入多个字符串参数,将按顺序连接后写入。
printf
格式化写入数据到文件。
printf(format)
printf(format, arg1, arg2, ...argN)示例
格式化写入交易数据。
javascript
function main() {
let file = os.open("trade_log.txt", "w+")
let price = 100.25
let volume = 1000
let bytes = file.printf("Price: %.2f, Volume: %d\n", price, volume)
Log("Formatted bytes written:", bytes)
file.seek(0, 0)
let data = file.read()
Log("data:", data) // data: Price: 100.25, Volume: 1000
// file.printf("| Price: %.2f, Volume: %d\n") // "| Price: %!f(MISSING), Volume: %!d(MISSING)"
// file.seek(0, 0)
// data = file.read()
// Log("data:", data)
file.close()
}返回值
| 类型 | 描述 |
number | 返回实际写入的字节数。 |
参数
| 名称 | 类型 | 必填 | 描述 |
format | string | 是 | 格式化字符串。 |
args | any (平台支持的任意类型) | 否 | 格式化参数。 |
参考
flush
刷新文件缓冲区,确保数据立即写入磁盘。
flush()示例
实时写入关键日志数据。
javascript
function main() {
let logFile = os.open("critical.log", "a")
logFile.printf("[%s] Critical event occurred\n", new Date().toISOString()) // [2025-09-09T03:15:43.895Z] Critical event occurred
logFile.flush() // 立即刷新缓冲区并写入磁盘
// 继续其他操作...
logFile.close()
}参考
tell
获取文件指针的当前位置。
tell()示例
记录文件操作过程中的位置。
javascript
function main() {
let file = os.open("data.txt", "r+")
Log("Initial position:", file.tell()) // Initial position: 0
file.write("Hello")
Log("After write position:", file.tell()) // After write position: 5
file.close()
}返回值
| 类型 | 描述 |
number | 返回文件指针的当前位置(以字节为单位的偏移量)。 |
参考
备注
返回文件指针相对于文件起始位置的字节偏移量。
seek
将文件指针移动到指定位置。
seek(offset, whence)示例
倒序读取字符。
javascript
function main() {
let str = "Hello YouQuant!"
let file = os.open("data.txt", "w+")
file.write(str)
// If i > str.length: will throw InternalError: seek .../xxx/data.txt: invalid argument at main
for (let i = 1; i <= str.length; i++) {
file.seek(-i, 2)
let data = file.read(1)
Log("i:", i, ", data:", data)
}
file.close()
}返回值
| 类型 | 描述 |
number | 返回文件指针的新位置。 |
参数
| 名称 | 类型 | 必填 | 描述 |
offset | number | 是 | 偏移量(以字节为单位)。 |
whence | number | 是 | 基准位置:0=文件开头,1=当前位置,2=文件末尾。 |
参考
备注
用于定位文件指针,offset参数可以为负数(表示向前移动)。
eof
检查文件指针是否已到达文件末尾。
eof()示例
逐行读取文件直至结束。
javascript
function main() {
let file = os.open("data.txt", "r")
let lineCount = 0
while (!file.eof()) {
let line = file.getline()
if (line) {
lineCount++
Log("Line", lineCount + ":", line)
}
}
Log("Total lines:", lineCount)
file.close()
}返回值
| 类型 | 描述 |
bool | 如果已到达文件末尾返回true,否则返回false。 |
参考
备注
用于在读取文件时判断是否已读取完所有内容。
read
从文件中读取数据。
read()
read(size)示例
分块读取文件内容。
javascript
function main() {
let file = os.open("data.txt", "r")
// data.txt
// This is a test line: Line 1.
// This is a test line: Line 2.
// ...
let chunkSize = 29
let totalBytes = 0
while (!file.eof()) {
let chunk = file.read(chunkSize)
if (chunk) {
totalBytes += chunk.length || chunk.byteLength
Log("Read chunk, total bytes so far:", totalBytes, ", chunk:", chunk)
}
}
file.close()
}返回值
| 类型 | 描述 |
string / ArrayBuffer / undefined | 返回读取的内容。当到达文件末尾时返回 |
参数
| 名称 | 类型 | 必填 | 描述 |
size | number | 否 | 要读取的字节数。如果不指定,则读取文件中剩余的所有内容。 |
参考
备注
可以读取指定字节数的内容或文件中剩余的全部内容。返回类型可能是字符串或ArrayBuffer。
write
向文件写入字符串数据。
write(data)示例
写入交易记录
javascript
function main() {
let file = os.open("trades.log", "a")
let timestamp = new Date().toISOString()
let tradeInfo = `${timestamp},BUY,50000,1\n`
let bytes = file.write(tradeInfo)
Log("Trade record written, bytes:", bytes)
file.close()
}返回值
| 类型 | 描述 |
number | 返回实际写入的字节数。 |
参数
| 名称 | 类型 | 必填 | 描述 |
data | string | 是 | 要写入的字符串数据。 |
参考
备注
将字符串数据写入文件的当前位置。
getline
从文件中读取下一行内容。
getline()示例
逐行读取文件直至结束。
javascript
function main() {
let file = os.open("data.txt", "r")
let lineCount = 0
while (!file.eof()) {
let line = file.getline()
if (line) {
lineCount++
Log("Line", lineCount + ":", line)
}
}
Log("Total lines:", lineCount)
file.close()
}返回值
| 类型 | 描述 |
string / undefined | 返回下一行内容,到达文件末尾时返回 |
参考
备注
按行顺序读取文件内容。
ListFilesResult
文件列表对象,用于记录目录列表信息。该对象包含两个数组属性:files(文件列表)和dirs(目录列表)。
参考
备注
ListFilesResult对象结构:
javascript
{
files: string[], // 搜索到的文件名数组
dirs: string[] // 当前目录下的子目录名数组
}
此对象由os.listFiles()函数返回。