How to Use Custom MAPE Loss Function in XGBoost

It is a regression problem to predict some sales volume based on some features (floats). From reading a few documentations, I understood if I am to use my own loss function to minimise (MAPE, for my example), then I have to supply the first and second derivatives of the loss to the xgboost trainer. This is my sample code.

import xgboost, numpy, pandas

def mape_grad(y_pred:numpy.ndarray, y_true:numpy.ndarray)->Tuple[numpy.ndarray]:
    Calculate the gradient and hessian of mean absolute percentage loss 
    from predicted and true values 
    gradients=numpy.array(object=list(map(lambda p:1 if p else -1, y_pred>y_true)))/samples
    return gradients, hessian

# Data acquisition as pandas dataframe not shown in detail. Features and target label are 
# stored in the dataframe train

data_dmatrix=xgboost.DMatrix(data=train.drop(labels=label, axis=1), label=train[label])
params = {'colsample_bytree': 0.3,'learning_rate': 0.1, 'max_depth': 5, 'alpha': 10}

# This throws error
model=xgboost.train(params=params, dtrain=data_dmatrix, obj=mape_grad)

The error says

TypeError: ‘>’ not supported between instances of ‘float’ and ‘DMatrix’

So I am not entirely clear about how exactly the mape_grad function is used by the call to train, i.e. what parameters does it pass and what does it expect in return. Any help around how to make this work will be appreciated. I expected the whole thing to work somewhat like how I define custom loss functions in tensorflow, so I may be carrying some assumptions that are not true in xgb.

Related, I can also see that the param dictionary in call to train can contain the objective function, as well as the keyword argument obj. ls there any difference between these two? Where to put my mape_grad function so that XGB can use it?

If it is important, I am running xgboost 1.3.3 on python3.6

Take a look at the examples at and