how to cancel stop loss and take profit order when position close on binance futures with rest api - rest

I'm using Binance futures rest API for algorithmic trading. after creating a buy or sell order, I'm also creating "take profit" and "stop-loss" orders, when I look at the Binance app. it looks like regular SL/TP orders but when I close positions manually, or when any SL/TP orders executed SL/TP orders still waiting in my open orders.
But when I create SL/TP orders with the Binance app and close position (for any reason) open orders also close for the same symbol.
Here is the endpoint and parameters for creating SL/TP orders;
https://fapi.binance.com/fapi/v1/order?symbol=ETHUSDT&side=BUY&type=TAKE_PROFIT_MARKET&timestamp=12123123&closePosition=true&stopPrice=4100&workingType=MARK_PRICE&priceProtect=true
this one create a TP order for the ETHUSDT symbol but I don't know why that order doesn't cancel when the position closed.
is there any missing parameter for creating SL/TP orders?

I'm have a related issue. For your specific problem what I have noticed is that when you submit, for example, a market long position. You can follow up with a TP and SL order by setting them as TAKE_PROFIT_MARKET and STOP_MARKET respectively.
For this to work you must by in 'one-way' mode (as opposed to 'hedge' mode).
Then set the value of 'timeInForce' to 'GTE_GTC' - I couldnt see this value in the documentation but I did see that when you set an order via the UI with a TP/SL this is what is shown. Also set 'reduceOnly' to True.
Then when you close the original market order both these 'pending' orders will be removed.
Just tested that you can in fact submit all these orders in a batch (list of json) to:
POST /fapi/v1/batchOrders
batch_payload = [
{
'newClientOrderId': '467fba09-a286-43c3-a79a-32efec4be80e',
'symbol': 'ETHUSDT',
'type': 'MARKET',
'quantity': '9.059',
'side': 'SELL'
},
{
'newClientOrderId': '6925e0cb-2d86-42af-875c-877da7b5fda5',
'symbol': 'ETHUSDT',
'type': 'STOP_MARKET',
'quantity': '9.059',
'side': 'BUY',
'stopPrice': '3037.9',
'timeInForce': 'GTE_GTC',
'reduceOnly': 'True'
},
{
'newClientOrderId': '121637a9-e15a-4f44-b62d-d424fb4870e0',
'symbol': 'ETHUSDT',
'type': 'TAKE_PROFIT_MARKET',
'quantity': '9.059',
'side': 'BUY',
'stopPrice': '2748.58',
'timeInForce': 'GTE_GTC',
'reduceOnly': 'True'
}
]

By default Binance doesn't close the TAKE_PROFIT_MARKET or STOP_MARKET after position is closed.. you need to manually close those orders, you can pull the current opened orders and filter them based on the positionSide (SELL / LONG / BOTH) and origType (TAKE_PROFIT_MARKET / STOP_MARKET) and you can get the orderId for those orders and batch cancel them or cancel them one by one
const position = 'LONG' // LONG, SHORT, BOTH
axios
.get('https://fapi.binance.com/fapi/v1/openOrders', {
params: {
symbol: 'BTCUSDT'
}
})
.then(({ data }) => {
const orderIds = data
.filter(
({ positionSide, origType }) =>
positionSide === position &&
['TAKE_PROFIT_MARKET', 'STOP_MARKET'].includes(origType)
)
.map(({ orderId }) => orderId)
// Use batch cancel or cancel order one by one
console.log('orderIds', orderIds)
})

Related

Update presence member status causing presence member list to display updated user as only member

