270 lines
No EOL
8.2 KiB
MQL5
270 lines
No EOL
8.2 KiB
MQL5
#ifndef LOT_CALC_MQH
|
|
#define LOT_CALC_MQH
|
|
|
|
#include "../setting.mqh"
|
|
#define RIGAL_MOD_3
|
|
//#define RIGAL_MOD_4
|
|
|
|
class calc_lot {
|
|
private:
|
|
static bool is_lvl1 ( setting_t *settings, int order_count ) {
|
|
return settings.multi_lots_level1 != 0
|
|
&& order_count >= settings.multi_lots_level1;
|
|
}
|
|
|
|
static bool is_lvl2 ( setting_t *settings, int order_count ) {
|
|
return settings.multi_lots_level2 != 0
|
|
&& is_lvl1 ( settings, order_count )
|
|
&& order_count >= settings.multi_lots_level2;
|
|
}
|
|
|
|
static bool is_lvl3 ( setting_t *settings, int order_count ) {
|
|
return settings.multi_lots_level3 != 0
|
|
&& is_lvl2 ( settings, order_count )
|
|
&& order_count >= settings.multi_lots_level3;
|
|
}
|
|
|
|
static bool is_lvl4 ( setting_t *settings, int order_count ) {
|
|
return settings.mult4 != 0
|
|
&& is_lvl3 ( settings, order_count )
|
|
&& order_count >= settings.mult4;
|
|
}
|
|
|
|
static double get_factor ( setting_t *settings,
|
|
int lvl ) {
|
|
double result = 1.0;
|
|
|
|
if ( settings.mult_stop != 0
|
|
&& settings.mult_stop < lvl ) {
|
|
lvl = settings.mult_stop;
|
|
}
|
|
|
|
if ( is_lvl4 ( settings, lvl ) ) {
|
|
result = get_factor ( settings, lvl - ( lvl - settings.mult4 + 1 ) );
|
|
|
|
int count = lvl + 1 - settings.mult4;
|
|
|
|
for ( int i = 0; i < count; i++ ) {
|
|
result += settings.mult4_add;
|
|
}
|
|
} else if ( is_lvl3 ( settings, lvl ) ) {
|
|
result = get_factor ( settings, lvl - ( lvl - settings.multi_lots_level3 + 1 ) );
|
|
|
|
int count = lvl + 1 - settings.multi_lots_level3;
|
|
|
|
for ( int i = 0; i < count; i++ ) {
|
|
result += settings.multi_lots_level3_corr;
|
|
}
|
|
} else if ( is_lvl2 ( settings, lvl ) ) {
|
|
result = get_factor ( settings, lvl - ( lvl - settings.multi_lots_level2 + 1 ) );
|
|
|
|
int count = lvl + 1 - settings.multi_lots_level2;
|
|
|
|
for ( int i = 0; i < count; i++ ) {
|
|
result += settings.multi_lots_level2_corr;
|
|
}
|
|
} else if ( is_lvl1 ( settings, lvl ) ) {
|
|
result = settings.multi_lots_factor;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static double get_for_gap_control ( setting_t *settings,
|
|
enum_order_operation_type order_type,
|
|
int lvl,
|
|
double last_lot,
|
|
double last_price,
|
|
double price ) {
|
|
double step_p = layer_market::to_points ( calc_grid_step::get ( settings, lvl ) );
|
|
double distance_p = tool_order::get_distance ( order_type, price, last_price );
|
|
double lot_factor = get_factor ( settings, lvl );
|
|
|
|
if ( !calc_gap::is_gap ( settings, order_type, order_type, distance_p, step_p ) ) {
|
|
return last_lot * lot_factor;
|
|
}
|
|
|
|
// TODO: print on every calc lot
|
|
//log_info_k ( _msg_key, StringFormat ( SRC_HANDLER_BASE_DETECT_GAP, dtos ( last_price ), dtos ( price ), dtos ( c_order::get_distance ( _order_type, price, last_price ) ) ) );
|
|
double gap_factor = lot_factor * ( ( distance_p - step_p ) / step_p ) * settings.gap_lot_koef;
|
|
double tripple_last_lot = last_lot * settings.gap_last_order_koef;
|
|
double result = last_lot * ( lot_factor + gap_factor );
|
|
return tripple_last_lot < result ? tripple_last_lot : result;
|
|
}
|
|
|
|
static double calc_lot_by_balance ( double min_lot, double currency_by_001_lot, double currency, int truncate_count, double market_lot_min, bool warning )
|
|
{
|
|
double sum=(currency - ((NotUsedCurrency>currency)?0:NotUsedCurrency) )*(UsedCurrencyPercent/100.0);
|
|
double koaf = sum / currency_by_001_lot;
|
|
double result = MathFloor(koaf)*0.01;
|
|
|
|
if ( CP(result,0.01) < market_lot_min)
|
|
{
|
|
if (warning)
|
|
{
|
|
log_warning( StringFormat(SRC_HANDLER_BASE_NOT_GOOD_LOT_OPEN_MIN, sum, layer_account::currency() , koaf*0.01, market_lot_min, market_lot_min));
|
|
}
|
|
return market_lot_min;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
static double get_base_lot ( setting_t *settings, layer_order_setting *settings_ptr, int lvl, bool warning )
|
|
{
|
|
if ( !settings.is_testing && lvl != 1 )
|
|
{
|
|
if (layer_order::get_min ( settings_ptr)!=NULL)
|
|
return layer_order::get_min ( settings_ptr ).lot;
|
|
}
|
|
|
|
return settings.currency_for_001_lot == 0 ?
|
|
settings.lots :
|
|
calc_lot_by_balance ( settings.lots,
|
|
settings.currency_for_001_lot,
|
|
settings.is_testing ? settings.testing_balance : (UseBalanceForMM?kernel_account::balance():kernel_account::equity()),
|
|
settings.lot_exp,
|
|
settings.is_testing ? settings.testing_layer_market_lot_min : layer_market::lot_min(), warning);
|
|
}
|
|
|
|
static double get_by_min_order ( setting_t *settings,
|
|
layer_order_setting *order_layer_settings_ptr,
|
|
int lvl,
|
|
enum_gap_control_type control_type,
|
|
double price,
|
|
double first_lot ) {
|
|
#ifdef RIGAL_MOD_3
|
|
////--- Rigal
|
|
double result = settings.test_min_lot > DBL_EPSILON ? settings.test_min_lot : first_lot;
|
|
////---
|
|
#else //RIGAL_MOD_3
|
|
double result = first_lot;
|
|
#endif //RIGAL_MOD_3
|
|
|
|
switch ( control_type ) {
|
|
case no_gap:
|
|
case op_stop:
|
|
result *= get_factor ( settings, lvl );
|
|
break;
|
|
|
|
case inc_lot:
|
|
//result = get_for_gap_control ( settings, settings_ptr.order_type, count + 1, result, open_prices[count - 1], price );
|
|
break;
|
|
}
|
|
#ifdef RIGAL_MOD_3
|
|
////--- Rigal
|
|
if(settings.test_min_lot > DBL_EPSILON)
|
|
result = first_lot / settings.test_min_lot * NormalizeDouble(result, settings.lot_exp);
|
|
////---
|
|
#endif //RIGAL_MOD_3
|
|
|
|
return result;
|
|
}
|
|
|
|
static double get_by_last_order ( setting_t *settings,
|
|
layer_order_setting *settings_ptr,
|
|
int lvl,
|
|
enum_gap_control_type control_type,
|
|
double price,
|
|
double first_lot ) {
|
|
#ifdef RIGAL_MOD_3
|
|
////--- Rigal
|
|
double result = settings.test_min_lot > DBL_EPSILON ? settings.test_min_lot : first_lot;
|
|
////---
|
|
#else //RIGAL_MOD_3
|
|
double result = first_lot;
|
|
#endif //RIGAL_MOD_3
|
|
|
|
switch ( control_type ) {
|
|
case no_gap:
|
|
case op_stop:
|
|
for ( int i = 1; i < lvl; i++ ) {
|
|
result *= get_factor ( settings, i + 1 );
|
|
}
|
|
|
|
break;
|
|
|
|
case inc_lot: {
|
|
int count = 0;
|
|
double open_prices[];
|
|
|
|
list<c_order *> *orders = layer_order::get ( settings_ptr );
|
|
ArrayResize ( open_prices, orders.count );
|
|
LIST_FOREACH ( orders, c_order *, item, {
|
|
count += 1;
|
|
open_prices[count - 1] = item.open_price;
|
|
} );
|
|
|
|
if ( count == 0 ) {
|
|
break;
|
|
}
|
|
|
|
for ( int i = 1; i < count; i++ ) {
|
|
result = get_for_gap_control ( settings, settings_ptr.order_type, i + 1, result, open_prices[i - 1], open_prices[i] );
|
|
}
|
|
|
|
result = get_for_gap_control ( settings, settings_ptr.order_type, count + 1, result, open_prices[count - 1], price );
|
|
break;
|
|
}
|
|
}
|
|
#ifdef RIGAL_MOD_3
|
|
////--- Rigal
|
|
if(settings.test_min_lot > DBL_EPSILON)
|
|
result = first_lot / settings.test_min_lot * NormalizeDouble(result, settings.lot_exp);
|
|
////---
|
|
#endif //RIGAL_MOD_3
|
|
return result;
|
|
}
|
|
|
|
public:
|
|
static double get ( setting_t *settings,
|
|
layer_order_setting *settings_ptr,
|
|
int lvl,
|
|
enum_gap_control_type control_type,
|
|
double price , bool warning) {
|
|
double base_lot = get_base_lot ( settings,
|
|
settings_ptr,
|
|
lvl, warning );
|
|
#ifdef RIGAL_MOD_4
|
|
//--- Rigal
|
|
double result = settings.test_min_lot > DBL_EPSILON ? settings.test_min_lot : base_lot;
|
|
//---
|
|
#else //RIGAL_MOD_4
|
|
double result = base_lot;
|
|
#endif //RIGAL_MOD_4
|
|
|
|
if ( lvl != 1 ) {
|
|
result = settings.mult_type == calc_lot_type_last_order ?
|
|
get_by_last_order ( settings,
|
|
settings_ptr,
|
|
lvl,
|
|
control_type,
|
|
price,
|
|
result ) :
|
|
get_by_min_order ( settings,
|
|
settings_ptr,
|
|
lvl,
|
|
control_type,
|
|
price,
|
|
result );
|
|
}
|
|
#ifdef RIGAL_MOD_4
|
|
//--- Rigal
|
|
if(settings.test_min_lot > DBL_EPSILON)
|
|
//--- Capteen
|
|
//result = first_lot / settings.test_min_lot * NormalizeDouble(result, settings.lot_exp);
|
|
result = base_lot / settings.test_min_lot * NormalizeDouble(result, settings.lot_exp);
|
|
//---
|
|
#endif //RIGAL_MOD_4
|
|
if ( settings.max_lot != 0.00 ) {
|
|
double max_lot = settings.max_lot * base_lot;
|
|
|
|
if ( max_lot < result ) {
|
|
result = max_lot;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
};
|
|
};
|
|
|
|
#endif |