initial load
This commit is contained in:
parent
8d8dd61dbf
commit
d1d902f91a
354
index.js
Normal file
354
index.js
Normal file
@ -0,0 +1,354 @@
|
||||
const express = require('express')
|
||||
var cors = require('cors')
|
||||
var fs = require('fs')
|
||||
var morgan = require('morgan')
|
||||
var path = require('path')
|
||||
const app = express()
|
||||
const port = 3000
|
||||
const host = "0.0.0.0"
|
||||
|
||||
|
||||
var accessLogStream = fs.createWriteStream(path.join(__dirname, 'access.log'), { flags: 'a' })
|
||||
|
||||
app.use(morgan('combined', { stream: accessLogStream }))
|
||||
|
||||
const axios = require('axios').default;
|
||||
|
||||
|
||||
const APIURL = 'https://api-fxpractice.oanda.com/v3'
|
||||
const accounts = {
|
||||
'1': {
|
||||
'ACCT': '101-001-8005237-001',
|
||||
'APIKEY': '85397a3ddc7b96ef57b90c9feda6d410-18f0f2b634f9f05533d2c20046bb79df'
|
||||
},
|
||||
'2': {
|
||||
'APIKEY': 'b954456a3f4ac735de2555e1af50abf7-ed83ace2f9fb86412b76608daefc73a5',
|
||||
'ACCT': '101-001-23367262-002'
|
||||
},
|
||||
'3': {
|
||||
'APIKEY': 'd4ea6095fe8017841279416437520aee-fa23a0556fb501520ceedbff5f405267',
|
||||
'ACCT': '101-002-26241098-001'
|
||||
}
|
||||
}
|
||||
|
||||
async function getTrades(acct_id, api_key) {
|
||||
try {
|
||||
const response = await axios.request({
|
||||
url: `${APIURL}/accounts/${acct_id}/openTrades`,
|
||||
method: 'get',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${api_key}`
|
||||
}
|
||||
});
|
||||
return (response)
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
async function getTradesByInstrument(acct_id, api_key, instrument) {
|
||||
try {
|
||||
const response = await axios.request({
|
||||
url: `${APIURL}/accounts/${acct_id}/trades?instrument=${instrument}`,
|
||||
method: 'get',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${api_key}`
|
||||
}
|
||||
});
|
||||
console.log(response)
|
||||
if (response.data.trades.length == 0) {
|
||||
return
|
||||
} else {
|
||||
|
||||
return (response.data.trades[0])
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
async function getPositions(acct_id, api_key) {
|
||||
try {
|
||||
const response = await axios.request({
|
||||
url: `${APIURL}/accounts/${acct_id}/openPositions`,
|
||||
method: 'get',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${api_key}`
|
||||
}
|
||||
});
|
||||
return (response);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
async function order(acct_id, api_key, instrument, quantity) {
|
||||
try {
|
||||
|
||||
|
||||
let dist = "0.005"
|
||||
let pdist = "0.005"
|
||||
|
||||
if (instrument.includes("JPY")) {
|
||||
dist = "0.5"
|
||||
pdist = "0.5"
|
||||
}
|
||||
|
||||
data = {
|
||||
"order": {
|
||||
"trailingStopLossOnFill": {
|
||||
"timeInForce": "GTC",
|
||||
"distance": dist
|
||||
},
|
||||
/*"takeProfitOnFill": {
|
||||
"distance": pdist
|
||||
},*/
|
||||
"timeInForce": "FOK",
|
||||
"instrument": instrument,
|
||||
"units": quantity,
|
||||
"type": "MARKET",
|
||||
"positionFill": "DEFAULT"
|
||||
}
|
||||
};
|
||||
const response = await axios.request({
|
||||
url: `${APIURL}/accounts/${acct_id}/orders`,
|
||||
method: 'post',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${api_key}`
|
||||
},
|
||||
data: data
|
||||
});
|
||||
console.log(data)
|
||||
return (response)
|
||||
/*try {
|
||||
delta = response.data.orderFillTransaction.price * .00164;
|
||||
price = response.data.orderFillTransaction.price;
|
||||
units = response.data.orderFillTransaction.units;
|
||||
pres = price.toString().split('.')[1].length
|
||||
if (units > 0) {
|
||||
price = price - delta;
|
||||
} else {
|
||||
price = price + delta
|
||||
}
|
||||
return await stopLoss(acct_id, api_key, response.data.orderFillTransaction.id, Number(price).toFixed(pres).toString())
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
return (error)
|
||||
}*/
|
||||
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
async function closeOrder(acct_id, api_key, tradeID) {
|
||||
try {
|
||||
const response = await axios.request({
|
||||
url: `${APIURL}/accounts/${acct_id}/trades/${tradeID}/close`,
|
||||
method: 'put',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${api_key}`
|
||||
},
|
||||
});
|
||||
console.log(response.data);
|
||||
return (response);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async function trailingStopLoss(acct_id, api_key, instrument) {
|
||||
const trade = await getTradesByInstrument(acct_id, api_key, instrument)
|
||||
const tradeID = trade.id;
|
||||
console.log(tradeID);
|
||||
if (!tradeID) {
|
||||
return
|
||||
}
|
||||
dist = "0.00164"
|
||||
if (instrument.includes("JPY")) {
|
||||
dist = "0.16"
|
||||
}
|
||||
try {
|
||||
data = {
|
||||
"trailingStopLoss": {
|
||||
"timeInForce": "GTC",
|
||||
"distance": dist
|
||||
}
|
||||
};
|
||||
const response = await axios.request({
|
||||
url: `${APIURL}/accounts/${acct_id}/trades/${tradeID}/orders`,
|
||||
method: 'put',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${api_key}`
|
||||
},
|
||||
data: data
|
||||
});
|
||||
console.log(data)
|
||||
console.log(response.data);
|
||||
return (response);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async function stopLoss(acct_id, api_key, tradeID, price) {
|
||||
try {
|
||||
data = {
|
||||
"stopLoss": {
|
||||
"timeInForce": "GTC",
|
||||
"distance": "0.30"
|
||||
//"price": price
|
||||
}
|
||||
};
|
||||
const response = await axios.request({
|
||||
url: `${APIURL}/accounts/${acct_id}/trades/${tradeID}/orders`,
|
||||
method: 'put',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${api_key}`
|
||||
},
|
||||
data: data
|
||||
});
|
||||
console.log(data)
|
||||
console.log(response.data);
|
||||
return (response);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async function takeProfit(acct_id, api_key, tradeID, dist) {
|
||||
try {
|
||||
data = {
|
||||
"takeProfit": {
|
||||
"timeInForce": "GTC",
|
||||
"distance": dist
|
||||
}
|
||||
};
|
||||
const response = await axios.request({
|
||||
url: `${APIURL}/accounts/${acct_id}/trades/${tradeID}/orders`,
|
||||
method: 'put',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${api_key}`
|
||||
},
|
||||
data: data
|
||||
});
|
||||
return (response);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
app.get('/closeAll', async (req, res) => {
|
||||
|
||||
for (account of Object.keys(accounts)) {
|
||||
let trades = await getTrades(accounts[account]['ACCT'], accounts[account]['APIKEY'])
|
||||
for (const t of trades.data['trades']) {
|
||||
await closeOrder(accounts[account]['ACCT'], accounts[account]['APIKEY'], t['id'])
|
||||
}
|
||||
}
|
||||
|
||||
res.json('done')
|
||||
})
|
||||
|
||||
|
||||
app.get('/tradesData', async (req, res) => {
|
||||
|
||||
let r = [];
|
||||
for (account of Object.keys(accounts)) {
|
||||
let response = await getTrades(accounts[account]['ACCT'], accounts[account]['APIKEY'])
|
||||
try {
|
||||
//Object.(response.data['trades']).forEach(([a, t]) =>{
|
||||
response.data['trades'].forEach(( t) =>{
|
||||
|
||||
t["Account"] = account;
|
||||
delete t['lastTransactionID'];
|
||||
delete t['trailingStopLossOrder'];
|
||||
console.log(t);
|
||||
r.push(t)
|
||||
});
|
||||
|
||||
} catch(error) {
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
res.header('Access-Control-Allow-Origin', '*')
|
||||
res.json(r)
|
||||
})
|
||||
|
||||
|
||||
app.get('/trades', async (req, res) => {
|
||||
|
||||
let r = {}
|
||||
for (account of Object.keys(accounts)) {
|
||||
let response = await getTrades(accounts[account]['ACCT'], accounts[account]['APIKEY'])
|
||||
try {
|
||||
r[account] = response.data;
|
||||
} catch(error) {
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
res.header('Access-Control-Allow-Origin', '*')
|
||||
res.json(r)
|
||||
})
|
||||
app.get('/trailingStop/:instrument', async (req, res) => {
|
||||
const response = await trailingStopLoss(ACCT, APIKEY, req.params.instrument);
|
||||
console.log(response);
|
||||
res.header('Access-Control-Allow-Origin', '*')
|
||||
res.json(response.data)
|
||||
})
|
||||
app.get('/tradesByInstrument/:instrument', async (req, res) => {
|
||||
res.header('Access-Control-Allow-Origin', '*')
|
||||
res.json(await getTradesByInstrument(ACCT, APIKEY, req.params.instrument))
|
||||
})
|
||||
app.get('/order/:instrument/:quantity', async (req, res) => {
|
||||
|
||||
|
||||
r = {};
|
||||
/*td = await getTradesByInstrument(accounts['1']['ACCT'], accounts['1']['APIKEY'], req.params.instrument);
|
||||
if (td) {
|
||||
|
||||
if (td["initialUnits"] != req.params.quantity) {
|
||||
let dist = "0.005"
|
||||
if (req.params.instrument.includes("JPY")) {
|
||||
let dist = "0.5"
|
||||
}
|
||||
await takeProfit(accounts['1']['ACCT'], accounts['1']['APIKEY'], td["id"], dist)
|
||||
}
|
||||
} else {
|
||||
response = await order(accounts['1']['ACCT'], accounts['1']['APIKEY'], req.params.instrument, req.params.quantity);
|
||||
}*/
|
||||
/*td = await getTradesByInstrument(accounts['2']['ACCT'], accounts['2']['APIKEY'], req.params.instrument);
|
||||
if (td) {
|
||||
|
||||
if (td["initialUnits"] != req.params.quantity) {
|
||||
let dist = "0.005"
|
||||
if (req.params.instrument.includes("JPY")) {
|
||||
|
||||
let dist = "0.5"
|
||||
}
|
||||
await takeProfit(accounts['2']['ACCT'], accounts['2']['APIKEY'], td["id"], dist)
|
||||
}
|
||||
} else {
|
||||
|
||||
response = await order(accounts['2']['ACCT'], accounts['2']['APIKEY'], req.params.instrument, req.params.quantity);
|
||||
} */
|
||||
for (account of Object.keys(accounts)) {
|
||||
response = await order(accounts[account]['ACCT'], accounts[account]['APIKEY'], req.params.instrument, req.params.quantity);
|
||||
}
|
||||
|
||||
|
||||
res.header('Access-Control-Allow-Origin', '*')
|
||||
|
||||
|
||||
res.json("ok")
|
||||
|
||||
})
|
||||
|
||||
app.listen(port, host, () => {
|
||||
console.log(`osapi started`);
|
||||
})
|
||||
17
package.json
Normal file
17
package.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "osapi",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"axios": "^1.4.0",
|
||||
"cors": "^2.8.5",
|
||||
"express": "^4.18.2",
|
||||
"morgan": "^1.10.0"
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user