Versi percubaan algoritma sering diperlukan oleh pencipta algoritma untuk menjalankan strategi pengedaran yang berkesan di cTrader Store. Artikel ini menerangkan cara memperkenalkan batasan kepada versi percubaan cBot, indikator dan plugin pada tahap kod.
Petua
Salin algoritma utama anda untuk mencipta versi percubaan, tambahkan batasan seperti yang dijelaskan dalam panduan ini dan kemudian terbitkan percubaan di cTrader Store.
Batasan percubaan
Batasan percubaan memastikan bahawa pembeli berpotensi boleh menguji tingkah laku umum, logik, dan kualiti algoritma anda, tetapi tidak dapat meniru sepenuhnya fungsi versi berbayar.
Batasan biasa dalam kod algoritma percubaan termasuk:
Operasi demo sahaja
Operasi ujian belakang sahaja
Had keuntungan harian
Simbol dan tempoh yang dikod keras
Parameter yang dikod keras
Dan banyak lagi
cBots
Struktur kod cBot percubaan mungkin kelihatan seperti ini:
1 2 3 4 5 6 7 8 910111213141516171819202122
[Robot(AccessRights = AccessRights.None)]publicclassTest:Robot{protectedoverridevoidOnStart(){// Trial setup checks (account type, symbol, expiry, etc.)// Restrictions logic for the trial// before or around your normal trading logic.}protectedoverridevoidOnBar(){// Restrictions logic for the trial// before or around your normal trading logic.}privatevoidRunStrategy(){// Normal trading logic goes here// e.g., signal detection, risk management, order placement.}}
1 2 3 4 5 6 7 8 910111213141516171819202122
importclrclr.AddReference("cAlgo.API")# Import cAlgo API typesfromcAlgo.APIimport*# Import trading wrapper functionsfromrobot_wrapperimport*classTest():defon_start(self):# Trial setup checks (account type, symbol, expiry, etc.)# Restrictions logic for the trial# before or around your normal trading logic.passdefon_bar(self):# Restrictions logic for the trial# before or around your normal trading logic.passdefrun_strategy(self):# Normal trading logic goes here# e.g., signal detection, risk management, order placement.pass
Demo sahaja
Benarkan bot percubaan berjalan hanya pada akaun demo. Jika pengguna melampirkannya ke akaun langsung, cBot akan berhenti beroperasi.
1 2 3 4 5 6 7 8 9101112131415161718192021
[Robot(AccessRights = AccessRights.None)]publicclassTest:Robot{protectedoverridevoidOnStart(){if(Account.IsLive){Print("This trial version can be used only on demo accounts.");Stop();// Stops the cBot for real accountsreturn;}RunStrategy();// <<< Actual trading logic}privatevoidRunStrategy(){// Normal trading logic goes here// e.g., signal detection, risk management, order placement.}}
1 2 3 4 5 6 7 8 910111213141516171819
importclrclr.AddReference("cAlgo.API")# Import cAlgo API typesfromcAlgo.APIimport*# Import trading wrapper functionsfromrobot_wrapperimport*classTest():defon_start(self):ifapi.Account.IsLive:print("This trial version can be used only on demo accounts.")api.Stop()# Stops the cBot for real accountsreturnself.run_strategy()# <<< Actual trading logicdefrun_strategy(self):# Normal trading logic goes here# e.g., signal detection, risk management, order placement.pass
Ujian belakang sahaja
Benarkan cBot berfungsi hanya semasa ujian belakang. Jika pengguna cuba menggunakan algoritma untuk berdagang dalam keadaan sebenar, tiada apa yang berlaku.
1 2 3 4 5 6 7 8 9101112131415
[Robot(AccessRights = AccessRights.None)]publicclassTest:Robot{protectedoverridevoidOnStart(){if(RunningMode==RunningMode.RealTime){Print("This trial version can run only in backtesting mode.");Stop();// Stops cBotreturn;}}// Rest of your cBot logic}
1 2 3 4 5 6 7 8 91011121314
importclrclr.AddReference("cAlgo.API")# Import cAlgo API typesfromcAlgo.APIimport*# Import trading wrapper functionsfromrobot_wrapperimport*classTest():defon_start(self):ifapi.RunningMode==RunningMode.RealTime:print("This trial version can run only in backtesting mode.")api.Stop()# Stops cBotreturn# Rest of your cBot logic
Had keuntungan harian
Atur cBot untuk berhenti beroperasi sebaik sahaja keuntungan bersih harian mencapai nilai yang ditetapkan.
[Robot(AccessRights = AccessRights.None)]publicclassTest:Robot{privateconstdoubleMaxDailyProfit=20.0;protectedoverridevoidOnStart(){StopIfMaxDailyProfitReached();Positions.Closed+=_=>StopIfMaxDailyProfitReached();}privatevoidStopIfMaxDailyProfitReached(){vartodayProfit=History.Where(t=>t.ClosingTime.Date==Server.Time.Date).Sum(t=>t.NetProfit);if(todayProfit<MaxDailyProfit)return;Print("Trial limit reached: daily profit cap.");Stop();// Stops cBot}// Rest of your cBot logic}
1 2 3 4 5 6 7 8 91011121314151617181920212223
importclrclr.AddReference("cAlgo.API")# Import cAlgo API typesfromcAlgo.APIimport*# Import trading wrapper functionsfromrobot_wrapperimport*classTest():MaxDailyProfit=20.0defon_start(self):self.stop_if_max_daily_profit_reached()api.Positions.Closed+=lambda_:self.stop_if_max_daily_profit_reached()defstop_if_max_daily_profit_reached(self):todayProfit=[t.NetProfitfortinHistoryift.ClosingTime.Date==api.Server.Time.Date]iftodayProfit<self.MaxDailyProfit:returnprint("Trial limit reached: daily profit cap.")api.Stop();# Stops cBot# Rest of your cBot logic
Simbol dan tempoh yang dikod keras
Jika pengguna cuba menjalankan cBot pada simbol atau tempoh lain, tiada apa yang berlaku.
1 2 3 4 5 6 7 8 910111213141516171819202122
[Robot(AccessRights = AccessRights.None)]publicclassTest:Robot{privateconststringValidSymbolName="EURUSD";privateconststringValidTimeFrame="Hour";protectedoverridevoidOnStart(){StopIfSymbolOrTimeFrameIsInvalid();}privatevoidStopIfSymbolOrTimeFrameIsInvalid(){if(SymbolName==ValidSymbolName&&TimeFrame.Name==ValidTimeFrame)return;Print($"This trial version works only on {ValidSymbolName} {ValidTimeFrame}.");Stop();// Stops cBot}// Rest of your cBot logic}
1 2 3 4 5 6 7 8 9101112131415161718192021
importclrclr.AddReference("cAlgo.API")# Import cAlgo API typesfromcAlgo.APIimport*# Import trading wrapper functionsfromrobot_wrapperimport*classTest():ValidSymbolName="EURUSD"ValidTimeFrame="Hour"defon_start(self):self.stop_if_symbol_or_time_frame_is_invalid()defstop_if_symbol_or_time_frame_is_invalid(self):ifapi.SymbolName==self.ValidSymbolNameandapi.TimeFrame.Name==self.ValidTimeFrame:returnprint(f"This trial version works only on {ValidSymbolName}{ValidTimeFrame}.")api.Stop();# Stops cBot# Rest of your cBot logic
Parameter yang dikod keras
Kodkan cBot untuk sentiasa menggunakan pemalar dalaman yang tidak menguntungkan, seperti volum kecil atau saiz lot.
1 2 3 4 5 6 7 8 910111213
[Robot(AccessRights = AccessRights.None)]publicclassTest:Robot{// In full version, you might have:// [Parameter("Volume (lots)", DefaultValue = 0.1)]// public double VolumeInLots { get; set; }// In trial version, you can omit parameters entirely// and always use a fixed volume amount when executing trades:privateconststringTrialVolumeInLots=0.01// Rest of your cBot logic}
1 2 3 4 5 6 7 8 9101112131415161718
importclrclr.AddReference("cAlgo.API")# Import cAlgo API typesfromcAlgo.APIimport*# Import trading wrapper functionsfromrobot_wrapperimport*classTest():# In full version, you might have:# [Parameter("Volume (lots)", DefaultValue = 0.1)]# public double VolumeInLots { get; set; }# In Python algos you have to define parameters# in C# file of your algo# In trial version, you can omit parameters entirely# and always use a fixed volume amount when executing trades:TrialVolumeInLots=0.01# Rest of your cBot logic
Dagangan harian terhad
Konfigurasikan cBot untuk berhenti berdagang untuk sepanjang hari selepas bilangan dagangan tertentu.
[Robot(AccessRights = AccessRights.None)]publicclassTest:Robot{privateconstintMaxTradesPerDay=5;protectedoverridevoidOnBar(){if(IsMaxDailyTradeReached())return;// Skip trading logic if max trade number reached}privatevoidIsMaxDailyTradeReached(){vartodayTradesCount=History.Where(t=>t.ClosingTime.Date==Server.Time.Date).Count();if(todayTradesCount<MaxTradesPerDay)returnfalse;Print("Trial limit reached: maximum trades for today.");returntrue;}// Rest of your cBot logic}
1 2 3 4 5 6 7 8 910111213141516171819202122
importclrclr.AddReference("cAlgo.API")# Import cAlgo API typesfromcAlgo.APIimport*# Import trading wrapper functionsfromrobot_wrapperimport*classTest():MaxTradesPerDay=5defon_bar(self):ifself.is_max_daily_trade_reached():return# Skip trading logic if max trade number reacheddefis_max_daily_trade_reached(self):todayTradesCount=len([tfortinapi.Historyift.ClosingTime.Date==Server.Time.Date])iftodayTradesCount<self.MaxTradesPerDay:returnFalseprint(f"Trial limit reached: maximum trades for today.")returnTrue# Rest of your cBot logic
Operasi terhad masa
Kodkan cBot untuk menghantar tarikh mula yang dipautkan kepada cTID pengguna apabila ia dimulakan, dan konfigurasikan untuk berhenti berfungsi selepas tempoh tetap. Untuk mengelakkan pengguna memintas konfigurasi mula percubaan, pertimbangkan untuk menggunakan perkhidmatan API jauh atau penyelesaian selamat yang serupa.
1 2 3 4 5 6 7 8 910111213141516171819202122232425
[Robot(AccessRights = AccessRights.None)]publicclassTest:Robot{privateconstintTrialDays=5;protectedoverridevoidOnStart(){// Do the same check on other methods like OnTick, OnBar, etc...if(Server.Time>=GetTrialStartTime().AddDays(TrialDays))OnTrialExpired();}privateDateTimeGetTrialStartTime(){// Add here the logic for getting trial start time from your secure remote service}privatevoidOnTrialExpired(){Print("Your trial period has expired. Please purchase the full version.");Stop();}// Rest of your cBot logic}
1 2 3 4 5 6 7 8 91011121314151617181920212223
importclrclr.AddReference("cAlgo.API")# Import cAlgo API typesfromcAlgo.APIimport*# Import trading wrapper functionsfromrobot_wrapperimport*classTest():TrialDays=5defon_start(self):# Do the same check on other methods like on_tick, on_bar, etc...ifapi.Server.Time>=self.get_trial_start_time().AddDays(self.TrialDays):self.on_trial_expired()defget_trial_start_time(self):# Add here the logic for getting trial start time from your secure remote servicepassdefon_trial_expired(self):print("Your trial period has expired. Please purchase the full version.")api.Stop()# Rest of your cBot logic
Batasan berasaskan sesi
Benarkan cBot berdagang hanya dalam satu sesi.
1 2 3 4 5 6 7 8 91011121314
[Robot(AccessRights = AccessRights.None)]publicclassTest:Robot{protectedoverridevoidOnBar(){// Do the same check on other methods like OnTick, etc...if(!IsValidSession())return}privateboolIsValidSession()=>MarketSessions.HasFlag(MarketSession.London)// Rest of your cBot logic}
1 2 3 4 5 6 7 8 910111213141516
importclrclr.AddReference("cAlgo.API")# Import cAlgo API typesfromcAlgo.APIimport*# Import trading wrapper functionsfromrobot_wrapperimport*classTest():defon_bar(self):# Do the same check on other methods like on_tick, etc...ifself.is_valid_session()==False:returndefis_valid_session(self):returnapi.MarketSessions.HasFlag(MarketSession.London)# Rest of your cBot logic
Dagangan simulasi sahaja
Kodkan cBot untuk log di mana ia akan berdagang dan tidak melaksanakan dagangan.
1 2 3 4 5 6 7 8 91011121314151617181920
[Robot(AccessRights = AccessRights.None)]publicclassTest:Robot{protectedoverridevoidOnBar(){// Example: simple signalvarbuySignal=Bars.ClosePrices.Last(1)>Bars.OpenPrices.Last(1);if(buySignal){// In full version, this is where you would execute an order:// ExecuteMarketOrder(TradeType.Buy, SymbolName, 10000);// In the trial: only log the virtual actionPrint($"[TRIAL] Would open BUY position at {Symbol.Ask}");}}// Rest of your cBot logic}
1 2 3 4 5 6 7 8 910111213141516171819
importclrclr.AddReference("cAlgo.API")# Import cAlgo API typesfromcAlgo.APIimport*# Import trading wrapper functionsfromrobot_wrapperimport*classTest():defon_bar(self):# Example: simple signalbuySignal=api.Bars.ClosePrices.Last(1)>api.Bars.OpenPrices.Last(1)ifbuySignal:# In full version, this is where you would execute an order:# api.ExecuteMarketOrder(TradeType.Buy, api.SymbolName, 10000);# In the trial: only log the virtual actionprint(f"[TRIAL] Would open BUY position at {api.Symbol.Ask}")# Rest of your cBot logic
Indikator
Struktur kod indikator percubaan mungkin kelihatan seperti ini:
importclrclr.AddReference("cAlgo.API")# Import cAlgo API typesfromcAlgo.APIimport*# Import trading wrapper functionsfromrobot_wrapperimport*classTest():definitialize(self):# Trial setup checks go herepassdefcalculate(self,index):# Trial indicator logic goes herepass
Fungsi yang dikurangkan
Indikator percubaan melaksanakan pengiraan asas, manakala versi penuh mengandungi logik yang lebih maju.
1 2 3 4 5 6 7 8 9101112131415161718
[Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]publicclassTest:Indicator{[Output("Result", LineColor = "DodgerBlue")]publicIndicatorDataSeriesResult{get;set;}protectedoverridevoidInitialize(){}publicoverridevoidCalculate(intindex){// Trial build: simplified logic onlyResult[index]=(Bars.HighPrices[index]+Bars.LowPrices[index])/2;// Full version might add more lines, buffers, filters, etc.}}
1 2 3 4 5 6 7 8 9101112131415
importclrclr.AddReference("cAlgo.API")# Import cAlgo API typesfromcAlgo.APIimport*# Import trading wrapper functionsfromrobot_wrapperimport*classTest():definitialize(self):passdefcalculate(self,index):# Trial build: simplified logic onlyapi.Result[index]=(api.Bars.HighPrices[index]+api.Bars.LowPrices[index])/2# Full version might add more lines, buffers, filters, etc.
Simbol dan tempoh masa yang dikod keras
Kodkan indikator untuk menunjukkan output hanya apabila simbol dan tempoh masa tertentu digunakan.
[Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]publicclassTest:Indicator{[Output("Result", LineColor = "DodgerBlue")]publicIndicatorDataSeriesResult{get;set;}privateconststringValidSymbolName="EURUSD";privateconststringValidTimeFrame="Hour";protectedoverridevoidInitialize(){if(!IsSymbolAndTimeFrameValid()){Chart.DrawStaticText("symbolLimit","Trial version supports only EURUSD and GBPUSD.",VerticalAlignment.Center,HorizontalAlignment.Center,Color.Yellow);return;}}publicoverridevoidCalculate(intindex){if(!IsSymbolAndTimeFrameValid())return;// Rest of your indicator logic}privatevoidIsSymbolAndTimeFrameValid(){returnSymbolName==ValidSymbolName&&TimeFrame.Name==ValidTimeFrame;}}
importclrclr.AddReference("cAlgo.API")# Import cAlgo API typesfromcAlgo.APIimport*# Import trading wrapper functionsfromrobot_wrapperimport*classTest():ValidSymbolName="EURUSD"ValidTimeFrame="Hour"definitialize(self):ifself.is_symbol_and_time_frame_valid()==False:api.Chart.DrawStaticText("symbolLimit","Trial version supports only EURUSD and GBPUSD.",VerticalAlignment.Center,HorizontalAlignment.Center,Color.Yellow)returndefcalculate(self,index):ifself.is_symbol_and_time_frame_valid()==False:return# Rest of your indicator logicdefis_symbol_and_time_frame_valid(self):returnapi.SymbolName==self.ValidSymbolNameandapi.TimeFrame.Name==self.ValidTimeFrame
Operasi terhad masa
Kodkan indikator untuk berhenti memaparkan output sebaik sahaja ia tamat tempoh dan hanya menunjukkan mesej.
[Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]publicclassTest:Indicator{[Output("Result", LineColor = "DodgerBlue")]publicIndicatorDataSeriesResult{get;set;}protectedoverridevoidInitialize(){}publicoverridevoidCalculate(intindex){if(IsTrialExpired()){Result[index]=double.NaN;return;}// Rest of your indicator logic}privateboolIsTrialExpired(){// Here you can check if trial is expired or not// You have to store trial start time somewhere secure outside// user reach and comapre it with Server.Time// You can also let user know trial is expired by showing// a text message on chart, ex:// Chart.DrawStaticText(// "trial_expired",// "Trial expired. Please purchase the full version.",// VerticalAlignment.Center,// HorizontalAlignment.Center,// Color.Red// );}}
importclrclr.AddReference("cAlgo.API")# Import cAlgo API typesfromcAlgo.APIimport*# Import trading wrapper functionsfromrobot_wrapperimport*importmathclassTest():definitialize(self):passdefcalculate(self,index):ifself.is_trial_expired():api.Result[index]=math.nanreturn# Rest of your indicator logicdefis_trial_expired(self):# Here you can check if trial is expired or not# You have to store trial start time somewhere secure outside# user reach and comapre it with api.Server.Time# You can also let user know trial is expired by showing# a text message on chart, ex:# api.Chart.DrawStaticText(# "trial_expired",# "Trial expired. Please purchase the full version.",# VerticalAlignment.Center,# HorizontalAlignment.Center,# Color.Red# )
Plugin
Struktur kod plugin percubaan mungkin kelihatan seperti ini:
1 2 3 4 5 6 7 8 9101112
[Plugin(AccessRights = AccessRights.None)]publicclassTest:Plugin{protectedoverridevoidOnStart(){// Trial setup or logic here}protectedoverridevoidOnStop(){}}
1 2 3 4 5 6 7 8 910111213
importclrclr.AddReference("cAlgo.API")# Import cAlgo API typesfromcAlgo.APIimport*# Import trading wrapper functionsfromrobot_wrapperimport*classTest():defon_start(self):# Trial setup or logic herepassdefon_stop(self,index):pass
Fungsi yang dikurangkan
Versi percubaan termasuk hanya ciri asas, manakala versi penuh menyediakan segala-galanya.
[Plugin(AccessRights = AccessRights.None)]publicclassTest:Plugin{protectedoverridevoidOnStart(){// Use same check inside your plugin other methodsif(IsTrialExpired())OnTrialExpired();// You can also run timer and keep checking trial expiryTimer.Start(100)}protectedoverridevoidOnTimer(){if(IsTrialExpired())OnTrialExpired();}privateDateTimeIsTrialExpired(){// Here you have to check if user trial period is expired// or not, for that you have to store the trial start time// somewhere secure outside user access and compare it with// Server.Time}privatevoidOnTrialExpired(){// Do whatever you want when trial is expired hereMessageBox.Show("Trial expired");}}
importclrclr.AddReference("cAlgo.API")# Import cAlgo API typesfromcAlgo.APIimport*# Import trading wrapper functionsfromrobot_wrapperimport*classTest():defon_start(self):# Use same check inside your plugin other methodsifself.is_trial_expired():self.on_trial_expired()# You can also run timer and keep checking trial expiryTimer.Start(100)defon_timer(self,index):ifself.is_trial_expired():self.on_trial_expired()defis_trial_expired(self):# Here you have to check if user trial period is expired# or not, for that you have to store the trial start time# somewhere secure outside user access and compare it with# Server.Timedefon_trial_expired(self):# Do whatever you want when the trial has expired hereapi.MessageBox.Show("Trial expired")