In Ably, Im using
Ably React hook
In the documentation, there is a way to update member status when monitoring what users have entered a room.
const [presenceData, updateStatus] = usePresence("your-channel-name", "initial state");
// The `updateStatus` function can be used to update the presence data for the current client
updateStatus("new status");
This is where I'm having an issue. I take the presence Data and generate a list of users like this.
const [presenceData, updateStatus] = usePresence(
channel,
{
id: user.id,
name: user.name,
isModerator: false,
},
(presenceUpdate) => {
presenceUpdate.action === "update" && console.log({ presenceUpdate });
}
So my list generates correctly. In the callback, I see that the data(presenceUpdate) is updated correctly. When a user enters the room they are displayed correctly. When I start updating the status (ie: change the isModerator flag to true), the presenceData list shows the incorrect user data. It shows the updated user twice (assuming two users are in the room).
updateStatus({...user, isModerator: true})
When using channeling with presenceMember data together, updateStatus has weird side effects.
const [channel] = useChannel("your-channel-name", (message) => {
console.log(message);
});
When you use updateStatus, are you just supposed to pass the updated member data or is there something else you need to do so your presenceMember data shows the correct information?
What Im expecting:
presenceData = [{id: 1, name: 'John', isModerator:false},{id:2, name: 'Steve', isModerator: true}]
What Im getting when I try updating Steve by setting isModerator to true:
presenceData = [{id:2, name: 'Steve', isModerator: true},{id:2, name: 'Steve', isModerator: true}]
Any ideas on what I'm doing wrong?
I figured it out. You cant update anyone else's member data besides your own. I assumed I can have one user update the status of other users but what ends up happening is everyone's status is updated with the object in updateStatus(object). To make sure you dont update other users' data property, have some check that lets you decide if you are the user that is updating your status. This way, the updateStatus function is only called for that user and not for everyone else.

Insert into relationship table using id created at user registration

I have two tables as seen below
The first table is for users and is populated via a registration form on the client side. When a new user is created, I need the second 'quotas' table to be populated with date, amount, and linked with the user id. The 'user_id' is used to pull the quotas information in a GET and display client side. I am having issues using the 'id' to populate the second table at the time of creation. I am using knex to make all queries. Would I be using join to link them in knex?
server
hydrateRouter // get all users
.route('/api/user')
.get((req, res) => {
knexInstance
.select('*')
.from('hydrate_users')
.then(results => {
res.json(results)
})
})
.post(jsonParser, (req, res, next) => { // register new users
const { username, glasses } = req.body;
const password = bcrypt.hashSync(req.body.password, 8);
const newUser = { username, password, glasses };
knexInstance
.insert(newUser)
.into('hydrate_users')
.then(user => {
res.status(201).json(user);
})
.catch(next);
})
client
export default class Register extends React.Component {
constructor(props) {
super(props);
this.state = {
username: '',
password: '',
glasses: 0
}
}
handleSubmit(event) {
event.preventDefault();
fetch('http://localhost:8000/api/user', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(this.state)
})
.then(response => response.json())
.then(responseJSON => {
this.props.history.push('/login');
})
}
server side route for displaying the water amount
hydrateRouter
.route('/api/user/waterconsumed/:user_id') // display water consumed/day
.all(requireAuth)
.get((req, res, next) => {
const {user_id} = req.params;
knexInstance
.from('hydrate_quotas')
.select('amount')
.where('user_id', user_id)
.first()
.then(water => {
res.json(water)
})
.catch(next)
})
Thank you!
Getting the id of an inserted row
So this is a common pattern in relational databases, where you can't create the egg until you have the unique id of the chicken that lays it! Clearly, the database needs to tell you how it wants to refer to the chicken.
In Postgres, you can simply use Knex's .returning function to make it explicit that you want the new row's id column returned to you after a successful insert. That'll make the first part of your query look like this:
knexInstance
.insert(newUser)
.into('users')
.returning('id')
Note: not all databases support this in the same way. In particular, if you happen to be developing locally using SQLite, it will return the number of rows affected by the query, not the id, since SQLite doesn't support SQL's RETURNING. Best is just to develop locally using Postgres to avoid nasty surprises.
Ok, so we know which chicken we're after. Now we need to make sure we've waited for the right id, then go ahead and use it:
.then(([ userId ]) => knexInstance
.insert({ user_id: userId,
date: knex.fn.now(),
amount: userConstants.INITIAL_QUOTA_AMOUNT })
.into('quotas')
)
Or however you choose to populate that second table.
Note: DATE is a SQL keyword. For that reason, it doesn't make a great column name. How about created or updated instead?
Responding with sensible data
So that's basic "I have the ID, let's insert to another table" strategy. However, you actually want to be able to respond with the user that was created... this seems like sensible API behaviour for a 201 response.
What you don't want to do is respond with the entire user record from the database, which will expose the password hash (as you're doing in your first code block from your question). Ideally, you'd probably like to respond with some UI-friendly combination of both tables.
Luckily, .returning also accepts an array argument. This allows us to pass a list of columns we'd like to respond with, reducing the risk of accidentally exposing something to the API surface that we'd rather not transmit.
const userColumns = [ 'id', 'username', 'glasses' ]
const quotaColumns = [ 'amount' ]
knexInstance
.insert(newUser)
.into('users')
.returning(userColumns)
.then(([ user]) => knexInstance
.insert({
user_id: user.id,
date: knex.fn.now(),
amount: userConstants.INITIAL_QUOTA_AMOUNT
})
.into('quotas')
.returning(quotaColumns)
.then(([ quota ]) => res.status(201)
.json({
...user,
...quota
})
)
)
Async/await for readability
These days, I'd probably avoid a promise chain like that in favour of the syntactic sugar that await provides us.
try {
const [ user ] = await knexInstance
.insert(newUser)
.into('users')
.returning(userColumns)
const [ quota ] = await knexInstance
.insert({
user_id: userId,
date: knex.fn.now(),
amount: userConstants.INITIAL_QUOTA_AMOUNT
})
.into('quotas')
.returning(quotaColumns)
res
.status(201)
.json({
...user,
...quota
})
} catch (e) {
next(Error("Something went wrong while inserting a user!"))
}
A note on transactions
There are a few assumptions here, but one big one: we assume that both inserts will be successful. Sure, we provide some error handling, but there's still the possibility that the first insert will succeed, and the second fail or time out for some reason.
Typically, we'd do multiple insertions in a transaction block. Here's how Knex handles this:
try {
const userResponse = await knexInstance.transaction(async tx => {
const [ user ] = await tx.insert(...)
const [ quota ] = await tx.insert(...)
return {
...user,
...quota
}
})
res
.status(201)
.json(userResponse)
} catch (e) {
next(Error('...'))
}
This is good general practice for multiple inserts that depend on each other, since it sets up an "all or nothing" approach: if something fails, the database will go back to its previous state.

