التداول ليس مجانيًا
الاختبار الرجعي الذي يتداول مجانًا يبالغ في كل استراتيجية، وكلما تداول أكثر كذب أكثر. التكاليف الحقيقية هي عمولة الوسيط ورسوم البورصة والجهات الرقابية، وفوق ذلك كله فارق العرض والطلب الذي تعبره في كل مرة. وتُعلن عادة بـالنقاط الأساسية من القيمة المتداولة: 1 نقطة أساس تساوي 0.01%. ورحلة ذهاب وعودة بـ5 نقاط لكل اتجاه تكلف 10 نقاط، وهذا لا تنجو منه استراتيجية تربح 3 نقاط يوميًا إذا انقلبت كل يوم.
def trade_cost(notional, bps):
return abs(notional) * bps / 10000
print(trade_cost(25000, 5)) # 12.5 buying 25,000 at 5 bps
print(trade_cost(-25000, 5)) # 12.5 selling costs the same
print(trade_cost(1_000_000, 1)) # 100.0 one basis point on a millionمعدل الدوران: كم تتداول
تعتمد التكلفة على مقدار تغير المركز لا على حجمه. فإذا كان المركز جزءًا من الحساب، فإن الدوران في يوم هو التغير المطلق عن المركز السابق: abs(position[t] - position[t - 1]) بدءًا من الصفر في اليوم 0. والبقاء شراءً لا يكلف شيئًا بعد الشراء الأول؛ والانتقال من الشراء إلى البيع يتداول الحساب مرتين. ومجموع الدوران في سنة هو أول رقم يُنظر إليه في أي استراتيجية.
import numpy as np
positions = np.array([1.0, 1.0, -1.0, -1.0, 0.0]) # long, long, flip to short, short, flat
turnover = np.abs(np.diff(positions, prepend=0.0)) # day 0 starts from a flat position
print(turnover) # [1. 0. 2. 0. 1.]
print(turnover.sum()) # 4.0 accounts traded over the five daysالعوائد الصافية وتكلفة التعادل
تكلفة اليوم كجزء من الحساب هي turnover * bps / 10000، والعائد الصافي هو العائد الإجمالي ناقصها. ورقم واحد مفيد هو تكلفة التعادل: التكلفة لكل وحدة متداولة التي يصبح عندها إجمالي الربح صفرًا تمامًا، sum(gross) / sum(turnover) * 10000. قارنها بما تدفعه فعلًا. استراتيجية تعادلها 2 نقطة ميتة عمليًا، وتعادلها 40 نقطة لديها هامش.
# Gross and net returns of a rule that flips often, at 5 bps per unit traded
import numpy as np
rng = np.random.default_rng(11)
positions = np.where(rng.random(250) > 0.5, 1.0, -1.0) # a coin-flip position, flipping often
gross = rng.normal(0.0015, 0.005, size=250) # a strategy with a real daily edge before costs
turnover = np.abs(np.diff(positions, prepend=0.0))
net = gross - turnover * 5 / 10000
print(round(float(gross.sum()), 4), round(float(net.sum()), 4))
print(round(float(turnover.sum()), 1), "accounts traded;", round(float(gross.sum() / turnover.sum() * 10000), 2), "bps break-even")# The break-even cost of a small example
import numpy as np
gross = np.array([0.004, 0.002, 0.003, 0.001, 0.002])
positions = np.array([1.0, 1.0, -1.0, -1.0, 0.0])
turnover = np.abs(np.diff(positions, prepend=0.0))
breakeven = gross.sum() / turnover.sum() * 10000
print(round(float(breakeven), 2)) # 30.0 bps per unit traded
print(abs(round(float((gross - turnover * breakeven / 10000).sum()), 10))) # 0.0: the whole profit is gone- تُعلن التكاليف بالنقاط الأساسية من القيمة المتداولة:
abs(notional) * bps / 10000، نفسها للشراء والبيع. - الدوران هو
abs(تغير المركز)(الانقلاب يتداول 2)؛ العائد الصافي = الإجمالي - الدوران * bps / 10000. - تكلفة التعادل
sum(gross) / sum(turnover) * 10000تبين كم تتحمل الاستراتيجية من تكلفة؛ قارنها بالتكلفة الفعلية.
التالي: الانزلاق السعري، الفجوة بين السعر المتوقع والسعر الذي حصلت عليه.
المختبر: ما الذي يُقيَّم
- سعّر صفقة واحدة باستخدام
trade_cost25 نقطة - احسب ما جرى تداوله باستخدام
turnover25 نقطة - اخصم الفاتورة باستخدام
net_returns25 نقطة - اعثر على التكلفة التي تقضي عليها باستخدام
breakeven_bps25 نقطة