CTC Comet Strategy 7.2024.1 - 流星-btc-30m.txt
Copy
// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © yuth.btce.1
//@version=5
strategy("CTC Comet Strategy 7.2024.1", overlay=true, initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=10, pyramiding=100, commission_type=strategy.commission.percent,commission_value=0.05)
import TradingView/ta/7
// Parameters
trade_type = input.string("Risk %", "Trade Type", options = ["Trade %", "Risk %"], group = "Money Management")
long_percent = input.float(defval = 1, minval = 0, title = "long Percent", group = "Money Management")
short_percent = input.float(defval = 0, minval = 0, title = "Short Percent", group = "Money Management")
leverage_limit = input.float(10, title = "Leverage Limit", step = 0.1, group = "Money Management")
max_risk = input.float(5, title = "Max Risk", group = "Money Management")
bbLen = input.int(20, title = "BB Length", group = "BB")
bbMul = input.float(2, step=0.1, title = "BB Multiplier", group = "BB")
bbMaType = input.string('SMA', title = 'BB MA type', options = ['SMA','EMA', 'WMA', 'HMA'], group = "BB")
bbSdFromBasis = input.bool(false, title = 'SD From Basis', group = "BB")
atr_period = input.int(14, title = "ATR Period", group = "Main")
ma1_len = input.int(100, title = "MA Length", group = "Main")
ma2_len = input.int(120, title = "MA2 Length", group = "Main")
max_drawdown = input.float(10.0, "Maximum Drawdown %", minval=1.0, maxval=100.0, group = "Risk Management")
volatility_threshold = input.float(1.5, "Volatility Threshold", minval=0.1, group = "Risk Management")
max_hold_bars = input.int(23, "Maximum Hold Time (bars)", minval=1, group ="Risk Management")
stop_loss_percent = input.float(2.0, step = 0.5, title = "Stop Loss %", group = "Risk Management")
global_stop_loss = input.float(5.0, "Global Stop Loss %", minval=1.0, maxval=100.0, group = "Risk Management")
use_date_range = input(true, title = '----------- Use Date Range ----------', group = "Date Range")
from_time = input.time(defval = timestamp("01 Jan 2018 00:00 +0000"), title = "From Time", group = "Date Range")
to_time = input.time(defval = timestamp("31 Dec 2099 00:00 +0000"), title = "To Time", group = "Date Range")
in_date_range = use_date_range ? (time >= from_time) and (time <= to_time) : true
BB(src, length, multiplier) =>
basis = switch bbMaType
'SMA' => middle = ta.sma(src, length)
'EMA' => middle = ta.ema(src, length)
'WMA' => middle = ta.wma(src, length)
'HMA' => middle = ta.hma(src, length)
stdevVal = bbSdFromBasis ? ta.stdev(basis, length) : ta.stdev(src, length)
upper = basis + (stdevVal * multiplier)
lower = basis - (stdevVal * multiplier)
[basis, upper, lower]
[middle, upper, lower] = BB(close, bbLen, bbMul)
atr = ta.atr(atr_period)
sar = ta.sar(0.02, 0.02, 0.2)
sar_stoploss_percent = math.abs((sar - close)) / close * 100
// Calculate ema channels
ma1 = ta.ema(close, ma1_len)
ma2 = ta.ema(close, ma2_len)
maUp = close > ma1 and ma1 > ma2
maDown = close < ma1 and ma1 < ma2
plot(ma1, color=color.gray)
plot(ma2, color=color.white)
// New calculations
volatility = ta.atr(14) / close * 100 // Volatility as a percentage of price
drawdown_ = 100 * (strategy.equity - strategy.initial_capital) / strategy.initial_capital
// Dynamic stop loss calculation
dynamic_stop_loss = math.min(stop_loss_percent, volatility * 2) // Adjust multiplier as needed
// Entry conditions
long_condition = in_date_range and close > upper and close > sar and maUp and volatility < volatility_threshold
short_condition = in_date_range and close < lower and close < sar and maDown and volatility < volatility_threshold
// Exit conditions
exit_long_condition = ta.crossunder(close, middle) or ta.crossunder(close, sar) or (bar_index - strategy.opentrades.entry_bar_index(0) > max_hold_bars)
exit_short_condition = ta.crossover(close, middle) or ta.crossover(close, sar) or (bar_index - strategy.opentrades.entry_bar_index(0) > max_hold_bars)
// Count open positions
var float total_risk = 0.0
// Dynamic position sizing
var float qtyLimit = 0.
var float qtyLong = 0.
var float qtyShort = 0.
qtyLimit := math.round_to_mintick(strategy.equity / close * leverage_limit)
if trade_type == "Risk %"
qtyLong := strategy.equity * long_percent / 100 / (dynamic_stop_loss / 100) / close
qtyShort := strategy.equity * short_percent / 100 / (dynamic_stop_loss / 100) / close
else
qtyLong := strategy.equity * long_percent / 100 / close
qtyShort := strategy.equity * short_percent / 100 / close
qtyLong := math.min(qtyLong, qtyLimit)
qtyShort := math.min(qtyShort, qtyLimit)
// In the strategy execution block
if (long_condition and atr > ta.sma(atr, 100) and qtyLong > 0 and (total_risk + long_percent <= max_risk) and drawdown_ > -max_drawdown)
strategy.entry("Long " + str.tostring(strategy.opentrades + 1), strategy.long, qty=qtyLong)
total_risk := total_risk + long_percent
for i = 1 to strategy.opentrades
strategy.exit("SL " + str.tostring(i), "Long " + str.tostring(i), stop=strategy.position_avg_price * (1 - dynamic_stop_loss/100))
if (short_condition and atr > ta.sma(atr, 100) and qtyShort > 0 and (total_risk + short_percent <= max_risk) and drawdown_ > -max_drawdown)
strategy.entry("Short " + str.tostring(strategy.opentrades + 1), strategy.short, qty=qtyShort)
total_risk := total_risk + short_percent
for i = 1 to strategy.opentrades
strategy.exit("SL " + str.tostring(i), "Short " + str.tostring(i), stop=strategy.position_avg_price * (1 + dynamic_stop_loss/100))
// In the exit long block
if (exit_long_condition or exit_short_condition)
strategy.close_all()
total_risk := 0.0
// Close all positions on exit condition or if global stop loss is hit
if (exit_long_condition or exit_short_condition or drawdown_ <= -max_drawdown or strategy.openprofit / strategy.equity <= -global_stop_loss / 100)
strategy.close_all("Exit All")
total_risk := 0.0
// Plot
plot(upper, "Upper BB", color.blue)
plot(lower, "Lower BB", color.blue)
plot(middle, "Middle BB", color.orange)
plot(sar, "SAR", color.purple, style=plot.style_cross)
//Show Stats support functions
get_bg_color_grey(row) =>
_bgcolor = row % 2 == 0 ? #CACACA : #E5E5E5
get_bg_color_blue(transp=0) =>
_bgcolor = color.new(#006bb3, transp)
get_bg_color_green(transp=0) =>
_bgcolor = color.new(#A6E59B, transp)
get_bg_color_red(transp=0) =>
_bgcolor = color.new(#E59B9B, transp)
get_bg_color_lightblue(transp=0) =>
_bgcolor = color.new(#00BFFF, transp)
get_bg_color_orange(transp=0) =>
_bgcolor = color.new(#FFA500, transp)
showStats = input.bool(true, "Show Stats", group = "Information")
if showStats
var float lowestCapital = strategy.initial_capital
var float maxCapital = strategy.initial_capital
var float drawdown = 0
var float drawdownPercent = 0
var float apr = 0
var int first_trade_bar_index = 0
var float trade_days = 0
int rowsforstats = 20
table sostats = table.new(position.top_right, columns=1, rows=rowsforstats, frame_width=1, frame_color=color.black)
maxCapital := math.max(strategy.initial_capital + strategy.netprofit, maxCapital)
if (strategy.opentrades > 0)
if first_trade_bar_index == 0
first_trade_bar_index := bar_index
if first_trade_bar_index > 0
trade_days := timeframe.in_seconds() * (bar_index - first_trade_bar_index) / 60 / 60 / 24
if trade_days > 0
apr := (strategy.netprofit + strategy.openprofit) / strategy.initial_capital / trade_days * 365
lowestCapital := math.min(lowestCapital, strategy.equity)
//if strategy.openprofit < 0
// drawdown := math.max(maxCapital - strategy.equity, drawdown)
// drawdownPercent := math.max(drawdownPercent, drawdown / (maxCapital))
drawdownPercent := math.max(drawdownPercent, strategy.max_drawdown / (maxCapital))
var string _text = ""
_row = 0
table.cell(sostats, column=0, row=_row, text='CTC Comet : ' + str.tostring(syminfo.basecurrency) + '/' + str.tostring(syminfo.currency) + ' - ' + timeframe.period, text_halign=text.align_left, text_size=size.small, text_color=color.white, bgcolor=color.green)
_row := _row + 1
table.cell(sostats, column=0, row=_row, text=str.format("Trade Type : {0}", trade_type), text_halign=text.align_left, text_color=color.black, text_size=size.small, bgcolor=get_bg_color_grey(_row))
_row := _row + 1
table.cell(sostats, column=0, row=_row, text=str.format("Long % : {0, number}", long_percent), text_halign=text.align_left, text_color=color.black, text_size=size.small, bgcolor=get_bg_color_grey(_row))
_row := _row + 1
table.cell(sostats, column=0, row=_row, text=str.format("Short % : {0, number}", short_percent), text_halign=text.align_left, text_color=color.black, text_size=size.small, bgcolor=get_bg_color_grey(_row))
_row := _row + 1
table.cell(sostats, column=0, row=_row, text=str.format("Leverage Limit : {0, number}", leverage_limit), text_halign=text.align_left, text_color=color.black, text_size=size.small, bgcolor=get_bg_color_grey(_row))
_row := _row + 1
table.cell(sostats, column=0, row=_row, text=str.format("Max Risk : {0, number}", max_risk), text_halign=text.align_left, text_color=color.black, text_size=size.small, bgcolor=get_bg_color_grey(_row))
_row := _row + 1
table.cell(sostats, column=0, row=_row, text=str.format("BB Length : {0, number}", bbLen), text_halign=text.align_left, text_color=color.black, text_size=size.small, bgcolor=get_bg_color_grey(_row))
_row := _row + 1
table.cell(sostats, column=0, row=_row, text=str.format("BB Multiplier : {0, number, #.####}", bbMul), text_halign=text.align_left, text_color=color.black, text_size=size.small, bgcolor=get_bg_color_grey(_row))
_row := _row + 1
table.cell(sostats, column=0, row=_row, text=str.format("BB MA Type : {0}", bbMaType), text_halign=text.align_left, text_color=color.black, text_size=size.small, bgcolor=get_bg_color_grey(_row))
_row := _row + 1
table.cell(sostats, column=0, row=_row, text=str.format("BB SD From Basis : {0}", bbSdFromBasis), text_halign=text.align_left, text_color=color.black, text_size=size.small, bgcolor=get_bg_color_grey(_row))
_row := _row + 1
table.cell(sostats, column=0, row=_row, text=str.format("MA : {0, number}/ {1, number}", ma1_len, ma2_len), text_halign=text.align_left, text_color=color.black, text_size=size.small, bgcolor=get_bg_color_grey(_row))
_row := _row + 1
table.cell(sostats, column=0, row=_row, text=str.format('Initial Capital : {0, number, #.####}', strategy.initial_capital), text_halign=text.align_left, text_color=color.black, text_size=size.small, bgcolor=get_bg_color_grey(_row))
_row := _row + 1
table.cell(sostats, column=0, row=_row, text=str.format('Current Capital : {0, number, #.####}', strategy.equity), text_halign=text.align_left, text_color=color.black, text_size=size.small, bgcolor=get_bg_color_grey(_row))
_row := _row + 1
table.cell(sostats, column=0, row=_row, text=str.format('Drawdown : {0, number, #.####} [{1, number, percent}] ', strategy.max_drawdown, drawdownPercent), text_halign=text.align_left, text_color=color.black, text_size=size.small, bgcolor=get_bg_color_grey(_row))
_row := _row + 1
table.cell(sostats, column=0, row=_row, text=str.format('Net PnL : {0, number, #.####} [{1, number, percent}]', strategy.netprofit, (strategy.equity - strategy.initial_capital) /strategy.initial_capital), text_halign=text.align_left, text_color=color.black, text_size=size.small, bgcolor=get_bg_color_grey(_row))
_row := _row + 1
table.cell(sostats, column=0, row=_row, text=str.format('Open PnL : {0, number, #.####}', strategy.openprofit), text_halign=text.align_left, text_color=color.black, text_size=size.small, bgcolor=get_bg_color_grey(_row))
_row := _row + 1
table.cell(sostats, column=0, row=_row, text=str.format("APR : {0, number, percent}", apr), text_halign=text.align_left, text_color=color.black, text_size=size.small, bgcolor=get_bg_color_grey(_row))
_row := _row + 1
///////////////////
// MONTHLY TABLE //
showMonthlyReturns = input.bool(true, "Show Monthly Returns", group = "Information")
i_eq_to_dd = input.string("Simple Equity", "Mode", ["Simple Equity", "Compound Equity", "Drawdown"], group = "R & DD Table")
i_precision = input.int(2, "Return Precision", group = "R & DD Table")
i_headers_col = input.color(#D4D4D4, "Headers Color", group = "R & DD Table")
i_headers_text_col = input.color(color.black, "Headers Text Color", group = "R & DD Table")
i_pos_col = input.color(color.green, "Positive Color", group = "R & DD Table")
i_neg_col = input.color(color.red, "Negative Color", group = "R & DD Table")
i_zero_col = input.color(#DDDDDD, "Zero Color", group = "R & DD Table")
i_cell_text_col = input.color(color.white, "Cell Text Color", group = "R & DD Table")
// TIME {
var month_times = array.new_int(0) // Array of all month times
new_month = month(time) != month(time[1])
if(new_month or barstate.isfirst)
array.push(month_times, time)
var year_times = array.new_int(0)
new_year = year(time) != year(time[1])
if (new_year or barstate.isfirst)
array.push(year_times, time)
//}
// SIMPLE EQUITY CALCULATIONS {
// Simple equity is strictly calculated from start to end of each month/year equity. There is no compound
var monthly_simp_pnls = array.new_float(0) // Array of all monthly profits and losses
var yearly_simp_pnls = array.new_float(0)
if(i_eq_to_dd == "Simple Equity")
var initial_monthly_equity = strategy.equity // Starting equity for each month
cur_month_pnl = nz((strategy.equity - initial_monthly_equity) / initial_monthly_equity) // Current month's equity change
if(new_month or barstate.isfirst)
initial_monthly_equity := strategy.equity
array.push(monthly_simp_pnls, cur_month_pnl)
else
array.set(monthly_simp_pnls, array.size(monthly_simp_pnls) - 1, cur_month_pnl)
var initial_yearly_equity = strategy.equity
cur_year_pnl = nz((strategy.equity - initial_yearly_equity) / initial_yearly_equity)
if (new_year or barstate.isfirst)
initial_yearly_equity := strategy.equity
array.push(yearly_simp_pnls, cur_year_pnl)
else
array.set(yearly_simp_pnls, array.size(yearly_simp_pnls) - 1, cur_year_pnl)
// }
// COMPOUND EQUITY CALCULATIONS {
// Compound equity is strictly calculated based on equity state from the beginning of time until the end of each month/year equity. It shows the exact equity movement through time
var monthly_comp_pnls = array.new_float(0) // Array of all monthly profits and losses
var yearly_comp_pnls = array.new_float(0)
if(i_eq_to_dd == "Compound Equity")
var initial_equity = strategy.equity
cur_month_pnl = nz((strategy.equity - initial_equity) / initial_equity) // Current month's equity change
if(new_month or barstate.isfirst)
array.push(monthly_comp_pnls, cur_month_pnl)
else
array.set(monthly_comp_pnls, array.size(monthly_comp_pnls) - 1, cur_month_pnl)
cur_year_pnl = nz((strategy.equity - initial_equity) / initial_equity)
if (new_year or barstate.isfirst)
array.push(yearly_comp_pnls, cur_year_pnl)
else
array.set(yearly_comp_pnls, array.size(yearly_comp_pnls) - 1, cur_year_pnl)
// }
// DRAWDOWN CALCULATIONS {
// Drawdowns are calculated from highest equity to lowest trough for the month/year
var monthly_dds = array.new_float(0) // Array of all monthly drawdowns
var yearly_dds = array.new_float(0)
if (i_eq_to_dd == "Drawdown")
total_equity = strategy.equity - strategy.openprofit
var cur_month_dd = 0.0
var m_ATH = total_equity // Monthly All-Time-High (ATH). It is reset each month
m_ATH := math.max(total_equity, nz(m_ATH[1]))
m_drawdown = -math.abs(total_equity / m_ATH * 100 - 100) / 100 // Drawdown at current bar
if(m_drawdown < cur_month_dd)
cur_month_dd := m_drawdown
if(new_month or barstate.isfirst)
cur_month_dd := 0.0
m_ATH := strategy.equity - strategy.openprofit
array.push(monthly_dds, 0)
else
array.set(monthly_dds, array.size(monthly_dds) - 1, cur_month_dd)
var cur_year_dd = 0.0
var y_ATH = total_equity
y_ATH := math.max(total_equity, nz(y_ATH[1]))
y_drawdown = -math.abs(total_equity / y_ATH * 100 - 100) / 100
if(y_drawdown < cur_year_dd)
cur_year_dd := y_drawdown
if (new_year or barstate.isfirst)
cur_year_dd := 0.0
y_ATH := strategy.equity - strategy.openprofit
array.push(yearly_dds, 0)
else
array.set(yearly_dds, array.size(yearly_dds) - 1, cur_year_dd)
// }
// TABLE LOGIC {
var main_table = table(na)
table.clear(main_table, 0, 0, 13, new_year ? array.size(year_times) - 1 : array.size(year_times))
main_table := table.new(position.bottom_right, columns = 14, rows = array.size(year_times) + 1, border_width = 1)
t_set_headers() => // Sets time headers of the table
// Set month headers
table.cell(main_table, 0, 0, "", text_color = i_headers_text_col, bgcolor = i_headers_col, text_size = size.small)
table.cell(main_table, 1, 0, "Jan", text_color = i_headers_text_col, bgcolor = i_headers_col, text_size = size.small)
table.cell(main_table, 2, 0, "Feb", text_color = i_headers_text_col, bgcolor = i_headers_col, text_size = size.small)
table.cell(main_table, 3, 0, "Mar", text_color = i_headers_text_col, bgcolor = i_headers_col, text_size = size.small)
table.cell(main_table, 4, 0, "Apr", text_color = i_headers_text_col, bgcolor = i_headers_col, text_size = size.small)
table.cell(main_table, 5, 0, "May", text_color = i_headers_text_col, bgcolor = i_headers_col, text_size = size.small)
table.cell(main_table, 6, 0, "Jun", text_color = i_headers_text_col, bgcolor = i_headers_col, text_size = size.small)
table.cell(main_table, 7, 0, "Jul", text_color = i_headers_text_col, bgcolor = i_headers_col, text_size = size.small)
table.cell(main_table, 8, 0, "Aug", text_color = i_headers_text_col, bgcolor = i_headers_col, text_size = size.small)
table.cell(main_table, 9, 0, "Sep", text_color = i_headers_text_col, bgcolor = i_headers_col, text_size = size.small)
table.cell(main_table, 10, 0, "Oct", text_color = i_headers_text_col, bgcolor = i_headers_col, text_size = size.small)
table.cell(main_table, 11, 0, "Nov", text_color = i_headers_text_col, bgcolor = i_headers_col, text_size = size.small)
table.cell(main_table, 12, 0, "Dec", text_color = i_headers_text_col, bgcolor = i_headers_col, text_size = size.small)
table.cell(main_table, 13, 0, str.tostring(i_eq_to_dd), text_color = i_headers_text_col, bgcolor = i_headers_col, text_size = size.small)
// Set year headers
for i = 0 to array.size(year_times) - 1
table.cell(main_table, 0, i + 1, str.tostring(year(array.get(year_times, i))), text_color = i_headers_text_col, bgcolor = i_headers_col, text_size = size.small)
t_set_months() => // Sets inner monthly data of the table
display_array = switch i_eq_to_dd
"Simple Equity" => monthly_simp_pnls
"Compound Equity" => monthly_comp_pnls
=> monthly_dds
for i = 0 to array.size(month_times) - 1
m_row = year(array.get(month_times, i)) - year(array.get(year_times, 0)) + 1
m_col = month(array.get(month_times, i))
m_color = array.get(display_array, i) == 0 ? color.new(i_zero_col, transp = 30) : array.get(display_array, i) > 0 ? color.new(i_pos_col, transp = 30) : color.new(i_neg_col, transp = 30)
table.cell(main_table, m_col, m_row, str.tostring(math.round(array.get(display_array, i) * 100, i_precision)), bgcolor = m_color, text_color = i_cell_text_col, text_size = size.small)
t_set_years() => // Sets inner yearly data of the table
display_array = switch i_eq_to_dd
"Simple Equity" => yearly_simp_pnls
"Compound Equity" => yearly_comp_pnls
=> yearly_dds
for i = 0 to array.size(year_times) - 1
y_color = array.get(display_array, i) == 0 ? color.new(i_zero_col, transp = 30) : array.get(display_array, i) > 0 ? color.new(i_pos_col, transp = 20) : color.new(i_neg_col, transp = 20)
table.cell(main_table, 13, i + 1, str.tostring(math.round(array.get(display_array, i) * 100, i_precision)), bgcolor = y_color, text_color = i_cell_text_col, text_size = size.small)
if showMonthlyReturns
t_set_headers()
t_set_months()
t_set_years()
Show all 399 lines