I may have an idea of a possible cause... I've been playing around with this and think the problem could be related to button placement.
When you place a button so it is flush in a corner, like this:

you may think the "anchor" cell for the button is B2. But in reality, you have to take the entire drawing into account
so you also have to account for the handles:

. In this example, the actual anchor cell is A1. And if the page refreshes or anything, then it could be moving the button to A1 instead of where you want it in B2.
I used this code to test the theory:
function getButtons() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ws = ss.getActiveSheet();
var drawings = ws.getDrawings(); //get all buttons
drawings.forEach( drawing => console.log(drawing.getContainerInfo().getAnchorRow(), drawing.getContainerInfo().getAnchorColumn())); //log its anchor cell
drawings.forEach( drawing => drawing.setPosition(2,2,0,0) ); //move it to where I want it to live
drawings.forEach( drawing => console.log(drawing.getContainerInfo().getAnchorRow(), drawing.getContainerInfo().getAnchorColumn())); //log new position
}
The first log shows the anchor cell as A1, and after moving it, it is now cell B2. This is due to the "handles" on the button.

After setting the position I want, notice the gap or 'padding' around the button:

Conclusion? This may be a factor in why some buttons may be moving unexplainably--not yet proven.
I hope that helps a little. If this isn't the cause, you could still use a similar function like the above to reset the buttons every hour or so, or onEdit, etc.