Restrict suggestions in Algolia to postcode

In Algolia Places I want to restrict the suggestions for streets to a specific postcode. I cannot seem to get it to work however. I thought this might be how it's done, but it doesn't work.
const optionsStreet = {
appId: '...',
apiKey: '...',
container: document.querySelector('#address'),
templates: {
value: function (suggestion) {
return suggestion.name;
}
}
};
const configStreet = {
language: 'de', // Receives results in German
postcodes: ['12345'],
type: 'address'
};
const placesStreet = places(optionsStreet).configure(configStreet);
placesStreet.on('change', function resultSelected(e) {
document.querySelector('#address').value = e.suggestion.name || '';
});
There's no easy way to do what you want.
You might want to open a feature request!
In the meantime...
First option
If that's some data you can get, use the insidePolygon option to restrict the searches to the geographical area represented by the postcode(s) you're interested in.
Note that you can filter on multiple disjoint polygons.
That option is a bit cumbersome to put in place but will give you the best results, as it ensures you'll get only the hits from the area you want.
Second option
You can also fork the project and fiddle with that part of the code:
.then(content => {
const hits = content.hits.map((hit, hitIndex) =>
formatHit({
formatInputValue: controls.formatInputValue,
hit,
hitIndex,
query,
rawAnswer: content,
})
);
controls.onHits({
hits,
query,
rawAnswer: content,
});
return hits;
})
Filter content.hits for the hits that match your postcode only and you'll get your filtered suggestions.
Two recommendations:
Increase the hitsPerPage setting because you're going to be removing many results from the hits due to your postcode filter:
const placesStreet = places(options).configure({
...config,
computeQueryParams(query) {
return {...query, hitsPerPage: 100};
}
});
You'll want to fine-tune the 100 depending on what you need.
Use the arountLatLng configuration to specify a point within the postcode area you want to target, to maximize the number of hits with the correct postcode.

vue js 2 - for loop in multiple rest calls fetchData

I am trying to get wp-rest and Vuejs 2 to work together, so far things are coming along nicely apart from this one rest call that requires another request for the design to be complete. Essentially I want to be able to iterate / loop through the first request and dynamically change update the second request.
And my second question is performance, overall the rest calls are taking a bit longer to load - is there something I can do to optimize?
Context:
The first result data gives me an id, slug and title to all the posts I want to display only on the homepage as featured - through that id or slug I want to pass it to the second request - so I can pull in more information about those posts - like featured image and other meta field data.
<pre>export default {
name: 'work',
data () {
return {
loading: false,
page: null,
pagesingle: null,
error: null
}
},
created() {
this.fetchData()
},
methods: {
fetchData() {
this.$http.get('/cms/wp-json/wp/v2/pages/?slug=work&_embed')
.then(result => {
this.page = result.data
this.$http.get('/cms/wp-json/wp/v2/cases-studes/?slug=case-study-name').then(
result => this.pagesingle = result.data
);
})
}
}
}</pre>
I think you want to look at Promise.all. It will take an array of promises, wait for them all to complete, and then resolve with an array of results.
You would build your array of promises based on the array of slugs and ids in your first request. Maybe something like
const promises = result.data.articles.map((article) =>
this.$http.get(`/cms/wp-json/wp/v2/cases-studies/?slug=${encodeURIComponent(article.slug)}`)
);
Getting the results is as easy as
Promise.all(promises).then((results) => {
this.arrayOfSinglePages = results.map((result) => result.data);
});
Now your this.page has the array of id (and stuff) and this.arrayOfSinglePages has the page details for each of them in the same order.

