Resolve "Alpaca API Implementation" #28
271
.eslintrc.js
271
.eslintrc.js
@ -1,136 +1,137 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
parser: "@typescript-eslint/parser",
|
parser: "@typescript-eslint/parser",
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
ecmaVersion: "latest", // Allows the use of modern ECMAScript features
|
ecmaVersion: "latest", // Allows the use of modern ECMAScript features
|
||||||
sourceType: "module", // Allows for the use of imports
|
sourceType: "module", // Allows for the use of imports
|
||||||
project: ["./tsconfig.json", "./tsconfig.test.json"]
|
project: ["./tsconfig.json", "./tsconfig.test.json"]
|
||||||
},
|
},
|
||||||
extends: ["plugin:@typescript-eslint/recommended"], // Uses the linting rules from @typescript-eslint/eslint-plugin
|
extends: ["plugin:@typescript-eslint/recommended"], // Uses the linting rules from @typescript-eslint/eslint-plugin
|
||||||
env: {
|
env: {
|
||||||
node: true, // Enable Node.js global variables
|
node: true, // Enable Node.js global variables
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
"array-callback-return": "error",
|
"array-callback-return": "error",
|
||||||
"no-await-in-loop": "error",
|
"no-await-in-loop": "error",
|
||||||
"no-cond-assign": [ "error", "always" ],
|
"no-cond-assign": ["error", "always"],
|
||||||
"no-constant-binary-expression": "error",
|
"no-constant-binary-expression": "error",
|
||||||
"no-constant-condition": "error",
|
"no-constant-condition": "error",
|
||||||
"no-constructor-return": "error",
|
"no-constructor-return": "error",
|
||||||
"no-duplicate-imports": "error",
|
"no-duplicate-imports": "error",
|
||||||
"no-promise-executor-return": "error",
|
"no-promise-executor-return": "error",
|
||||||
"no-self-compare": "error",
|
"no-self-compare": "error",
|
||||||
"no-undef": [ "error", { "typeof": true } ],
|
"no-undef": ["error", { "typeof": true }],
|
||||||
"no-unmodified-loop-condition": "error",
|
"no-unmodified-loop-condition": "error",
|
||||||
"no-unreachable-loop": "error",
|
"no-unreachable-loop": "error",
|
||||||
"no-unused-private-class-members": "error",
|
"no-unused-private-class-members": "error",
|
||||||
"require-atomic-updates": "error",
|
"require-atomic-updates": "error",
|
||||||
|
|
||||||
"accessor-pairs": "error",
|
"accessor-pairs": "error",
|
||||||
"block-scoped-var": "error",
|
"block-scoped-var": "error",
|
||||||
"curly": [ "error", "all" ],
|
"curly": ["error", "all"],
|
||||||
"default-case": "error",
|
"default-case": "error",
|
||||||
"default-case-last": "error",
|
"default-case-last": "error",
|
||||||
"default-param-last": "error",
|
"default-param-last": "error",
|
||||||
"dot-notation": "error",
|
"dot-notation": "error",
|
||||||
"eqeqeq": "error",
|
"eqeqeq": "error",
|
||||||
"func-style": [ "error", "expression" ],
|
"func-style": ["error", "expression"],
|
||||||
"grouped-accessor-pairs": [ "error", "getBeforeSet" ],
|
"grouped-accessor-pairs": ["error", "getBeforeSet"],
|
||||||
"no-caller": "error",
|
"no-caller": "error",
|
||||||
"no-console": "error",
|
"no-console": "error",
|
||||||
"no-eq-null": "error",
|
"no-eq-null": "error",
|
||||||
"no-eval": "error",
|
"no-eval": "error",
|
||||||
"no-extend-native": "error",
|
"no-extend-native": "error",
|
||||||
"no-extra-label": "error",
|
"no-extra-label": "error",
|
||||||
"no-implicit-coercion": "error",
|
"no-implicit-coercion": "error",
|
||||||
"no-implicit-globals": "error",
|
"no-implicit-globals": "error",
|
||||||
"no-implied-eval": "error",
|
"no-implied-eval": "error",
|
||||||
"no-inline-comments": "error",
|
"no-inline-comments": "error",
|
||||||
"no-invalid-this": "error",
|
"no-invalid-this": "error",
|
||||||
"no-iterator": "error",
|
"no-iterator": "error",
|
||||||
"no-label-var": "error",
|
"no-label-var": "error",
|
||||||
"no-labels": "error",
|
"no-labels": "error",
|
||||||
"no-lone-blocks": "error",
|
"no-lone-blocks": "error",
|
||||||
"no-lonely-if": "error",
|
"no-lonely-if": "error",
|
||||||
"no-loop-func": "error",
|
"no-loop-func": "error",
|
||||||
"no-magic-numbers": "error",
|
"no-magic-numbers": "error",
|
||||||
"no-mixed-operators": "error",
|
"no-mixed-operators": "error",
|
||||||
"no-multi-assign": "error",
|
"no-multi-assign": "error",
|
||||||
"no-multi-str": "error",
|
"no-multi-str": "error",
|
||||||
"no-nested-ternary": "error",
|
"no-nested-ternary": "error",
|
||||||
"no-new": "error",
|
"no-new": "error",
|
||||||
"no-new-func": "error",
|
"no-new-func": "error",
|
||||||
"no-new-wrappers": "error",
|
"no-new-wrappers": "error",
|
||||||
"no-nonoctal-decimal-escape": "error",
|
"no-nonoctal-decimal-escape": "error",
|
||||||
"no-object-constructor": "error",
|
"no-object-constructor": "error",
|
||||||
"no-octal-escape": "error",
|
"no-octal-escape": "error",
|
||||||
"no-param-reassign": "error",
|
"no-param-reassign": "error",
|
||||||
"no-plusplus": "error",
|
"no-plusplus": "error",
|
||||||
"no-proto": "error",
|
"no-proto": "error",
|
||||||
"no-return-assign": "error",
|
"no-return-assign": "error",
|
||||||
"no-script-url": "error",
|
"no-script-url": "error",
|
||||||
"no-sequences": "error",
|
"no-sequences": "error",
|
||||||
"no-shadow": "error",
|
"no-shadow": "error",
|
||||||
"no-throw-literal": "error",
|
"no-throw-literal": "error",
|
||||||
"no-undef-init": "error",
|
"no-undef-init": "error",
|
||||||
"no-undefined": "error",
|
"no-undefined": "error",
|
||||||
"no-underscore-dangle": "error",
|
"no-underscore-dangle": "error",
|
||||||
"no-unneeded-ternary": "error",
|
"no-unneeded-ternary": "error",
|
||||||
"no-unused-expressions": "error",
|
"no-unused-expressions": "error",
|
||||||
"no-useless-call": "error",
|
"no-useless-call": "error",
|
||||||
"no-useless-catch": "error",
|
"no-useless-catch": "error",
|
||||||
"no-useless-computed-key": "error",
|
"no-useless-computed-key": "error",
|
||||||
"no-useless-concat": "error",
|
"no-useless-concat": "error",
|
||||||
"no-useless-constructor": "error",
|
"no-useless-constructor": "error",
|
||||||
"no-useless-rename": "error",
|
"no-useless-rename": "error",
|
||||||
"no-var": "error",
|
"no-var": "error",
|
||||||
"no-void": "error",
|
"no-void": "error",
|
||||||
"one-var": [ "error", "never" ],
|
"one-var": ["error", "never"],
|
||||||
"one-var-declaration-per-line": [ "error", "always" ],
|
"one-var-declaration-per-line": ["error", "always"],
|
||||||
"prefer-arrow-callback": "error",
|
"prefer-arrow-callback": "error",
|
||||||
"prefer-const": "error",
|
"prefer-const": "error",
|
||||||
"prefer-exponentiation-operator": "error",
|
"prefer-exponentiation-operator": "error",
|
||||||
"prefer-named-capture-group": "error",
|
"prefer-named-capture-group": "error",
|
||||||
"prefer-numeric-literals": "error",
|
"prefer-numeric-literals": "error",
|
||||||
"prefer-object-has-own": "error",
|
"prefer-object-has-own": "error",
|
||||||
"prefer-object-spread": "error",
|
"prefer-object-spread": "error",
|
||||||
"prefer-promise-reject-errors": "error",
|
"prefer-promise-reject-errors": "error",
|
||||||
"prefer-regex-literals": "error",
|
"prefer-regex-literals": "error",
|
||||||
"prefer-rest-params": "error",
|
"prefer-rest-params": "error",
|
||||||
"prefer-spread": "error",
|
"prefer-spread": "error",
|
||||||
"prefer-template": "error",
|
"prefer-template": "error",
|
||||||
"quote-props": [ "error", "as-needed" ],
|
"quote-props": ["error", "as-needed"],
|
||||||
"radix": "error",
|
"semi": ["error", "always"],
|
||||||
"require-await": "error",
|
"radix": "error",
|
||||||
"require-unicode-regexp": "error",
|
"require-await": "error",
|
||||||
"symbol-description": "error",
|
"require-unicode-regexp": "error",
|
||||||
"yoda": "error",
|
"symbol-description": "error",
|
||||||
|
"yoda": "error",
|
||||||
"array-bracket-newline": [ "error", "consistent" ],
|
|
||||||
"array-bracket-spacing": [ "error", "always", { "singleValue": false } ],
|
"array-bracket-newline": ["error", "consistent"],
|
||||||
"array-element-newline": [ "error", "consistent" ],
|
"array-bracket-spacing": ["error", "always", { "singleValue": false }],
|
||||||
"arrow-parens": "error",
|
"array-element-newline": ["error", "consistent"],
|
||||||
"arrow-spacing": "error",
|
"arrow-parens": "error",
|
||||||
"block-spacing": "error",
|
"arrow-spacing": "error",
|
||||||
"computed-property-spacing": "error",
|
"block-spacing": "error",
|
||||||
"eol-last": "error",
|
"computed-property-spacing": "error",
|
||||||
"generator-star-spacing": [ "error", { "before": false, "after": true } ],
|
"eol-last": "error",
|
||||||
"key-spacing": "error",
|
"generator-star-spacing": ["error", { "before": false, "after": true }],
|
||||||
"linebreak-style": "error",
|
"key-spacing": "error",
|
||||||
"lines-around-comment": [ "error", { "allowBlockStart": true }],
|
"linebreak-style": "error",
|
||||||
"max-len": [ "error", { "code": 120 } ],
|
"lines-around-comment": ["error", { "allowBlockStart": true }],
|
||||||
"new-parens": "error",
|
"max-len": ["error", { "code": 120 }],
|
||||||
"no-multi-spaces": "error",
|
"new-parens": "error",
|
||||||
"no-multiple-empty-lines": "error",
|
"no-multi-spaces": "error",
|
||||||
"no-trailing-spaces": "error",
|
"no-multiple-empty-lines": "error",
|
||||||
"no-whitespace-before-property": "error",
|
"no-trailing-spaces": "error",
|
||||||
"nonblock-statement-body-position": [ "error", "below" ],
|
"no-whitespace-before-property": "error",
|
||||||
"object-curly-newline": [ "error", { "ObjectExpression": { "consistent": true }, "ObjectPattern": { "consistent": true } } ],
|
"nonblock-statement-body-position": ["error", "below"],
|
||||||
"operator-linebreak": "error",
|
"object-curly-newline": ["error", { "ObjectExpression": { "consistent": true }, "ObjectPattern": { "consistent": true } }],
|
||||||
"padded-blocks": [ "error", "never" ],
|
"operator-linebreak": "error",
|
||||||
"space-in-parens": "error",
|
"padded-blocks": ["error", "never"],
|
||||||
"switch-colon-spacing": [ "error", { "after": false, "before": false } ],
|
"space-in-parens": "error",
|
||||||
"template-curly-spacing": "error",
|
"switch-colon-spacing": ["error", { "after": false, "before": false }],
|
||||||
"wrap-iife": "error",
|
"template-curly-spacing": "error",
|
||||||
"yield-star-spacing": [ "error", "after" ],
|
"wrap-iife": "error",
|
||||||
}
|
"yield-star-spacing": ["error", "after"],
|
||||||
};
|
}
|
||||||
|
};
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
node_modules/**
|
node_modules/**
|
||||||
dist/**
|
dist/**
|
||||||
docs/**
|
docs/**
|
||||||
|
.env
|
@ -8,6 +8,7 @@ const config: Config.InitialOptions =
|
|||||||
},
|
},
|
||||||
|
|
||||||
collectCoverageFrom: ['src/*.ts'],
|
collectCoverageFrom: ['src/*.ts'],
|
||||||
|
verbose: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default config
|
export default config
|
255
package-lock.json
generated
255
package-lock.json
generated
@ -9,6 +9,8 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "GPL-3.0-or-later",
|
"license": "GPL-3.0-or-later",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@alpacahq/alpaca-trade-api": "^3.0.1",
|
||||||
|
"dotenv": "^16.3.1",
|
||||||
"winston": "^3.10.0"
|
"winston": "^3.10.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@ -34,6 +36,35 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@alpacahq/alpaca-trade-api": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@alpacahq/alpaca-trade-api/-/alpaca-trade-api-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-FOsgA4jREAArWbb7nuKTo2yiUdb8+/4vboyTX2SRJSi+oYBaFrZV+hMNx7fGWtuLuKGRKEdK8Nc+8MFjwcbz4g==",
|
||||||
|
"dependencies": {
|
||||||
|
"axios": "^0.21.1",
|
||||||
|
"dotenv": "^6.2.0",
|
||||||
|
"events": "^3.2.0",
|
||||||
|
"just-extend": "^4.1.0",
|
||||||
|
"lodash": "^4.17.19",
|
||||||
|
"minimist": "^1.2.6",
|
||||||
|
"msgpack5": "^5.3.2",
|
||||||
|
"nats": "^1.4.9",
|
||||||
|
"urljoin": "^0.1.5",
|
||||||
|
"ws": "^7.4.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.x",
|
||||||
|
"npm": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@alpacahq/alpaca-trade-api/node_modules/dotenv": {
|
||||||
|
"version": "6.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-6.2.0.tgz",
|
||||||
|
"integrity": "sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@ampproject/remapping": {
|
"node_modules/@ampproject/remapping": {
|
||||||
"version": "2.2.1",
|
"version": "2.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz",
|
||||||
@ -662,9 +693,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/traverse": {
|
"node_modules/@babel/traverse": {
|
||||||
"version": "7.23.0",
|
"version": "7.23.2",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.0.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz",
|
||||||
"integrity": "sha512-t/QaEvyIoIkwzpiZ7aoSKK8kObQYeF7T2v+dazAYCb8SXtp58zEVkWW7zAnju8FNKNdr4ScAOEDmMItbyOmEYw==",
|
"integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/code-frame": "^7.22.13",
|
"@babel/code-frame": "^7.22.13",
|
||||||
@ -1822,6 +1853,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
|
||||||
"integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ=="
|
"integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ=="
|
||||||
},
|
},
|
||||||
|
"node_modules/axios": {
|
||||||
|
"version": "0.21.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
|
||||||
|
"integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
|
||||||
|
"dependencies": {
|
||||||
|
"follow-redirects": "^1.14.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/babel-jest": {
|
"node_modules/babel-jest": {
|
||||||
"version": "29.7.0",
|
"version": "29.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz",
|
||||||
@ -1944,6 +1983,35 @@
|
|||||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/base64-js": {
|
||||||
|
"version": "1.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||||
|
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/bl": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
|
||||||
|
"dependencies": {
|
||||||
|
"buffer": "^5.5.0",
|
||||||
|
"inherits": "^2.0.4",
|
||||||
|
"readable-stream": "^3.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/brace-expansion": {
|
"node_modules/brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||||
@ -2019,6 +2087,29 @@
|
|||||||
"node-int64": "^0.4.0"
|
"node-int64": "^0.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/buffer": {
|
||||||
|
"version": "5.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
||||||
|
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"base64-js": "^1.3.1",
|
||||||
|
"ieee754": "^1.1.13"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/buffer-from": {
|
"node_modules/buffer-from": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
||||||
@ -2346,6 +2437,17 @@
|
|||||||
"node": ">=6.0.0"
|
"node": ">=6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/dotenv": {
|
||||||
|
"version": "16.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz",
|
||||||
|
"integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/motdotla/dotenv?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/electron-to-chromium": {
|
"node_modules/electron-to-chromium": {
|
||||||
"version": "1.4.544",
|
"version": "1.4.544",
|
||||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.544.tgz",
|
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.544.tgz",
|
||||||
@ -2565,6 +2667,14 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/events": {
|
||||||
|
"version": "3.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
|
||||||
|
"integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/execa": {
|
"node_modules/execa": {
|
||||||
"version": "5.1.1",
|
"version": "5.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
|
||||||
@ -2613,6 +2723,11 @@
|
|||||||
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
|
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/extend": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/extend/-/extend-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-AgFD4VU+lVLP6vjnlNfF7OeInLTyeyckCNPEsuxz1vi786UuK/nk6ynPuhn/h+Ju9++TQyr5EpLRI14fc1QtTQ=="
|
||||||
|
},
|
||||||
"node_modules/fast-deep-equal": {
|
"node_modules/fast-deep-equal": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||||
@ -2747,6 +2862,25 @@
|
|||||||
"resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz",
|
||||||
"integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="
|
"integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/follow-redirects": {
|
||||||
|
"version": "1.15.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz",
|
||||||
|
"integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"debug": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fs.realpath": {
|
"node_modules/fs.realpath": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||||
@ -2918,6 +3052,25 @@
|
|||||||
"node": ">=10.17.0"
|
"node": ">=10.17.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ieee754": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"node_modules/ignore": {
|
"node_modules/ignore": {
|
||||||
"version": "5.2.4",
|
"version": "5.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
|
||||||
@ -3770,6 +3923,11 @@
|
|||||||
"integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==",
|
"integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/just-extend": {
|
||||||
|
"version": "4.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz",
|
||||||
|
"integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg=="
|
||||||
|
},
|
||||||
"node_modules/keyv": {
|
"node_modules/keyv": {
|
||||||
"version": "4.5.3",
|
"version": "4.5.3",
|
||||||
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz",
|
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz",
|
||||||
@ -3836,6 +3994,11 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/lodash": {
|
||||||
|
"version": "4.17.21",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||||
|
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||||
|
},
|
||||||
"node_modules/lodash.memoize": {
|
"node_modules/lodash.memoize": {
|
||||||
"version": "4.1.2",
|
"version": "4.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
|
||||||
@ -3970,11 +4133,48 @@
|
|||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/minimist": {
|
||||||
|
"version": "1.2.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
||||||
|
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ms": {
|
"node_modules/ms": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||||
},
|
},
|
||||||
|
"node_modules/msgpack5": {
|
||||||
|
"version": "5.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/msgpack5/-/msgpack5-5.3.2.tgz",
|
||||||
|
"integrity": "sha512-e9jz+6InQIUb2cGzZ/Mi+rQBs1KFLby+gNi+22VwQ1pnC9ieZjysKGmRMjdlf6IyjsltbgY4tGoHwHmyS7l94A==",
|
||||||
|
"dependencies": {
|
||||||
|
"bl": "^4.0.0",
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"readable-stream": "^3.0.0",
|
||||||
|
"safe-buffer": "^5.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/nats": {
|
||||||
|
"version": "1.4.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/nats/-/nats-1.4.12.tgz",
|
||||||
|
"integrity": "sha512-Jf4qesEF0Ay0D4AMw3OZnKMRTQm+6oZ5q8/m4gpy5bTmiDiK6wCXbZpzEslmezGpE93LV3RojNEG6dpK/mysLQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"nuid": "^1.1.4",
|
||||||
|
"ts-nkeys": "^1.0.16"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"node-pub": "examples/node-pub",
|
||||||
|
"node-reply": "examples/node-reply",
|
||||||
|
"node-req": "examples/node-req",
|
||||||
|
"node-sub": "examples/node-sub"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/natural-compare": {
|
"node_modules/natural-compare": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
|
||||||
@ -4014,6 +4214,14 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/nuid": {
|
||||||
|
"version": "1.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/nuid/-/nuid-1.1.6.tgz",
|
||||||
|
"integrity": "sha512-Eb3CPCupYscP1/S1FQcO5nxtu6l/F3k0MQ69h7f5osnsemVk5pkc8/5AyalVT+NCfra9M71U8POqF6EZa6IHvg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8.16.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/once": {
|
"node_modules/once": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||||
@ -4864,6 +5072,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ts-nkeys": {
|
||||||
|
"version": "1.0.16",
|
||||||
|
"resolved": "https://registry.npmjs.org/ts-nkeys/-/ts-nkeys-1.0.16.tgz",
|
||||||
|
"integrity": "sha512-1qrhAlavbm36wtW+7NtKOgxpzl+70NTF8xlz9mEhiA5zHMlMxjj3sEVKWm3pGZhHXE0Q3ykjrj+OSRVaYw+Dqg==",
|
||||||
|
"dependencies": {
|
||||||
|
"tweetnacl": "^1.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ts-node": {
|
"node_modules/ts-node": {
|
||||||
"version": "10.9.1",
|
"version": "10.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
|
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
|
||||||
@ -4907,6 +5123,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tweetnacl": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw=="
|
||||||
|
},
|
||||||
"node_modules/type-check": {
|
"node_modules/type-check": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||||
@ -5037,6 +5258,14 @@
|
|||||||
"punycode": "^2.1.0"
|
"punycode": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/urljoin": {
|
||||||
|
"version": "0.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/urljoin/-/urljoin-0.1.5.tgz",
|
||||||
|
"integrity": "sha512-OSGi+PS3zxk8XfQ+7buaupOdrW9P9p+V9rjxGzJaYEYDe/B2rv3WJCupq5LNERW4w4kWxsduUUrhCxZZiQ2udw==",
|
||||||
|
"dependencies": {
|
||||||
|
"extend": "~2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/util-deprecate": {
|
"node_modules/util-deprecate": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
@ -5168,6 +5397,26 @@
|
|||||||
"node": "^12.13.0 || ^14.15.0 || >=16.0.0"
|
"node": "^12.13.0 || ^14.15.0 || >=16.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ws": {
|
||||||
|
"version": "7.5.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
|
||||||
|
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.3.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"bufferutil": "^4.0.1",
|
||||||
|
"utf-8-validate": "^5.0.2"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"bufferutil": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"utf-8-validate": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/y18n": {
|
"node_modules/y18n": {
|
||||||
"version": "5.0.8",
|
"version": "5.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
||||||
|
@ -28,6 +28,8 @@
|
|||||||
"typescript": "^5.2.2"
|
"typescript": "^5.2.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@alpacahq/alpaca-trade-api": "^3.0.1",
|
||||||
|
"dotenv": "^16.3.1",
|
||||||
"winston": "^3.10.0"
|
"winston": "^3.10.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
51
src/alpaca/exchange.ts
Normal file
51
src/alpaca/exchange.ts
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import Alpaca from '@alpacahq/alpaca-trade-api';
|
||||||
|
import { AlpacaPortfolioProvider } from './portfolio';
|
||||||
|
import { AlpacaQuoteProvider } from './quote';
|
||||||
|
import { Exchange } from '../interface/exchange';
|
||||||
|
import { PortfolioProvider } from '../interface/portfolio';
|
||||||
|
import { QuoteProvider } from '../interface/quote';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exchange implementation for Alpaca.
|
||||||
|
*/
|
||||||
|
export class AlpacaExchange implements Exchange {
|
||||||
|
/**
|
||||||
|
* The Alpaca API client.
|
||||||
|
*/
|
||||||
|
readonly alpaca: Alpaca;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The portfolio provider for the exchange.
|
||||||
|
*/
|
||||||
|
readonly portfolioProvider: PortfolioProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The quote provider for the exchange.
|
||||||
|
*/
|
||||||
|
readonly quoteProvider: QuoteProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the exchange.
|
||||||
|
*/
|
||||||
|
readonly name: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance of the Alpaca exchange.
|
||||||
|
* @constructor
|
||||||
|
* @param {string} keyId - The API key ID for the Alpaca exchange.
|
||||||
|
* @param {string} secretKey - The secret key for the Alpaca exchange.
|
||||||
|
* @param {boolean} paper - Whether to use the paper trading environment or not.
|
||||||
|
*/
|
||||||
|
constructor(keyId: string, secretKey: string, paper: boolean) {
|
||||||
|
this.alpaca = new Alpaca({
|
||||||
|
keyId: keyId,
|
||||||
|
secretKey: secretKey,
|
||||||
|
paper: paper
|
||||||
|
});
|
||||||
|
|
||||||
|
this.portfolioProvider = new AlpacaPortfolioProvider(this.alpaca);
|
||||||
|
this.quoteProvider = new AlpacaQuoteProvider(this.alpaca);
|
||||||
|
|
||||||
|
this.name = 'Alpaca';
|
||||||
|
}
|
||||||
|
}
|
63
src/alpaca/portfolio.ts
Normal file
63
src/alpaca/portfolio.ts
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import Alpaca from '@alpacahq/alpaca-trade-api';
|
||||||
|
import { PortfolioProvider, Portfolio, Position } from '../interface/portfolio';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The position object returned by Alpaca.
|
||||||
|
* @see https://alpaca.markets/docs/api-references/trading-api/positions/#properties
|
||||||
|
*/
|
||||||
|
class AlpacaPosition {
|
||||||
|
asset_id!: string;
|
||||||
|
symbol!: string;
|
||||||
|
exchange!: string;
|
||||||
|
asset_class!: string;
|
||||||
|
avg_entry_price!: string;
|
||||||
|
qty!: string;
|
||||||
|
qty_available!: string;
|
||||||
|
side!: string;
|
||||||
|
market_value!: string;
|
||||||
|
cost_basis!: string;
|
||||||
|
unrealized_pl!: string;
|
||||||
|
unrealized_plpc!: string;
|
||||||
|
unrealized_intraday_pl!: string;
|
||||||
|
unrealized_intraday_plpc!: string;
|
||||||
|
current_price!: string;
|
||||||
|
lastday_price!: string;
|
||||||
|
change_today!: string;
|
||||||
|
asset_marginable!: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a portfolio using the Alpaca API client.
|
||||||
|
*/
|
||||||
|
export class AlpacaPortfolioProvider implements PortfolioProvider {
|
||||||
|
/**
|
||||||
|
* The Alpaca API client.
|
||||||
|
*/
|
||||||
|
readonly alpaca: Alpaca;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches the portfolio.
|
||||||
|
*/
|
||||||
|
readonly fetchPortfolio = (): Promise<Portfolio> => {
|
||||||
|
return (this.alpaca.getPositions() as Promise<AlpacaPosition[]>).then((positions) => {
|
||||||
|
return new Portfolio(positions.map((position) => {
|
||||||
|
return new Position(
|
||||||
|
position.symbol,
|
||||||
|
parseInt(position.qty, 10),
|
||||||
|
parseFloat(position.market_value),
|
||||||
|
parseFloat(position.cost_basis),
|
||||||
|
parseFloat(position.market_value)
|
||||||
|
);
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new AlpacaPortfolioProvider instance.
|
||||||
|
* @constructor
|
||||||
|
* @param {Alpaca} alpaca - The Alpaca API client.
|
||||||
|
*/
|
||||||
|
constructor(alpaca: Alpaca) {
|
||||||
|
this.alpaca = alpaca;
|
||||||
|
}
|
||||||
|
}
|
41
src/alpaca/quote.ts
Normal file
41
src/alpaca/quote.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import Alpaca from '@alpacahq/alpaca-trade-api';
|
||||||
|
import { QuoteProvider, Quote } from '../interface/quote';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides quotes using the Alpaca API.
|
||||||
|
*/
|
||||||
|
export class AlpacaQuoteProvider implements QuoteProvider {
|
||||||
|
/**
|
||||||
|
* The Alpaca API client.
|
||||||
|
*/
|
||||||
|
readonly alpaca: Alpaca;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches a quote for the given stock symbol.
|
||||||
|
* @param symbol The stock symbol to fetch the quote for.
|
||||||
|
* @returns A Promise that resolves to a Quote object.
|
||||||
|
*/
|
||||||
|
readonly fetchQuote = (symbol: string): Promise<Quote> => {
|
||||||
|
return this.alpaca.getLatestQuote(symbol).then((quote) => {
|
||||||
|
return new Quote(
|
||||||
|
quote.Symbol,
|
||||||
|
quote.AskPrice,
|
||||||
|
quote.AskSize,
|
||||||
|
quote.BidPrice,
|
||||||
|
quote.BidSize,
|
||||||
|
new Date(Date.parse(quote.Timestamp))
|
||||||
|
);
|
||||||
|
}).catch((err) => {
|
||||||
|
return err;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new AlpacaQuoteProvider instance.
|
||||||
|
* @constructor
|
||||||
|
* @param {Alpaca} alpaca - The Alpaca API client.
|
||||||
|
*/
|
||||||
|
constructor(alpaca: Alpaca) {
|
||||||
|
this.alpaca = alpaca;
|
||||||
|
}
|
||||||
|
}
|
@ -9,4 +9,4 @@ export {
|
|||||||
PortfolioProvider,
|
PortfolioProvider,
|
||||||
Quote,
|
Quote,
|
||||||
QuoteProvider
|
QuoteProvider
|
||||||
}
|
};
|
||||||
|
@ -20,4 +20,4 @@ export interface Exchange {
|
|||||||
* The name of the exchange.
|
* The name of the exchange.
|
||||||
*/
|
*/
|
||||||
readonly name: string;
|
readonly name: string;
|
||||||
}
|
}
|
||||||
|
@ -3,67 +3,46 @@
|
|||||||
*/
|
*/
|
||||||
export class Position {
|
export class Position {
|
||||||
/**
|
/**
|
||||||
* The price of the last trade made for this position.
|
* The symbol name of the asset
|
||||||
*/
|
|
||||||
readonly lastTrade: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The date and time of the last trade made for this position.
|
|
||||||
*/
|
|
||||||
readonly lastTradeTime: Date;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The change in the position value.
|
|
||||||
*/
|
|
||||||
readonly change: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The percentage change in the position value.
|
|
||||||
*/
|
|
||||||
readonly changePercent: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The earnings per share of the position.
|
|
||||||
*/
|
|
||||||
readonly earningsPerShare: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The market capitalization of the position.
|
|
||||||
*/
|
|
||||||
readonly marketCap: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The symbol of the position.
|
|
||||||
*/
|
*/
|
||||||
readonly symbol: string;
|
readonly symbol: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a position in a portfolio.
|
* The total number of shares, not including open orders
|
||||||
* @constructor
|
|
||||||
* @param {number} lastTrade - The price of the last trade made for this position.
|
|
||||||
* @param {Date} lastTradeTime - The date and time of the last trade made for this position.
|
|
||||||
* @param {number} change - The change in the position value.
|
|
||||||
* @param {number} changePercent - The percentage change in the position value.
|
|
||||||
* @param {number} earningsPerShare - The earnings per share of the position.
|
|
||||||
* @param {number} marketCap - The market capitalization of the position.
|
|
||||||
* @param {string} symbol - The symbol of the position.
|
|
||||||
*/
|
*/
|
||||||
constructor(
|
readonly quantity: number;
|
||||||
lastTrade: number,
|
|
||||||
lastTradeTime: Date,
|
/**
|
||||||
change: number,
|
* The total dollar amount of the position
|
||||||
changePercent: number,
|
*/
|
||||||
earningsPerShare: number,
|
readonly marketValue: number;
|
||||||
marketCap: number,
|
|
||||||
symbol: string
|
/**
|
||||||
) {
|
* The total cost basis
|
||||||
this.lastTrade = lastTrade;
|
*/
|
||||||
this.lastTradeTime = lastTradeTime;
|
readonly costBasis: number;
|
||||||
this.change = change;
|
|
||||||
this.changePercent = changePercent;
|
/**
|
||||||
this.earningsPerShare = earningsPerShare;
|
* The current asset price per share
|
||||||
this.marketCap = marketCap;
|
*/
|
||||||
|
readonly pricePerShare: number;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new Portfolio object.
|
||||||
|
* @constructor
|
||||||
|
* @param {string} symbol - The symbol of the asset in the portfolio.
|
||||||
|
* @param {number} quantity - The quantity of the asset in the portfolio.
|
||||||
|
* @param {number} marketValue - The market value of the asset in the portfolio.
|
||||||
|
* @param {number} costBasis - The cost basis of the asset in the portfolio.
|
||||||
|
* @param {number} pricePerShare - The price per share of the asset in the portfolio.
|
||||||
|
*/
|
||||||
|
constructor(symbol: string, quantity: number, marketValue: number, costBasis: number, pricePerShare: number) {
|
||||||
this.symbol = symbol;
|
this.symbol = symbol;
|
||||||
|
this.quantity = quantity;
|
||||||
|
this.marketValue = marketValue;
|
||||||
|
this.costBasis = costBasis;
|
||||||
|
this.pricePerShare = pricePerShare;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,52 +2,20 @@
|
|||||||
* Represents a stock quote.
|
* Represents a stock quote.
|
||||||
*/
|
*/
|
||||||
export class Quote {
|
export class Quote {
|
||||||
/**
|
|
||||||
* The name of the company associated with this quote.
|
|
||||||
*/
|
|
||||||
readonly companyName: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The earnings per share of a company.
|
|
||||||
*/
|
|
||||||
readonly earningsPerShare: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The estimated earnings for a stock.
|
|
||||||
*/
|
|
||||||
readonly estimatedEarnings: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The price of the last trade for the security.
|
|
||||||
*/
|
|
||||||
readonly lastTrade: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The symbol of the financial instrument being quoted.
|
|
||||||
*/
|
|
||||||
readonly symbol: string;
|
readonly symbol: string;
|
||||||
|
readonly askPrice: number;
|
||||||
|
readonly askSize: number;
|
||||||
|
readonly bidPrice: number;
|
||||||
|
readonly bidSize: number;
|
||||||
|
readonly timeStamp: Date;
|
||||||
|
|
||||||
/**
|
constructor(symbol: string, askPrice: number, askSize: number, bidPrice: number, bidSize: number, timeStamp: Date) {
|
||||||
* Represents a quote for a particular stock.
|
|
||||||
* @constructor
|
|
||||||
* @param {string} companyName - The name of the company associated with the stock.
|
|
||||||
* @param {number} earningsPerShare - The earnings per share for the stock.
|
|
||||||
* @param {number} estimatedEarnings - The estimated earnings for the stock.
|
|
||||||
* @param {number} lastTrade - The last trade price for the stock.
|
|
||||||
* @param {string} symbol - The symbol for the stock.
|
|
||||||
*/
|
|
||||||
constructor(
|
|
||||||
companyName: string,
|
|
||||||
earningsPerShare: number,
|
|
||||||
estimatedEarnings: number,
|
|
||||||
lastTrade: number,
|
|
||||||
symbol: string
|
|
||||||
) {
|
|
||||||
this.companyName = companyName;
|
|
||||||
this.earningsPerShare = earningsPerShare;
|
|
||||||
this.estimatedEarnings = estimatedEarnings;
|
|
||||||
this.lastTrade = lastTrade;
|
|
||||||
this.symbol = symbol;
|
this.symbol = symbol;
|
||||||
|
this.askPrice = askPrice;
|
||||||
|
this.askSize = askSize;
|
||||||
|
this.bidPrice = bidPrice;
|
||||||
|
this.bidSize = bidSize;
|
||||||
|
this.timeStamp = timeStamp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
19
test/alpaca.test.ts
Normal file
19
test/alpaca.test.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { describe, expect, test } from '@jest/globals';
|
||||||
|
import 'dotenv/config';
|
||||||
|
import { AlpacaExchange } from '../src/alpaca/exchange';
|
||||||
|
|
||||||
|
describe('Alpaca Tests', () => {
|
||||||
|
test('portfolio fetch', () => {
|
||||||
|
expect(process.env.ALPACA_API_KEY).toBeDefined();
|
||||||
|
expect(process.env.ALPACA_SECRET_KEY).toBeDefined();
|
||||||
|
const exchange = new AlpacaExchange(process.env.ALPACA_API_KEY!, process.env.ALPACA_SECRET_KEY!, true);
|
||||||
|
expect(exchange.portfolioProvider.fetchPortfolio()).resolves.toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('quote fetch', () => {
|
||||||
|
expect(process.env.ALPACA_API_KEY).toBeDefined();
|
||||||
|
expect(process.env.ALPACA_SECRET_KEY).toBeDefined();
|
||||||
|
const exchange = new AlpacaExchange(process.env.ALPACA_API_KEY!, process.env.ALPACA_SECRET_KEY!, true);
|
||||||
|
expect(exchange.quoteProvider.fetchQuote("AAPL")).resolves.toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
@ -1,7 +0,0 @@
|
|||||||
import {describe, expect, test} from '@jest/globals';
|
|
||||||
|
|
||||||
describe('sum module', () => {
|
|
||||||
test('adds 1 + 2 to equal 3', () => {
|
|
||||||
expect(1 + 2).toBe(3);
|
|
||||||
});
|
|
||||||
});
|
|
Loading…
x
Reference in New Issue
Block a user