2
$\begingroup$

I am trying the following code:

riskFactor = 0.815; (* Used to ammend liquidation price*)
bitmexTakerFee = 0.00075; (* 0.075% , see \
https://www.bitmex.com/app/fees*)

bitmexMarginC = Compile[{{quantity, _Real}, {leverage, _Real}},
   (1/leverage)  quantity + 2 bitmexTakerFee ,

   Parallelization -> True, RuntimeAttributes -> {Listable}, 
   CompilationTarget -> "C", RuntimeOptions -> "Speed", 
   CompilationOptions -> {"ExpressionOptimization" -> True, 
     "InlineCompiledFunctions" -> True, 
     "InlineExternalDefinitions" -> True}];



bitmexComputeLiqC = 
  Compile[{{entry, _Real}, {target, _Real}, {leverage, _Real}}, 
   entry + If[target > entry, -1, 1] riskFactor* entry/leverage,

   Parallelization -> True, RuntimeAttributes -> {Listable}, 
   CompilationTarget -> "C", RuntimeOptions -> "Speed", 
   CompilationOptions -> {"ExpressionOptimization" -> True, 
     "InlineCompiledFunctions" -> True, 
     "InlineExternalDefinitions" -> True}];



bitmexProfitC = 
  Compile[{{quantity, _Real}, {entry, _Real}, {exit, _Real} , \
{leverage, _Real}, {direction, _Real}},
   Sign@direction 100 (entry/exit) (exit/entry - 1)  leverage,

   Parallelization -> True, RuntimeAttributes -> {Listable}, 
   CompilationTarget -> "C", RuntimeOptions -> "Speed", 
   CompilationOptions -> {"ExpressionOptimization" -> True, 
     "InlineCompiledFunctions" -> True, 
     "InlineExternalDefinitions" -> True}];



pctToAbsPriceC = 
  Compile[{{sEntry, _Real}, {sTarget, _Real}, {x, _Real}},
   ((sTarget - sEntry) x/100 + sEntry),

   Parallelization -> True, RuntimeAttributes -> {Listable}, 
   CompilationTarget -> "C", RuntimeOptions -> "Speed", 
   CompilationOptions -> {"ExpressionOptimization" -> True, 
     "InlineCompiledFunctions" -> True, 
     "InlineExternalDefinitions" -> True}];



absPriceToPctC = 
  Compile[{{sEntry, _Real}, {sTarget, _Real}, {x, _Real}},
    100 (x - sEntry)/(sTarget - sEntry) ,

   Parallelization -> True, RuntimeAttributes -> {Listable}, 
   CompilationTarget -> "C", RuntimeOptions -> "Speed", 
   CompilationOptions -> {"ExpressionOptimization" -> True, 
     "InlineCompiledFunctions" -> True, 
     "InlineExternalDefinitions" -> True}];



tradeResultCC = 
  Compile[{{data, _Real, 
     1}, {sEntry, _Real}, {sTarget, _Real}, {pctEntry, _Real}, \
{pctTarget, _Real}, {pctStop, _Real}, {leverage, _Real}},
   Module[
    {
     entryWindowEndTick = Quotient[Length@ data, 4],
     dir = sTarget - sEntry,
     pctLiq = 0.0,
     entryTick = -100,
     targetTick = Length@ data*100,
     stopTick = Length@ data*100,
     liqTick = Length@ data*100,
     liqPrice = 0,
     firstTick = -100,
     result = 0,
     profit = 0.0,
     n = 1,
     min = -1
     },
    pctLiq = 
     absPriceToPctC[sEntry, sTarget, 
      bitmexComputeLiqC[pctToAbsPriceC[sEntry, sTarget, pctEntry], 
       pctToAbsPriceC[sEntry, sTarget, pctTarget], leverage]];
    While[
     Sign[First@data - pctEntry] == Sign[data[[n]] - pctEntry] && 
      n < entryWindowEndTick, n++];
    If[n == entryWindowEndTick, entryTick = -100, entryTick = n];
    If[entryTick == -100, profit = 0, (* Entry didnt reached, 
     no trade, so 0 benefit *)
     n = entryTick;
     While[
      Not[data[[n]] >= pctTarget || data[[n]] <= pctStop || 
         data[[n]] <= pctLiq] && n < Length@data, n++];
     If[n >= Length@data, targetTick = Length@data,
      If [data[[n]] >= pctTarget, targetTick = n];
      If [data[[n]] <= pctStop , stopTick = n];
      If [data[[n]] <= pctLiq , liqTick = n]
      ];
     (*Print["n = ",n];
     Print["targetTick = ",targetTick];
     Print["stopTick = ",stopTick];
     Print["liqTick = ",liqTick];*)
     min = Min[targetTick, stopTick, liqTick];
     profit = Which[
       min == targetTick,
       bitmexProfitC[leverage, 
        pctToAbsPriceC[sEntry, sTarget, pctEntry], 
        pctToAbsPriceC[sEntry, sTarget, data[[targetTick]]], leverage,
         dir],
       min == stopTick,
       (*Print["stop"];*)
       bitmexProfitC[leverage, 
        pctToAbsPriceC[sEntry, sTarget, pctEntry], 
        pctToAbsPriceC[sEntry, sTarget, data[[stopTick]]], leverage, 
        dir],
        min == liqTick,
       (*Print["liquidation"];*)
       -101,
       True,
       -9999999999 (*Cannot happen, needed for Which to compile *)
       ];
     ];
    profit
    ],


   Parallelization -> True, RuntimeAttributes -> {Listable}, 
   CompilationTarget -> "C", RuntimeOptions -> "Speed", 
   CompilationOptions -> {"ExpressionOptimization" -> True, 
     "InlineCompiledFunctions" -> True, 
     "InlineExternalDefinitions" -> True}
   ];

I've been working to make tradeResultCC compile to plain C code. However, I still get some MainEvaluate calls when I inspect it:

<< CompiledFunctionTools`
CompilePrint@tradeResultCC
(...)
139 R10 = MainEvaluate[ Hold[pctToAbsPriceC][ R0, R1, R2]]
(...)
167 R6 = MainEvaluate[ Hold[pctToAbsPriceC][ R0, R1, R2]]

I don't understand why those MainEvaluate calls are there, and how is that not inlined.

I am using Mathematica 11.2

$\endgroup$
2
  • 1
    $\begingroup$ bitmexMarginC cannot avoid MainEvaluate because bitmexTakerFee is undefined, and bitmexComputeLiqCcannot avoid it because riskFactor is undefined. If you fix those, it should work. $\endgroup$
    – QuantumDot
    Dec 23, 2019 at 20:53
  • $\begingroup$ @QuantumDot sorry, those are defined but I forgot to copy them. I have fixed the question. $\endgroup$
    – José D.
    Dec 23, 2019 at 20:59

1 Answer 1

5
$\begingroup$

The reason it doesn't work is because you are using Mathematica 11.2 which does not faithfully inline the definitions of the CompiledFunctions. Mathematica 12 has no problems with your code.

As a workaround, you can manually inline the definitions by injecting the relevant code with the help of With. I have taken the liberty of making your code work in version 11.2.

riskFactor = 0.815; (*Used to ammend liquidation price*)
bitmexTakerFee = 
  0.00075; (*0.075%,see https://www.bitmex.com/app/fees*)

bitmexMarginC = With[{bitmexTakerFee = bitmexTakerFee},
   Function[{quantity, leverage},
    (1/leverage) quantity + 2 bitmexTakerFee]
   ];

bitmexComputeLiqC = With[{riskFactor = riskFactor},
   Function[{entry, target, leverage},
    entry + If[target > entry, -1, 1] riskFactor*entry/leverage
    ]
   ];

bitmexProfitC = Function[{quantity, entry, exit, leverage, direction},
   Sign@direction 100 (entry/exit) (exit/entry - 1) leverage
   ];

pctToAbsPriceC = Function[{sEntry, sTarget, x},
   ((sTarget - sEntry) x/100 + sEntry)
   ];

absPriceToPctC = Function[{sEntry, sTarget, x},
   100 (x - sEntry)/(sTarget - sEntry)
   ];

tradeResultCC = With[
   {bitmexMarginC = bitmexMarginC, 
    bitmexComputeLiqC = bitmexComputeLiqC, 
    bitmexProfitC = bitmexProfitC, pctToAbsPriceC = pctToAbsPriceC, 
    absPriceToPctC = absPriceToPctC},
   Compile[
    {{data, _Real, 
      1}, {sEntry, _Real}, {sTarget, _Real}, {pctEntry, _Real}, \
{pctTarget, _Real}, {pctStop, _Real}, {leverage, _Real}},

    Module[
     {entryWindowEndTick = Quotient[Length@data, 4],
      dir = sTarget - sEntry,
      pctLiq = 0.0,
      entryTick = -100,
      targetTick = Length@data*100,
      stopTick = Length@data*100,
      liqTick = Length@data*100,
      liqPrice = 0,
      firstTick = -100,
      result = 0,
      profit = 0.0,
      n = 1,
      min = -1
      },

     pctLiq = 
      absPriceToPctC[sEntry, sTarget, 
       bitmexComputeLiqC[pctToAbsPriceC[sEntry, sTarget, pctEntry], 
        pctToAbsPriceC[sEntry, sTarget, pctTarget], leverage]];
     While[
      Sign[First@data - pctEntry] == Sign[data[[n]] - pctEntry] && 
       n < entryWindowEndTick, n++];
     If[n == entryWindowEndTick, entryTick = -100, entryTick = n];
     If[entryTick == -100, profit = 0,(*Entry didnt reached,no trade,
      so 0 benefit*)
      n = entryTick;
      While[
       Not[data[[n]] >= pctTarget || data[[n]] <= pctStop || 
          data[[n]] <= pctLiq] && n < Length@data, n++];
      If[n >= Length@data,
       targetTick = Length@data,
       If[data[[n]] >= pctTarget, targetTick = n];
       If[data[[n]] <= pctStop, stopTick = n];
       If[data[[n]] <= pctLiq, liqTick = n]];

      (*Print["n = ",n];
      Print["targetTick = ",targetTick];
      Print["stopTick = ",stopTick];
      Print["liqTick = ",liqTick];*)

      min = Min[targetTick, stopTick, liqTick];
      profit = Which[
        min == targetTick,
        bitmexProfitC[leverage, 
         pctToAbsPriceC[sEntry, sTarget, pctEntry], 
         pctToAbsPriceC[sEntry, sTarget, data[[targetTick]]], 
         leverage, dir],

        min == stopTick,
        (*Print["stop"];*)
        bitmexProfitC[leverage, 
         pctToAbsPriceC[sEntry, sTarget, pctEntry], 
         pctToAbsPriceC[sEntry, sTarget, data[[stopTick]]], leverage, 
         dir],

        min == liqTick,
        (*Print["liquidation"];*)
        -101,

        True,
        -9999999999 (*Cannot happen,needed for Which to compile*)];];
     profit],

    Parallelization -> True, RuntimeAttributes -> {Listable}, 
    CompilationTarget -> "C", RuntimeOptions -> "Speed", 
    CompilationOptions -> {"ExpressionOptimization" -> True, 
      "InlineCompiledFunctions" -> True, 
      "InlineExternalDefinitions" -> True}]
   ];
$\endgroup$
1
  • $\begingroup$ Thanks! That worked. I've submited an edit to your answer fixing the spacing. $\endgroup$
    – José D.
    Dec 23, 2019 at 21:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.