MongoDB Social Network Adding Followers

I'm implementing a social network in MongoDB and I need to keep track of Followers and Following for each User. When I search for Users I want to display a list like Facebook with the User Name, Picture and number of Followers & Following. If I just wanted to display the User Name and Picture (info that doesn't change) it would be easy, but I also need to display the number of Followers & Following (which changes fairly regularly).
My current strategy is to embed the People a User follows into each User Document:
firstName: "Joe",
lastName: "Bloggs",
follows: [
{
_id: ObjectId("520534b81c9aac710d000002"),
profilePictureUrl: "https://pipt.s3.amazonaws.com/users/xxx.jpg",
name: "Mark Rogers",
},
{
_id: ObjectId("51f26293a5c5ea4331cb786a"),
name: "The Palace Bar",
profilePictureUrl: "https://s3-eu-west-1.amazonaws.com/businesses/xxx.jpg",
}
]
The question is - What is the best strategy to keep track of the number of Followers & Following for each User?
If I include the number of Follows / Following as part of the embedded document i.e.
follows: [
{
_id: ObjectId("520534b81c9aac710d000002"),
profilePictureUrl: "https://pipt.s3.amazonaws.com/users/xxx.jpg",
name: "Mark Rogers",
**followers: 10,**
**following: 400**
}
then every time a User follows someone requires multiple updates across all the embedded documents.
Since the consistency of this data isn't really important (i.e. Showing someone I have 10 instead of 11 followers isn't the end of the world), I can queue this update. Is this approach ok or can anyone suggest a better approach ?
You're on the right track. Think about which calculation is performed more - determining the number of followers/following or changing number of followers/following? Even if you're caching the output of the # of followers/following calculation it's still going to be performed one or two orders of magnitude more often than changing the number.
Also, think about the opposite. If you really need to display the number of followers/following for each of those users, you'll have to then do an aggregate on each load (or cache it somewhere, but you're still doing a lot of calcs).
Option 1: Cache the number of followers/following in the embedded document.
Upsides: Can display stats in O(1) time
Downsides: Requires O(N) time to follow/unfollow
Option 2: Count the number of followers/following on each page view (or cache invalidation)
Upsides: Can follow/unfollow in O(1) time
Downsides: Requires O(N) time to display
Add in the fact that follower/following stats can be eventually consistent whereas the counts have to be displayed on demand and I think it's a pretty easy decision to cache it.
I've gone ahead and implement the update followers/following based on the same strategy recommended by Mason (Option 1). Here's my code in NodeJs and Mongoose and using the AsyncJs Waterfall pattern in case anyone is interested or has any opinions. I haven't implemented queuing yet but the plan would be to farm most of this of to a queue.
async.waterfall([
function (callback) {
/** find & update the person we are following */
Model.User
.findByIdAndUpdate(id,{$inc:{followers:1}},{upsert:true,select:{fullName:1,profilePictureUrl:1,address:1,following:1,followers:1}})
.lean()
.exec(callback);
},
function (followee, callback) {
/** find & update the person doing the following */
var query = {
$inc:{following:1},
$addToSet: { follows: followee}
}
Model.User
.findByIdAndUpdate(credentials.username,query,{upsert:true,select:{fullName:1,profilePictureUrl:1,address:1,following:1,followers:1}})
.lean()
.exec(function(err,follower){
callback(err,follower,followee);
});
},
function(follower,followee,callback){
/** update the following count */
Model.User
.update({'follows._id':follower.id},{'follows.$.following':follower.following},{upsert:true,multi:true},function(err){
callback(err,followee);
});
},
function(followee,callback){
/** update the followers count */
Model.User
.update({'follows._id':followee.id},{'follows.$.followers':followee.followers},{upsert:true,multi:true},callback);
}
], function (err) {
if (err)
next(err);
else {
res.send(HTTPStatus.OK);
next();
}
});